· 10 years ago · Jan 17, 2016, 11:54 PM
1/************************************************************************
2 Tethealla Login Server
3 Copyright (C) 2008 Terry Chatman Jr.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 3 as
7 published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16************************************************************************/
17
18
19// Notes:
20//
21// - Limit to 40 guild cards for now.
22//
23
24#define NO_SQL
25#define NO_CONNECT_TEST
26
27#define SOCKET_ERROR -1
28
29//#include <windows.h>
30#include <sys/select.h>
31#include <sys/socket.h>
32#include <netinet/in.h>
33#include <netinet/ip.h>
34#include <netdb.h>
35
36#include <stdarg.h>
37
38#include <stdlib.h>
39
40#include <errno.h>
41
42#include <stdio.h>
43#include <string.h>
44#include <time.h>
45
46#ifndef NO_SQL
47#include <mysql.h>
48#endif
49#include <md5.h>
50
51#include "resource.h"
52#include "pso_crypt.h"
53#include "bbtable.h"
54#include "prs.cpp"
55
56#define max(a,b) (a>b?a:b)
57
58#define tchar char
59
60 /* The Itoa code is in the puiblic domain */
61 char *_itoa(int value, char* str, int radix) {
62 static char dig[] =
63 "0123456789"
64 "abcdefghijklmnopqrstuvwxyz";
65 int n = 0, neg = 0;
66 unsigned int v;
67 char* p, *q;
68 char c;
69 if (radix == 10 && value < 0) {
70 value = -value;
71 neg = 1;
72 }
73 v = value;
74 do {
75 str[n++] = dig[v%radix];
76 v /= radix;
77 } while (v);
78 if (neg)
79 str[n++] = '-';
80 str[n] = '\0';
81 for (p = str, q = p + n/2; p != q; ++p, --q)
82 c = *p, *p = *q, *q = c;
83 return str;
84 }
85
86 void _strupr(char *p)
87{
88 while(*p)
89 {
90 *p=toupper(p);
91 p++;
92 }
93}
94
95#define MAX_SIMULTANEOUS_CONNECTIONS 6
96#define LOGIN_COMPILED_MAX_CONNECTIONS 300
97#define SHIP_COMPILED_MAX_CONNECTIONS 50
98#define MAX_EB02 800000
99#define SERVER_VERSION "0.048"
100#define MAX_ACCOUNTS 2000
101#define MAX_DRESS_FLAGS 500
102#define DRESS_FLAG_EXPIRY 7200
103
104const char *PSO_CLIENT_VER_STRING = "TethVer12510";
105#define PSO_CLIENT_VER 0x41
106
107//#define USEADDR_ANY
108#define DEBUG_OUTPUT
109#define TCP_BUFFER_SIZE 64000
110#define PACKET_BUFFER_SIZE ( TCP_BUFFER_SIZE * 16 )
111
112#define SEND_PACKET_03 0x00 // Done
113#define SEND_PACKET_E6 0x01 // Done
114#define SEND_PACKET_E2 0x02 // Done
115#define SEND_PACKET_E5 0x03 // Done
116#define SEND_PACKET_E8 0x04 // Done
117#define SEND_PACKET_DC 0x05 // Done
118#define SEND_PACKET_EB 0x06 // Done
119#define SEND_PACKET_E4 0x07 // Done
120#define SEND_PACKET_B1 0x08
121#define SEND_PACKET_A0 0x09
122#define RECEIVE_PACKET_93 0x0A
123#define MAX_SENDCHECK 0x0B
124
125#define CLASS_HUMAR 0x00
126#define CLASS_HUNEWEARL 0x01
127#define CLASS_HUCAST 0x02
128#define CLASS_RAMAR 0x03
129#define CLASS_RACAST 0x04
130#define CLASS_RACASEAL 0x05
131#define CLASS_FOMARL 0x06
132#define CLASS_FONEWM 0x07
133#define CLASS_FONEWEARL 0x08
134#define CLASS_HUCASEAL 0x09
135#define CLASS_FOMAR 0x0A
136#define CLASS_RAMARL 0x0B
137#define CLASS_MAX 0x0C
138
139struct timeval select_timeout = {
140 0,
141 5000
142};
143
144/* functions */
145
146void send_to_server(int sock, char* packet);
147int receive_from_server(int sock, char* packet);
148void debug(char *fmt, ...);
149void debug_perror(char * msg);
150void tcp_listen (int sockfd);
151int tcp_accept (int sockfd, struct sockaddr *client_addr, int *addr_len );
152int tcp_sock_connect(char* dest_addr, int port);
153int tcp_sock_open(struct in_addr ip, int port);
154
155/* Ship Packets */
156
157unsigned char ShipPacket00[] = {
158 0x00, 0x00, 0x3F, 0x01, 0x03, 0x04, 0x19, 0x55, 0x54, 0x65, 0x74, 0x68, 0x65, 0x61, 0x6C, 0x6C,
159 0x61, 0x20, 0x4C, 0x6F, 0x67, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164};
165
166/* Start Encryption Packet */
167
168unsigned char Packet03[] = {
169 0xC8, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x68, 0x61, 0x6E, 0x74, 0x61, 0x73, 0x79,
170 0x20, 0x53, 0x74, 0x61, 0x72, 0x20, 0x4F, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x42, 0x6C, 0x75,
171 0x65, 0x20, 0x42, 0x75, 0x72, 0x73, 0x74, 0x20, 0x47, 0x61, 0x6D, 0x65, 0x20, 0x53, 0x65, 0x72,
172 0x76, 0x65, 0x72, 0x2E, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31,
173 0x39, 0x39, 0x39, 0x2D, 0x32, 0x30, 0x30, 0x34, 0x20, 0x53, 0x4F, 0x4E, 0x49, 0x43, 0x54, 0x45,
174 0x41, 0x4D, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
176 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
177 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
178 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
179 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
180 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
181 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30
182};
183
184const unsigned char Message03[] = { "Tethealla Gate v.047" };
185
186
187/* Server Redirect */
188
189const unsigned char Packet19[] = {
190 0x10, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
191};
192
193
194/* Login message */
195
196const unsigned char Packet1A[] = {
197 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x45, 0x00
198};
199
200/* Ping pong */
201
202const unsigned char Packet1D[] = {
203 0x08, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00
204};
205
206/* Current time */
207
208const unsigned char PacketB1[] = {
209 0x24, 0x00, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00
210};
211
212/* Guild Card Data */
213
214unsigned char PacketDC01[0x14] = {0};
215unsigned char PacketDC02[0x10] = {0};
216unsigned char PacketDC_Check[54672] = {0};
217
218/* No Character Header */
219
220unsigned char PacketE4[0x10] = { 0 };
221
222
223/* Character Header */
224
225unsigned char PacketE5[0x88] = { 0 };
226
227/* Security Packet */
228
229const unsigned char PacketE6[] = {
2300x44, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2310x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x3F, 0x71, 0x8D, 0x34, 0x37, 0x7A, 0xBD,
2320x67, 0x39, 0x65, 0x6B, 0x2C, 0xB1, 0xA5, 0x7C, 0x17, 0x93, 0x93, 0x29, 0x4A, 0x90, 0xE9, 0x11,
2330xB8, 0xB5, 0x0E, 0x77, 0x41, 0x30, 0x9B, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2340x01, 0x01, 0x00, 0x00
235};
236
237/* Acknowledging client's expected checksum */
238
239const unsigned char PacketE8[] = {
240 0x0C, 0x00, 0xE8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
241};
242
243/* The "Top Broadcast" Packet */
244
245const unsigned char PacketEE[] = {
246 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
247};
248
249unsigned char E2_Base[2808] = { 0 };
250unsigned char PacketE2Data[2808] = { 0 };
251
252/* String sent to server to retrieve IP address. */
253
254char* HTTP_REQ = "GET http://www.pioneer2.net/remote.php HTTP/1.0\r\n\r\n\r\n";
255
256/* Populated by load_config_file(): */
257
258char mySQL_Host[255] = {0};
259char mySQL_Username[255] = {0};
260char mySQL_Password[255] = {0};
261char mySQL_Database[255] = {0};
262unsigned int mySQL_Port;
263unsigned char serverIP[4];
264unsigned short serverPort;
265int override_on = 0;
266unsigned char overrideIP[4];
267unsigned short serverMaxConnections;
268unsigned short serverMaxShips;
269unsigned serverNumConnections = 0;
270unsigned serverConnectionList[LOGIN_COMPILED_MAX_CONNECTIONS];
271unsigned serverNumShips = 0;
272unsigned serverShipList[SHIP_COMPILED_MAX_CONNECTIONS];
273unsigned quest_numallows;
274unsigned* quest_allow;
275unsigned max_ship_keys = 0;
276
277/* Rare table structure */
278
279unsigned rt_tables_ep1[0x200 * 10 * 4] = {0};
280unsigned rt_tables_ep2[0x200 * 10 * 4] = {0};
281unsigned rt_tables_ep4[0x200 * 10 * 4] = {0};
282
283unsigned mob_rate[8]; // rare appearance rate
284
285char Welcome_Message[255] = {0};
286time_t servertime;
287
288#ifndef NO_SQL
289
290MYSQL * myData;
291char myQuery[0x10000] = {0};
292MYSQL_ROW myRow ;
293MYSQL_RES * myResult;
294
295#endif
296
297//#define NO_ALIGN __declspec(align(1))
298#define NO_ALIGN __attribute__((aligned(1)))
299
300/* Mag data structure */
301
302typedef struct NO_ALIGN st_mag
303{
304 unsigned char two; // "02" =P
305 unsigned char mtype;
306 unsigned char level;
307 unsigned char blasts;
308 short defense;
309 short power;
310 short dex;
311 short mind;
312 unsigned itemid;
313 char synchro;
314 unsigned char IQ;
315 unsigned char PBflags;
316 unsigned char color;
317} MAG;
318
319
320/* Character Data Structure */
321
322typedef struct NO_ALIGN st_minichar {
323 unsigned short packetSize; // 0x00 - 0x01
324 unsigned short command; // 0x02 - 0x03
325 unsigned char flags[4]; // 0x04 - 0x07
326 unsigned char unknown[8]; // 0x08 - 0x0F
327 unsigned short level; // 0x10 - 0x11
328 unsigned short reserved; // 0x12 - 0x13
329 char gcString[10]; // 0x14 - 0x1D
330 unsigned char unknown2[14]; // 0x1E - 0x2B
331 unsigned char nameColorBlue; // 0x2C
332 unsigned char nameColorGreen; // 0x2D
333 unsigned char nameColorRed; // 0x2E
334 unsigned char nameColorTransparency; // 0x2F
335 unsigned short skinID; // 0x30 - 0x31
336 unsigned char unknown3[18]; // 0x32 - 0x43
337 unsigned char sectionID; // 0x44
338 unsigned char _class; // 0x45
339 unsigned char skinFlag; // 0x46
340 unsigned char unknown4[5]; // 0x47 - 0x4B (same as unknown5 in E7)
341 unsigned short costume; // 0x4C - 0x4D
342 unsigned short skin; // 0x4E - 0x4F
343 unsigned short face; // 0x50 - 0x51
344 unsigned short head; // 0x52 - 0x53
345 unsigned short hair; // 0x54 - 0x55
346 unsigned short hairColorRed; // 0x56 - 0x57
347 unsigned short hairColorBlue; // 0x58 - 0x59
348 unsigned short hairColorGreen; // 0x5A - 0x5B
349 unsigned proportionX; // 0x5C - 0x5F
350 unsigned proportionY; // 0x60 - 0x63
351 unsigned char name[24]; // 0x64 - 0x7B
352 unsigned char unknown5[8] ; // 0x7C - 0x83
353 unsigned playTime;
354} MINICHAR;
355
356//packetSize = 0x399C;
357//command = 0x00E7;
358
359typedef struct NO_ALIGN st_bank_item {
360 unsigned char data[12]; // the standard $setitem1 - $setitem3 fare
361 unsigned itemid; // player item id
362 unsigned char data2[4]; // $setitem4 (mag use only)
363 unsigned bank_count; // Why?
364} BANK_ITEM;
365
366typedef struct NO_ALIGN st_bank {
367 unsigned bankUse;
368 unsigned bankMeseta;
369 BANK_ITEM bankInventory [200];
370} BANK;
371
372typedef struct NO_ALIGN st_item {
373 unsigned char data[12]; // the standard $setitem1 - $setitem3 fare
374 unsigned itemid; // player item id
375 unsigned char data2[4]; // $setitem4 (mag use only)
376} ITEM;
377
378typedef struct NO_ALIGN st_inventory {
379 unsigned in_use; // 0x01 = item slot in use, 0xFF00 = unused
380 unsigned flags; // 8 = equipped
381 ITEM item;
382} INVENTORY;
383
384typedef struct NO_ALIGN st_chardata {
385 unsigned short packetSize; // 0x00-0x01 // Always set to 0x399C
386 unsigned short command; // 0x02-0x03 // // Always set to 0x00E7
387 unsigned char flags[4]; // 0x04-0x07
388 unsigned char inventoryUse; // 0x08
389 unsigned char HPuse; // 0x09
390 unsigned char TPuse; // 0x0A
391 unsigned char lang; // 0x0B
392 INVENTORY inventory[30]; // 0x0C-0x353
393 unsigned short ATP; // 0x354-0x355
394 unsigned short MST; // 0x356-0x357
395 unsigned short EVP; // 0x358-0x359
396 unsigned short HP; // 0x35A-0x35B
397 unsigned short DFP; // 0x35C-0x35D
398 unsigned short TP; // 0x35E-0x35F
399 unsigned short LCK; // 0x360-0x361
400 unsigned short ATA; // 0x362-0x363
401 unsigned char unknown[8]; // 0x364-0x36B (Offset 0x360 has 0x0A value on Schthack's...)
402 unsigned short level; // 0x36C-0x36D;
403 unsigned short unknown2; // 0x36E-0x36F;
404 unsigned XP; // 0x370-0x373
405 unsigned meseta; // 0x374-0x377;
406 char gcString[10]; // 0x378-0x381;
407 unsigned char unknown3[14]; // 0x382-0x38F; // Same as E5 unknown2
408 unsigned char nameColorBlue; // 0x390;
409 unsigned char nameColorGreen; // 0x391;
410 unsigned char nameColorRed; // 0x392;
411 unsigned char nameColorTransparency; // 0x393;
412 unsigned short skinID; // 0x394-0x395;
413 unsigned char unknown4[18]; // 0x396-0x3A7
414 unsigned char sectionID; // 0x3A8;
415 unsigned char _class; // 0x3A9;
416 unsigned char skinFlag; // 0x3AA;
417 unsigned char unknown5[5]; // 0x3AB-0x3AF; // Same as E5 unknown4.
418 unsigned short costume; // 0x3B0 - 0x3B1;
419 unsigned short skin; // 0x3B2 - 0x3B3;
420 unsigned short face; // 0x3B4 - 0x3B5;
421 unsigned short head; // 0x3B6 - 0x3B7;
422 unsigned short hair; // 0x3B8 - 0x3B9;
423 unsigned short hairColorRed; // 0x3BA-0x3BB;
424 unsigned short hairColorBlue; // 0x3BC-0x3BD;
425 unsigned short hairColorGreen; // 0x3BE-0x3BF;
426 unsigned proportionX; // 0x3C0-0x3C3;
427 unsigned proportionY; // 0x3C4-0x3C7;
428 unsigned char name[24]; // 0x3C8-0x3DF;
429 unsigned playTime; // 0x3E0 - 0x3E3
430 unsigned char unknown6[4]; // 0x3E4 - 0x3E7;
431 unsigned char keyConfig[232]; // 0x3E8 - 0x4CF;
432 // Stored from ED 07 packet.
433 unsigned char techniques[20]; // 0x4D0 - 0x4E3;
434 unsigned char unknown7[16]; // 0x4E4 - 0x4F3;
435 unsigned char options[4]; // 0x4F4-0x4F7;
436 // Stored from ED 01 packet.
437 unsigned char unknown8[520]; // 0x4F8 - 0x6FF;
438 unsigned bankUse; // 0x700 - 0x703
439 unsigned bankMeseta; // 0x704 - 0x707;
440 BANK_ITEM bankInventory [200]; // 0x708 - 0x19C7
441 unsigned guildCard; // 0x19C8-0x19CB;
442 // Stored from E8 06 packet.
443 unsigned char name2[24]; // 0x19CC - 0x19E3;
444 unsigned char unknown9[232]; // 0x19E4-0x1ACB;
445 unsigned char reserved1; // 0x1ACC; // Has value 0x01 on Schthack's
446 unsigned char reserved2; // 0x1ACD; // Has value 0x01 on Schthack's
447 unsigned char sectionID2; // 0x1ACE;
448 unsigned char _class2; // 0x1ACF;
449 unsigned char unknown10[4]; // 0x1AD0-0x1AD3;
450 unsigned char symbol_chats[1248]; // 0x1AD4 - 0x1FB3
451 // Stored from ED 02 packet.
452 unsigned char shortcuts[2624]; // 0x1FB4 - 0x29F3
453 // Stored from ED 03 packet.
454 unsigned char unknown11[344]; // 0x29F4 - 0x2B4B;
455 unsigned char GCBoard[172]; // 0x2B4C - 0x2BF7;
456 unsigned char unknown12[200]; // 0x2BF8 - 0x2CBF;
457 unsigned char challengeData[320]; // 0x2CC0 - 0X2DFF
458 unsigned char unknown13[172]; // 0x2E00 - 0x2EAB;
459 unsigned char unknown14[276]; // 0x2EAC - 0x2FBF; // I don't know what this is, but split from unknown13 because this chunk is
460 // actually copied into the 0xE2 packet during login @ 0x08
461 unsigned char keyConfigGlobal[364]; // 0x2FC0 - 0x312B // Copied into 0xE2 login packet @ 0x11C
462 // Stored from ED 04 packet.
463 unsigned char joyConfigGlobal[56]; // 0x312C - 0x3163 // Copied into 0xE2 login packet @ 0x288
464 // Stored from ED 05 packet.
465 unsigned guildCard2; // 0x3164 - 0x3167 (From here on copied into 0xE2 login packet @ 0x2C0...)
466 unsigned teamID; // 0x3168 - 0x316B
467 unsigned char teamInformation[8]; // 0x316C - 0x3173 (usually blank...)
468 unsigned short privilegeLevel; // 0x3174 - 0x3175
469 unsigned short reserved3; // 0x3176 - 0x3177
470 unsigned char teamName[28]; // 0x3178 - 0x3193
471 unsigned unknown15; // 0x3194 - 0x3197
472 unsigned char teamFlag[2048]; // 0x3198 - 0x3997
473 unsigned char teamRewards[8]; // 0x3998 - 0x39A0
474} CHARDATA;
475
476
477/* Player Structure */
478
479typedef struct st_banana {
480 int plySockfd;
481 int login;
482 unsigned char peekbuf[8];
483 unsigned char rcvbuf [TCP_BUFFER_SIZE];
484 unsigned short rcvread;
485 unsigned short expect;
486 unsigned char decryptbuf [TCP_BUFFER_SIZE];
487 unsigned char sndbuf [TCP_BUFFER_SIZE];
488 unsigned char encryptbuf [TCP_BUFFER_SIZE];
489 int snddata,
490 sndwritten;
491 unsigned char packet [TCP_BUFFER_SIZE];
492 unsigned short packetdata;
493 unsigned short packetread;
494 int crypt_on;
495 PSO_CRYPT server_cipher, client_cipher;
496 unsigned guildcard;
497 char guildcard_string[12];
498 unsigned char guildcard_data[20000];
499 int sendingchars;
500 short slotnum;
501 unsigned lastTick; // The last second
502 unsigned toBytesSec; // How many bytes per second the server sends to the client
503 unsigned fromBytesSec; // How many bytes per second the server receives from the client
504 unsigned packetsSec; // How many packets per second the server receives from the client
505 unsigned connected;
506 unsigned char sendCheck[MAX_SENDCHECK+2];
507 int todc;
508 unsigned char IP_Address[16];
509 char hwinfo[18];
510 int isgm;
511 int dress_flag;
512 unsigned connection_index;
513} BANANA;
514
515typedef struct st_dressflag {
516 unsigned guildcard;
517 unsigned flagtime;
518} DRESSFLAG;
519
520/* a RC4 expanded key session */
521struct rc4_key {
522 unsigned char state[256];
523 unsigned x, y;
524};
525
526/* Ship Structure */
527
528typedef struct st_orange {
529 int shipSockfd;
530 unsigned char name[13];
531 unsigned playerCount;
532 unsigned char shipAddr[5];
533 unsigned char listenedAddr[4];
534 unsigned short shipPort;
535 unsigned char rcvbuf [TCP_BUFFER_SIZE];
536 unsigned long rcvread;
537 unsigned long expect;
538 unsigned char decryptbuf [TCP_BUFFER_SIZE];
539 unsigned char sndbuf [PACKET_BUFFER_SIZE];
540 unsigned char encryptbuf [TCP_BUFFER_SIZE];
541 unsigned char packet [PACKET_BUFFER_SIZE];
542 unsigned long packetread;
543 unsigned long packetdata;
544 int snddata,
545 sndwritten;
546 unsigned shipID;
547 int authed;
548 int todc;
549 int crypt_on;
550 unsigned char user_key[128];
551 int key_change[128];
552 unsigned key_index;
553 struct rc4_key cs_key; // Encryption keys
554 struct rc4_key sc_key; // Encryption keys
555 unsigned connection_index;
556 unsigned connected;
557 unsigned last_ping;
558 int sent_ping;
559} ORANGE;
560
561fd_set ReadFDs, WriteFDs, ExceptFDs;
562
563DRESSFLAG dress_flags[MAX_DRESS_FLAGS];
564unsigned char dp[TCP_BUFFER_SIZE*4];
565unsigned char tmprcv[PACKET_BUFFER_SIZE];
566char Packet1AData[TCP_BUFFER_SIZE];
567char PacketEEData[TCP_BUFFER_SIZE];
568unsigned char PacketEB01[0x4C8*2] = {0};
569unsigned char PacketEB02[MAX_EB02] = {0};
570unsigned PacketEB01_Total;
571unsigned PacketEB02_Total;
572
573unsigned keys_in_use [SHIP_COMPILED_MAX_CONNECTIONS+1] = { 0 };
574
575#ifdef NO_SQL
576
577typedef struct st_bank_file {
578 unsigned guildcard;
579 BANK common_bank;
580} L_BANK_DATA;
581
582typedef struct st_account {
583 char username[18];
584 char password[33];
585 char email[255];
586 unsigned regtime;
587 char lastip[16];
588 long long lasthwinfo;
589 unsigned guildcard;
590 int isgm;
591 int isbanned;
592 int islogged;
593 int isactive;
594 int teamid;
595 int privlevel;
596 unsigned char lastchar[24];
597} L_ACCOUNT_DATA;
598
599
600typedef struct st_character {
601 unsigned guildcard;
602 int slot;
603 CHARDATA data;
604 MINICHAR header;
605} L_CHARACTER_DATA;
606
607
608typedef struct st_guild {
609 unsigned accountid;
610 unsigned friendid;
611 char friendname[24];
612 char friendtext[176];
613 unsigned short reserved;
614 unsigned short sectionid;
615 unsigned short pclass;
616 unsigned short comment[45];
617 int priority;
618} L_GUILD_DATA;
619
620
621typedef struct st_hwbans {
622 unsigned guildcard;
623 long long hwinfo;
624} L_HW_BANS;
625
626
627typedef struct st_ipbans {
628 unsigned char ipinfo;
629} L_IP_BANS;
630
631
632typedef struct st_key_data {
633 unsigned guildcard;
634 unsigned char controls[420];
635} L_KEY_DATA;
636
637
638typedef struct st_security_data {
639 unsigned guildcard;
640 unsigned thirtytwo;
641 long long sixtyfour;
642 int slotnum;
643 int isgm;
644} L_SECURITY_DATA;
645
646
647typedef struct st_ship_data {
648 unsigned char rc4key[128];
649 unsigned idx;
650} L_SHIP_DATA;
651
652
653typedef struct st_team_data {
654 unsigned short name[12];
655 unsigned owner;
656 unsigned char flag[2048];
657 unsigned teamid;
658} L_TEAM_DATA;
659
660// Oh brother :D
661
662L_BANK_DATA *bank_data[MAX_ACCOUNTS];
663L_ACCOUNT_DATA *account_data[MAX_ACCOUNTS];
664L_CHARACTER_DATA *character_data[MAX_ACCOUNTS*4];
665L_GUILD_DATA *guild_data[MAX_ACCOUNTS*40];
666L_HW_BANS *hw_bans[MAX_ACCOUNTS];
667L_IP_BANS *ip_bans[MAX_ACCOUNTS];
668L_KEY_DATA *key_data[MAX_ACCOUNTS];
669L_SECURITY_DATA *security_data[MAX_ACCOUNTS];
670L_SHIP_DATA *ship_data[SHIP_COMPILED_MAX_CONNECTIONS];
671L_TEAM_DATA *team_data[MAX_ACCOUNTS];
672
673unsigned num_accounts = 0;
674unsigned num_characters = 0;
675unsigned num_guilds = 0;
676unsigned num_hwbans = 0;
677unsigned num_ipbans = 0;
678unsigned num_keydata = 0;
679unsigned num_bankdata = 0;
680unsigned num_security = 0;
681unsigned num_shipkeys = 0;
682unsigned num_teams = 0;
683unsigned ds,ds2;
684int ds_found, new_record, free_record;
685
686#endif
687
688BANK empty_bank;
689
690/* encryption stuff */
691
692void prepare_key(unsigned char *keydata, unsigned len, struct rc4_key *key);
693
694PSO_CRYPT* cipher_ptr;
695
696void encryptcopy (BANANA* client, const unsigned char* src, unsigned size);
697void decryptcopy (unsigned char* dest, const unsigned char* src, unsigned size);
698void compressShipPacket ( ORANGE* ship, unsigned char* src, unsigned long src_size );
699void decompressShipPacket ( ORANGE* ship, unsigned char* dest, unsigned char* src );
700
701#ifdef NO_SQL
702
703void UpdateDataFile ( const char* filename, unsigned count, void* data, unsigned record_size, int new_record );
704void DumpDataFile ( const char* filename, unsigned* count, void** data, unsigned record_size );
705
706unsigned lastdump = 0;
707
708#endif
709
710//#define MYWM_NOTIFYICON (WM_USER+2)
711//int program_hidden = 1;
712//HWND consoleHwnd;
713//HWND backupHwnd;
714
715void WriteLog(char *fmt, ...)
716{
717#define MAX_GM_MESG_LEN 4096
718
719 va_list args;
720 char text[ MAX_GM_MESG_LEN ];
721 //SYSTEMTIME rawtime;
722
723
724 FILE *fp;
725
726 //GetLocalTime (&rawtime);
727 va_start (args, fmt);
728 strcpy (text + vsprintf( text,fmt,args), "\r\n");
729 va_end (args);
730
731 fp = fopen ( "login.log", "a");
732 if (!fp)
733 {
734 printf ("Unable to log to login.log\n");
735 }
736
737 fprintf (fp, "%s", text);
738 fclose (fp);
739
740 printf ("%s", text);
741}
742
743
744void display_packet ( unsigned char* buf, int len )
745{
746 int c, c2, c3, c4;
747
748 c = c2 = c3 = c4 = 0;
749
750 for (c=0;c<len;c++)
751 {
752 if (c3==16)
753 {
754 for (;c4<c;c4++)
755 if (buf[c4] >= 0x20)
756 dp[c2++] = buf[c4];
757 else
758 dp[c2++] = 0x2E;
759 c3 = 0;
760 sprintf (&dp[c2++], "\n" );
761 }
762
763 if ((c == 0) || !(c % 16))
764 {
765 sprintf (&dp[c2], "(%04X) ", c);
766 c2 += 7;
767 }
768
769 sprintf (&dp[c2], "%02X ", buf[c]);
770 c2 += 3;
771 c3++;
772 }
773
774 if ( len % 16 )
775 {
776 c3 = len;
777 while (c3 % 16)
778 {
779 sprintf (&dp[c2], " ");
780 c2 += 3;
781 c3++;
782 }
783 }
784
785 for (;c4<c;c4++)
786 if (buf[c4] >= 0x20)
787 dp[c2++] = buf[c4];
788 else
789 dp[c2++] = 0x2E;
790
791 dp[c2] = 0;
792 printf ("%s\n\n", &dp[0]);
793}
794
795/* Computes the message digest for string inString.
796 Prints out message digest, a space, the string (in quotes) and a
797 carriage return.
798 */
799void MDString (inString, outString)
800char *inString;
801char *outString;
802{
803 unsigned char c;
804 MD5_CTX mdContext;
805 unsigned int len = strlen (inString);
806
807 MD5Init (&mdContext);
808 MD5Update (&mdContext, inString, len);
809 MD5Final (&mdContext);
810 for (c=0;c<16;c++)
811 {
812 *outString = mdContext.digest[c];
813 outString++;
814 }
815}
816
817void convertIPString (char* IPData, unsigned IPLen, int fromConfig )
818{
819 unsigned p,p2,p3;
820 char convert_buffer[5];
821
822 p2 = 0;
823 p3 = 0;
824 for (p=0;p<IPLen;p++)
825 {
826 if ((IPData[p] > 0x20) && (IPData[p] != 46))
827 convert_buffer[p3++] = IPData[p]; else
828 {
829 convert_buffer[p3] = 0;
830 if (IPData[p] == 46) // .
831 {
832 serverIP[p2] = atoi (&convert_buffer[0]);
833 p2++;
834 p3 = 0;
835 if (p2>3)
836 {
837 if (fromConfig)
838 printf ("tethealla.ini is corrupted. (Failed to read IP information from file!)\n"); else
839 printf ("Failed to determine IP address.\n");
840 printf ("Hit [ENTER]");
841 gets (&dp[0]);
842 exit (1);
843 }
844 }
845 else
846 {
847 serverIP[p2] = atoi (&convert_buffer[0]);
848 if (p2 != 3)
849 {
850 if (fromConfig)
851 printf ("tethealla.ini is corrupted. (Failed to read IP information from file!)\n"); else
852 printf ("Failed to determine IP address.\n");
853 printf ("Hit [ENTER]");
854 gets (&dp[0]);
855 exit (1);
856 }
857 break;
858 }
859 }
860 }
861}
862
863long CalculateChecksum(void* data,unsigned long size)
864{
865 long offset,y,cs = 0xFFFFFFFF;
866 for (offset = 0; offset < (long)size; offset++)
867 {
868 cs ^= *(unsigned char*)((long)data + offset);
869 for (y = 0; y < 8; y++)
870 {
871 if (!(cs & 1)) cs = (cs >> 1) & 0x7FFFFFFF;
872 else cs = ((cs >> 1) & 0x7FFFFFFF) ^ 0xEDB88320;
873 }
874 }
875 return (cs ^ 0xFFFFFFFF);
876}
877
878unsigned char EBBuffer [0x10000];
879
880void construct0xEB()
881{
882 char EBFiles[16][255];
883 unsigned EBSize;
884 unsigned EBOffset = 0;
885 unsigned EBChecksum;
886 FILE* fp;
887 FILE* fpb;
888 unsigned char ch, ch6;
889 unsigned ch2, ch3, ch4, ch5, ch7;
890
891 if ( ( fp = fopen ("e8send.txt", "r" ) ) == NULL )
892 {
893 printf ("Missing e8send.txt\n");
894 printf ("Hit [ENTER]");
895 gets (&dp[0]);
896 exit (1);
897 }
898 PacketEB01[0x02] = 0xEB;
899 PacketEB01[0x03] = 0x01;
900 ch = ch6 = 0;
901 ch3 = 0x08;
902 ch4 = ch5 = 0x00;
903 while ( fgets ( &EBFiles[ch][0], 255, fp ) != NULL )
904 {
905 ch2 = strlen (&EBFiles[ch][0]);
906 if (EBFiles[ch][ch2-1] == 0x0A)
907 EBFiles[ch][ch2--] = 0x00;
908 EBFiles[ch][ch2] = 0;
909 printf ("\nLoading data from %s ... ", &EBFiles[ch][0]);
910 if ( ( fpb = fopen (&EBFiles[ch][0], "rb") ) == NULL )
911 {
912 printf ("Could not open %s!\n", &EBFiles[ch][0]);
913 printf ("Hit [ENTER]");
914 gets (&dp[0]);
915 exit (1);
916 }
917 fseek (fpb, 0, SEEK_END);
918 EBSize = ftell (fpb);
919 fseek (fpb, 0, SEEK_SET);
920 fread (&EBBuffer[0], 1, EBSize, fpb);
921 EBChecksum = (unsigned) CalculateChecksum(&EBBuffer[0], EBSize);
922 *(unsigned *) &PacketEB01[ch3] = EBSize;
923 ch3 += 4;
924 *(unsigned *) &PacketEB01[ch3] = EBChecksum;
925 ch3 += 4;
926 *(unsigned *) &PacketEB01[ch3] = EBOffset;
927 ch3 += 4;
928 memcpy (&PacketEB01[ch3], &EBFiles[ch][0], ch2+1 );
929 ch3 += 0x40;
930 EBOffset += EBSize;
931 ch++;
932 fclose ( fpb );
933 for (ch7=0;ch7<EBSize;ch7++)
934 {
935 if (ch4 == 0x00)
936 {
937 ch5 += 2;
938 PacketEB02[ch5++] = 0xEB;
939 PacketEB02[ch5++] = 0x02;
940 ch5 += 4;
941 PacketEB02[ch5++] = ch6;
942 ch5 += 3;
943 ch4 = 0x0C;
944 }
945 PacketEB02[ch5++] = EBBuffer[ch7];
946 ch4++;
947 if (ch4 == 26636)
948 {
949 *(unsigned short*) &PacketEB02[ch5 - 26636] = (unsigned short) ch4;
950 ch4 = 0;
951 ch6++;
952 }
953 }
954 }
955
956 if ( ch4 ) // Probably have some remaining data.
957 {
958 *(unsigned short*)&PacketEB02 [ch5 - ch4] = (unsigned short) ch4;
959 PacketEB02_Total = ch5;
960 if (ch5 > MAX_EB02)
961 {
962 printf ("Too much patch data to send.\n");
963 printf ("Hit [ENTER]");
964 gets (&dp[0]);
965 exit (1);
966 }
967 }
968
969 *(unsigned short*) &PacketEB01[0x00] = (unsigned short) ch3;
970 PacketEB01[0x04] = ch;
971 PacketEB01_Total = ch3;
972 fclose ( fp );
973}
974
975unsigned normalName = 0xFFFFFFFF;
976unsigned globalName = 0xFF1D94F7;
977unsigned localName = 0xFFB0C4DE;
978
979unsigned char hexToByte ( char* hs )
980{
981 unsigned b;
982
983 if ( hs[0] < 58 ) b = (hs[0] - 48); else b = (hs[0] - 55);
984 b *= 16;
985 if ( hs[1] < 58 ) b += (hs[1] - 48); else b += (hs[1] - 55);
986 return (unsigned char) b;
987}
988
989void load_config_file()
990{
991 int config_index = 0;
992 unsigned char config_data[255];
993 unsigned ch;
994
995 FILE* fp;
996
997 if ( ( fp = fopen ("tethealla.ini", "r" ) ) == NULL )
998 {
999 printf ("The configuration file tethealla.ini appears to be missing.\n");
1000 printf ("Hit [ENTER]");
1001 gets (&dp[0]);
1002 exit (1);
1003 }
1004 else
1005 while (fgets (&config_data[0], 255, fp) != NULL)
1006 {
1007 if (config_data[0] != 0x23)
1008 {
1009 if ((config_index < 0x04) || (config_index > 0x04))
1010 {
1011 ch = strlen (&config_data[0]);
1012 if (config_data[ch-1] == 0x0A)
1013 config_data[ch--] = 0x00;
1014 config_data[ch] = 0;
1015 }
1016 switch (config_index)
1017 {
1018 case 0x00:
1019 // MySQL Host
1020 memcpy (&mySQL_Host[0], &config_data[0], ch+1);
1021 break;
1022 case 0x01:
1023 // MySQL Username
1024 memcpy (&mySQL_Username[0], &config_data[0], ch+1);
1025 break;
1026 case 0x02:
1027 // MySQL Password
1028 memcpy (&mySQL_Password[0], &config_data[0], ch+1);
1029 break;
1030 case 0x03:
1031 // MySQL Database
1032 memcpy (&mySQL_Database[0], &config_data[0], ch+1);
1033 break;
1034 case 0x04:
1035 // MySQL Port
1036 mySQL_Port = atoi (&config_data[0]);
1037 break;
1038 case 0x05:
1039 // Server IP address
1040 {
1041 if ((config_data[0] == 0x41) || (config_data[0] == 0x61))
1042 {
1043 struct sockaddr_in pn_in;
1044 struct hostent *pn_host;
1045 int pn_sockfd, pn_len;
1046 char pn_buf[512];
1047 char* pn_ipdata;
1048
1049 printf ("\n** Determining IP address ... ");
1050
1051 pn_host = gethostbyname ( "www.pioneer2.net" );
1052 if (!pn_host) {
1053 printf ("Could not resolve www.pioneer2.net\n");
1054 printf ("Hit [ENTER]");
1055 gets (&dp[0]);
1056 exit (1);
1057 }
1058
1059 /* Create a reliable, stream socket using TCP */
1060 if ((pn_sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
1061 {
1062 printf ("Unable to create TCP/IP streaming socket.");
1063 printf ("Hit [ENTER]");
1064 gets (&dp[0]);
1065 exit(1);
1066 }
1067
1068 /* Construct the server address structure */
1069 memset(&pn_in, 0, sizeof(pn_in)); /* Zero out structure */
1070 pn_in.sin_family = AF_INET; /* Internet address family */
1071
1072 *(unsigned*) &pn_in.sin_addr.s_addr = *(unsigned *) pn_host->h_addr; /* Web Server IP address */
1073
1074 pn_in.sin_port = htons(80); /* Web Server port */
1075
1076 /* Establish the connection to the pioneer2.net Web Server ... */
1077
1078 if (connect(pn_sockfd, (struct sockaddr *) &pn_in, sizeof(pn_in)) < 0)
1079 {
1080 printf ("\nCannot connect to www.pioneer2.net!");
1081 printf ("Hit [ENTER]");
1082 gets (&dp[0]);
1083 exit(1);
1084 }
1085
1086 /* Process pioneer2.net's response into the serverIP variable. */
1087
1088 send_to_server ( pn_sockfd, HTTP_REQ );
1089 pn_len = recv(pn_sockfd, &pn_buf[0], sizeof(pn_buf) - 1, 0);
1090 close(pn_sockfd);
1091 pn_buf[pn_len] = 0;
1092 pn_ipdata = strstr (&pn_buf[0], "/html");
1093 if (!pn_ipdata)
1094 {
1095 printf ("Failed to determine IP address.\n");
1096 }
1097 else
1098 pn_ipdata += 9;
1099
1100 convertIPString (pn_ipdata, strlen (pn_ipdata), 0 );
1101 }
1102 else
1103 {
1104 convertIPString (&config_data[0], ch+1, 1);
1105 }
1106 }
1107 break;
1108 case 0x06:
1109 // Welcome Message
1110 memcpy (&Welcome_Message[0], &config_data[0], ch+1 );
1111 break;
1112 case 0x07:
1113 // Server Listen Port
1114 serverPort = atoi (&config_data[0]);
1115 break;
1116 case 0x08:
1117 // Max Client Connections
1118 serverMaxConnections = atoi (&config_data[0]);
1119 if ( serverMaxConnections > LOGIN_COMPILED_MAX_CONNECTIONS )
1120 {
1121 serverMaxConnections = LOGIN_COMPILED_MAX_CONNECTIONS;
1122 printf ("This version of the login server has not been compiled to handle more than %u login connections. Adjusted.\n", LOGIN_COMPILED_MAX_CONNECTIONS );
1123 }
1124 if (!serverMaxConnections)
1125 serverMaxConnections = LOGIN_COMPILED_MAX_CONNECTIONS;
1126 break;
1127 case 0x09:
1128 // Max Ship Connections
1129 serverMaxShips = atoi (&config_data[0]);
1130 if ( serverMaxShips > SHIP_COMPILED_MAX_CONNECTIONS )
1131 {
1132 serverMaxShips = SHIP_COMPILED_MAX_CONNECTIONS;
1133 printf ("This version of the login server has not been compiled to handle more than %u ship connections. Adjusted.\n", SHIP_COMPILED_MAX_CONNECTIONS );
1134 }
1135 if (!serverMaxShips)
1136 serverMaxShips = SHIP_COMPILED_MAX_CONNECTIONS;
1137 break;
1138 case 0x0A:
1139 // Override IP address (if specified, this IP will be sent out instead of your own to those who connect)
1140 if ((config_data[0] > 0x30) && (config_data[0] < 0x3A))
1141 {
1142 override_on = 1;
1143 *(unsigned *) &overrideIP[0] = *(unsigned *) &serverIP[0];
1144 serverIP[0] = 0;
1145 convertIPString (&config_data[0], ch+1, 1);
1146 }
1147 break;
1148 case 0x0B:
1149 // Hildebear rate
1150 mob_rate[0] = atoi ( &config_data[0] );
1151 break;
1152 case 0x0C:
1153 // Rappy rate
1154 mob_rate[1] = atoi ( &config_data[0] );
1155 break;
1156 case 0x0D:
1157 // Lily rate
1158 mob_rate[2] = atoi ( &config_data[0] );
1159 break;
1160 case 0x0E:
1161 // Slime rate
1162 mob_rate[3] = atoi ( &config_data[0] );
1163 break;
1164 case 0x0F:
1165 // Merissa rate
1166 mob_rate[4] = atoi ( &config_data[0] );
1167 break;
1168 case 0x10:
1169 // Pazuzu rate
1170 mob_rate[5] = atoi ( &config_data[0] );
1171 break;
1172 case 0x11:
1173 // Dorphon Eclair rate
1174 mob_rate[6] = atoi ( &config_data[0] );
1175 break;
1176 case 0x12:
1177 // Kondrieu rate
1178 mob_rate[7] = atoi ( &config_data[0] );
1179 break;
1180 case 0x13:
1181 // Global GM name color
1182 config_data[6] = hexToByte (&config_data[4]);
1183 config_data[7] = hexToByte (&config_data[2]);
1184 config_data[8] = hexToByte (&config_data[0]);
1185 config_data[9] = 0xFF;
1186 globalName = *(unsigned *) &config_data[6];
1187 break;
1188 case 0x14:
1189 // Local GM name color
1190 config_data[6] = hexToByte (&config_data[4]);
1191 config_data[7] = hexToByte (&config_data[2]);
1192 config_data[8] = hexToByte (&config_data[0]);
1193 config_data[9] = 0xFF;
1194 localName = *(unsigned *) &config_data[6];
1195 break;
1196 case 0x15:
1197 // Normal name color
1198 config_data[6] = hexToByte (&config_data[4]);
1199 config_data[7] = hexToByte (&config_data[2]);
1200 config_data[8] = hexToByte (&config_data[0]);
1201 config_data[9] = 0xFF;
1202 normalName = *(unsigned *) &config_data[6];
1203 break;
1204 default:
1205 break;
1206 }
1207 config_index++;
1208 }
1209 }
1210 fclose (fp);
1211
1212 if (config_index < 0x13)
1213 {
1214 printf ("tethealla.ini seems to be corrupted.\n");
1215 printf ("Hit [ENTER]");
1216 gets (&dp[0]);
1217 exit (1);
1218 }
1219}
1220
1221BANANA * connections[LOGIN_COMPILED_MAX_CONNECTIONS];
1222ORANGE * ships[SHIP_COMPILED_MAX_CONNECTIONS];
1223BANANA * workConnect;
1224ORANGE * workShip;
1225
1226unsigned char PacketA0Data[0x4000] = {0};
1227unsigned short PacketA0Size = 0;
1228const char serverName[] = { "T\0E\0T\0H\0E\0A\0L\0L\0A\0" };
1229
1230const char NoShips[9] = "No ships!";
1231
1232void construct0xA0()
1233{
1234 ORANGE* shipcheck;
1235 unsigned totalShips = 0xFFFFFFF4;
1236 unsigned short A0Offset;
1237 char* shipName;
1238 unsigned char playerCountString[5];
1239 unsigned ch, ch2, shipNum;
1240
1241 memset (&PacketA0Data[0], 0, 0x4000);
1242
1243 PacketA0Data[0x02] = 0xA0;
1244 PacketA0Data[0x0A] = 0x20;
1245 *(unsigned *) &PacketA0Data[0x0C] = totalShips;
1246 PacketA0Data[0x10] = 0x04;
1247 memcpy (&PacketA0Data[0x12], &serverName[0], 18 );
1248 A0Offset = 0x36;
1249 totalShips = 0x00;
1250 for (ch=0;ch<serverNumShips;ch++)
1251 {
1252 shipNum = serverShipList[ch];
1253 if (ships[shipNum])
1254 {
1255 shipcheck = ships[shipNum];
1256 if ((shipcheck->shipSockfd >= 0) && (shipcheck->playerCount < 10000))
1257 {
1258 totalShips++;
1259 PacketA0Data[A0Offset] = 0x12;
1260 *(unsigned *) &PacketA0Data[A0Offset+2] = shipcheck->shipID;
1261 ch2 = A0Offset+0x08;
1262 shipName = &shipcheck->name[0];
1263 while (*shipName != 0x00)
1264 {
1265 PacketA0Data[ch2++] = *shipName;
1266 PacketA0Data[ch2++] = 0x00;
1267 shipName++;
1268 }
1269 PacketA0Data[ch2++] = 0x20;
1270 PacketA0Data[ch2++] = 0x00;
1271 PacketA0Data[ch2++] = 0x28;
1272 PacketA0Data[ch2++] = 0x00;
1273 _itoa (shipcheck->playerCount, &playerCountString[0], 10);
1274 shipName = &playerCountString[0];
1275 while (*shipName != 0x00)
1276 {
1277 PacketA0Data[ch2++] = *shipName;
1278 PacketA0Data[ch2++] = 0x00;
1279 shipName++;
1280 }
1281 PacketA0Data[ch2++] = 0x29;
1282 PacketA0Data[ch2++] = 0x00;
1283 A0Offset += 0x2C;
1284 }
1285 }
1286 }
1287 if (!totalShips)
1288 {
1289 totalShips++;
1290 PacketA0Data[A0Offset] = 0x12;
1291 *(unsigned *) &PacketA0Data[A0Offset+2] = totalShips;
1292 for (ch=0;ch<9;ch++)
1293 PacketA0Data[A0Offset+0x08+(ch*2)] = NoShips[ch];
1294 A0Offset += 0x2C;
1295 }
1296 *(unsigned *) &PacketA0Data[0x04] = totalShips;
1297 while (A0Offset % 8)
1298 PacketA0Data[A0Offset++] = 0x00;
1299 *(unsigned short*) &PacketA0Data[0x00] = (unsigned short) A0Offset;
1300 PacketA0Size = A0Offset;
1301}
1302
1303
1304
1305unsigned free_connection()
1306{
1307 unsigned fc;
1308 BANANA* wc;
1309
1310 for (fc=0;fc<serverMaxConnections;fc++)
1311 {
1312 wc = connections[fc];
1313 if (wc->plySockfd<0)
1314 return fc;
1315 }
1316 return 0xFFFF;
1317}
1318
1319unsigned free_shipconnection()
1320{
1321 unsigned fc;
1322 ORANGE* wc;
1323
1324 for (fc=0;fc<serverMaxShips;fc++)
1325 {
1326 wc = ships[fc];
1327 if (wc->shipSockfd<0)
1328 return fc;
1329 }
1330 return 0xFFFF;
1331}
1332
1333
1334void initialize_connection (BANANA* connect)
1335{
1336 unsigned ch, ch2;
1337
1338 if (connect->plySockfd >= 0)
1339 {
1340 ch2 = 0;
1341 for (ch=0;ch<serverNumConnections;ch++)
1342 {
1343 if (serverConnectionList[ch] != connect->connection_index)
1344 serverConnectionList[ch2++] = serverConnectionList[ch];
1345 }
1346 serverNumConnections = ch2;
1347 close (connect->plySockfd);
1348 }
1349 memset (connect, 0, sizeof (BANANA));
1350 connect->plySockfd = -1;
1351 connect->login = -1;
1352 connect->lastTick = 0xFFFFFFFF;
1353 connect->connected = 0xFFFFFFFF;
1354}
1355
1356void initialize_ship (ORANGE* ship)
1357{
1358 unsigned ch, ch2;
1359
1360 if (ship->shipSockfd >= 0)
1361 {
1362 if ( ( ship->key_index ) && ( ship->key_index <= max_ship_keys ) && ( keys_in_use [ ship->key_index ] ) )
1363 keys_in_use [ ship->key_index ] = 0; // key no longer in use
1364
1365 ch2 = 0;
1366 for (ch=0;ch<serverNumShips;ch++)
1367 {
1368 if (serverShipList[ch] != ship->connection_index)
1369 serverShipList[ch2++] = serverShipList[ch];
1370 }
1371 serverNumShips = ch2;
1372 close (ship->shipSockfd);
1373 }
1374 memset (ship, 0, sizeof (ORANGE) );
1375 for (ch=0;ch<128;ch++)
1376 ship->key_change[ch] = -1;
1377 ship->shipSockfd = -1;
1378 // Will be changed upon a successful authentication
1379 ship->playerCount = 0xFFFF;
1380 construct0xA0(); // Removes inactive ships
1381}
1382
1383void start_encryption(BANANA* connect)
1384{
1385 unsigned c, c3, c4, connectNum;
1386 BANANA *workConnect, *c5;
1387
1388 // Limit the number of connections from an IP address to MAX_SIMULTANEOUS_CONNECTIONS.
1389
1390 c3 = 0;
1391
1392 for (c=0;c<serverNumConnections;c++)
1393 {
1394 connectNum = serverConnectionList[c];
1395 workConnect = connections[connectNum];
1396 //debug ("%s comparing to %s", (char*) &workConnect->IP_Address[0], (char*) &connect->IP_Address[0]);
1397 if ((!strcmp(&workConnect->IP_Address[0], &connect->IP_Address[0])) &&
1398 (workConnect->plySockfd >= 0))
1399 c3++;
1400 }
1401
1402 if (c3 > MAX_SIMULTANEOUS_CONNECTIONS)
1403 {
1404 // More than MAX_SIMULTANEOUS_CONNECTIONS connections from a certain IP address...
1405 // Delete oldest connection to server.
1406 c4 = 0xFFFFFFFF;
1407 c5 = NULL;
1408 for (c=0;c<serverNumConnections;c++)
1409 {
1410 connectNum = serverConnectionList[c];
1411 workConnect = connections[connectNum];
1412 if ((!strcmp(&workConnect->IP_Address[0], &connect->IP_Address[0])) &&
1413 (workConnect->plySockfd >= 0))
1414 {
1415 if (workConnect->connected < c4)
1416 {
1417 c4 = workConnect->connected;
1418 c5 = workConnect;
1419 }
1420 }
1421 }
1422 if (c5)
1423 {
1424 workConnect = c5;
1425 initialize_connection (workConnect);
1426 }
1427 }
1428
1429 memcpy (&connect->sndbuf[0], &Packet03[0], sizeof (Packet03));
1430 for (c=0;c<0x30;c++)
1431 {
1432 connect->sndbuf[0x68+c] = (unsigned char) rand() % 255;
1433 connect->sndbuf[0x98+c] = (unsigned char) rand() % 255;
1434 }
1435 connect->snddata += sizeof (Packet03);
1436 cipher_ptr = &connect->server_cipher;
1437 pso_crypt_table_init_bb (cipher_ptr, &connect->sndbuf[0x68]);
1438 cipher_ptr = &connect->client_cipher;
1439 pso_crypt_table_init_bb (cipher_ptr, &connect->sndbuf[0x98]);
1440 connect->crypt_on = 1;
1441 connect->sendCheck[SEND_PACKET_03] = 1;
1442 connect->connected = (unsigned) servertime;
1443}
1444
1445void SendB1 (BANANA* client)
1446{
1447 //SYSTEMTIME rawtime;
1448 time_t t;
1449 struct tm *rawtime;
1450
1451 /*if ((client->guildcard) && (client->slotnum != -1))
1452 {
1453 GetSystemTime (&rawtime);
1454 *(long long*) &client->encryptbuf[0] = *(long long*) &PacketB1[0];
1455 memset (&client->encryptbuf[0x08], 0, 28);
1456 sprintf (&client->encryptbuf[8], "%u:%02u:%02u: %02u:%02u:%02u.%03u", rawtime.wYear, rawtime.wMonth, rawtime.wDay,
1457 rawtime.wHour, rawtime.wMinute, rawtime.wSecond, rawtime.wMilliseconds );
1458 cipher_ptr = &client->server_cipher;
1459 encryptcopy (client, &client->encryptbuf[0], 0x24 );
1460 }*/
1461 if ((client->guildcard) && (client->slotnum != -1))
1462 {
1463 time(&t);
1464 rawtime = localtime(&t);
1465 *(long long*) &client->encryptbuf[0] = *(long long*) &PacketB1[0];
1466 memset (&client->encryptbuf[0x08], 0, 28);
1467 sprintf (&client->encryptbuf[8], "%u:%02u:%02u: %02u:%02u:%02u.%03u", rawtime->tm_year, rawtime->tm_mon, rawtime->tm_mday,
1468 rawtime->tm_hour, rawtime->tm_min, rawtime->tm_sec, rawtime->tm_sec/1000 ); //WICHTIG
1469 cipher_ptr = &client->server_cipher;
1470 encryptcopy (client, &client->encryptbuf[0], 0x24 );
1471 }
1472 else
1473 client->todc = 1;
1474}
1475
1476void Send1A (const char *mes, BANANA* client)
1477{
1478 unsigned short x1A_Len;
1479
1480 memcpy (&Packet1AData[0], &Packet1A[0], sizeof (Packet1A));
1481 x1A_Len = sizeof (Packet1A);
1482
1483 while (*mes != 0x00)
1484 {
1485 Packet1AData[x1A_Len++] = *(mes++);
1486 Packet1AData[x1A_Len++] = 0x00;
1487 }
1488
1489 Packet1AData[x1A_Len++] = 0x00;
1490 Packet1AData[x1A_Len++] = 0x00;
1491
1492 while (x1A_Len % 8)
1493 Packet1AData[x1A_Len++] = 0x00;
1494 *(unsigned short*) &Packet1AData[0] = x1A_Len;
1495 cipher_ptr = &client->server_cipher;
1496 encryptcopy (client, &Packet1AData[0], x1A_Len);
1497 client->todc = 1;
1498}
1499
1500void SendA0 (BANANA* client)
1501{
1502 if ((client->guildcard) && (client->slotnum != -1))
1503 {
1504 cipher_ptr = &client->server_cipher;
1505 encryptcopy (client, &PacketA0Data[0], *(unsigned short*) &PacketA0Data[0]);
1506 }
1507 else
1508 client->todc = 1;
1509}
1510
1511
1512void SendEE (const char *mes, BANANA* client)
1513{
1514 unsigned short xEE_Len;
1515
1516 if ((client->guildcard) && (client->slotnum != -1))
1517 {
1518 memcpy (&PacketEEData[0], &PacketEE[0], sizeof (PacketEE));
1519 xEE_Len = sizeof (PacketEE);
1520
1521 while (*mes != 0x00)
1522 {
1523 PacketEEData[xEE_Len++] = *(mes++);
1524 PacketEEData[xEE_Len++] = 0x00;
1525 }
1526
1527 PacketEEData[xEE_Len++] = 0x00;
1528 PacketEEData[xEE_Len++] = 0x00;
1529
1530 while (xEE_Len % 8)
1531 PacketEEData[xEE_Len++] = 0x00;
1532 *(unsigned short*) &PacketEEData[0] = xEE_Len;
1533 cipher_ptr = &client->server_cipher;
1534 encryptcopy (client, &PacketEEData[0], xEE_Len);
1535 }
1536}
1537
1538void Send19 (unsigned char ip1, unsigned char ip2, unsigned char ip3, unsigned char ip4, unsigned short ipp, BANANA* client)
1539{
1540 memcpy ( &client->encryptbuf[0], &Packet19, sizeof (Packet19));
1541 client->encryptbuf[0x08] = ip1;
1542 client->encryptbuf[0x09] = ip2;
1543 client->encryptbuf[0x0A] = ip3;
1544 client->encryptbuf[0x0B] = ip4;
1545 *(unsigned short*) &client->encryptbuf[0x0C] = ipp;
1546 cipher_ptr = &client->server_cipher;
1547 encryptcopy (client, &client->encryptbuf[0], sizeof (Packet19));
1548}
1549
1550unsigned char key_data_send[840+10] = {0};
1551
1552void SendE2 (BANANA* client)
1553{
1554 int key_exists = 0;
1555
1556 if ((client->guildcard) && (!client->sendCheck[SEND_PACKET_E2]))
1557 {
1558 memcpy (&PacketE2Data[0], &E2_Base[0], 2808);
1559
1560#ifdef NO_SQL
1561
1562 ds_found = -1;
1563 for (ds=0;ds<num_keydata;ds++)
1564 {
1565 if (key_data[ds]->guildcard == client->guildcard)
1566 {
1567 ds_found = ds;
1568 break;
1569 }
1570 }
1571 if (ds_found != -1)
1572 memcpy (&PacketE2Data[0x11C], &key_data[ds_found]->controls, 420 );
1573 else
1574 {
1575 key_data[num_keydata] = malloc (sizeof(L_KEY_DATA));
1576 key_data[num_keydata]->guildcard = client->guildcard;
1577 memcpy (&key_data[num_keydata]->controls, &E2_Base[0x11C], 420);
1578 UpdateDataFile ("keydata.dat", num_keydata, key_data[num_keydata], sizeof(L_KEY_DATA), 1);
1579 num_keydata++;
1580 }
1581
1582#else
1583
1584 sprintf (&myQuery[0], "SELECT * from key_data WHERE guildcard='%u'", client->guildcard );
1585
1586 //printf ("MySQL query %s\n", myQuery );
1587
1588 // Check to see if we've got some saved key data.
1589
1590 if ( ! mysql_query ( myData, &myQuery[0] ) )
1591 {
1592 myResult = mysql_store_result ( myData );
1593 key_exists = (int) mysql_num_rows ( myResult );
1594 if ( key_exists )
1595 {
1596 //debug ("Key data exists, fetching...");
1597 myRow = mysql_fetch_row ( myResult );
1598 memcpy (&PacketE2Data[0x11C], myRow[1], 420 );
1599 }
1600 else
1601 {
1602 //debug ("Key data does not exist...");
1603 mysql_real_escape_string ( myData, &key_data_send[0], &E2_Base[0x11C], 420 );
1604 sprintf (&myQuery[0], "INSERT INTO key_data (guildcard, controls) VALUES ('%u','%s')", client->guildcard, (char*) &key_data_send[0] );
1605 memcpy (&PacketE2Data[0x11C], &E2_Base[0x11C], 420);
1606 if ( mysql_query ( myData, &myQuery[0] ) )
1607 debug ("Could not insert key information into database.");
1608 }
1609 mysql_free_result ( myResult );
1610 }
1611 else
1612 {
1613 Send1A ("Could not fetch key data.\n\nThere is a problem with the MySQL database.", client);
1614 client->todc = 1;
1615 return;
1616 }
1617#endif
1618 memset (&PacketE2Data[0xAF4], 0xFF, 4); // Enable dressing room, etc,.
1619 cipher_ptr = &client->server_cipher;
1620 encryptcopy (client, &PacketE2Data[0], sizeof (PacketE2Data));
1621 client->sendCheck[SEND_PACKET_E2] = 0x01;
1622 }
1623 else
1624 client->todc = 1;
1625}
1626
1627unsigned StringLength (const char* src)
1628{
1629 unsigned ch = 0;
1630
1631 while (*src != 0x00)
1632 {
1633 ch++;
1634 src++;
1635 }
1636 return ch;
1637}
1638
1639CHARDATA E7_Base, E7_Work;
1640unsigned char chardata[0x200];
1641unsigned char E7chardata[(sizeof(CHARDATA)*2)+100];
1642unsigned char startingStats[12*14];
1643unsigned char DefaultTeamFlagSlashes[4098];
1644unsigned char DefaultTeamFlag[2048];
1645unsigned char FlagSlashes[4098];
1646
1647void AckCharacter_Creation(unsigned char slotnum, BANANA* client)
1648{
1649 unsigned short *n;
1650#ifndef NO_SQL
1651 int char_exists;
1652#endif
1653 unsigned short packetSize;
1654 MINICHAR* clientchar;
1655 CHARDATA* E7Base;
1656 CHARDATA* NewE7;
1657 unsigned short maxFace, maxHair, maxHairColorRed, maxHairColorBlue, maxHairColorGreen,
1658 maxCostume, maxSkin, maxHead;
1659 unsigned ch;
1660
1661 packetSize = *(unsigned short*) &client->decryptbuf[0];
1662 if ( ( client->guildcard ) && ( slotnum < 4 ) && ( client->sendingchars == 0 ) &&
1663 ( packetSize == 0x88 ) && ( client->decryptbuf[0x45] < CLASS_MAX ) )
1664 {
1665 clientchar = (MINICHAR*) &client->decryptbuf[0x00];
1666 clientchar->name[0] = 0x09; // Filter colored names
1667 clientchar->name[1] = 0x00;
1668 clientchar->name[2] = 0x45;
1669 clientchar->name[3] = 0x00;
1670 clientchar->name[22] = 0; // Truncate names too long
1671 clientchar->name[23] = 0;
1672 if ((clientchar->_class == CLASS_HUMAR) ||
1673 (clientchar->_class == CLASS_HUNEWEARL) ||
1674 (clientchar->_class == CLASS_RAMAR) ||
1675 (clientchar->_class == CLASS_RAMARL) ||
1676 (clientchar->_class == CLASS_FOMARL) ||
1677 (clientchar->_class == CLASS_FONEWM) ||
1678 (clientchar->_class == CLASS_FONEWEARL) ||
1679 (clientchar->_class == CLASS_FOMAR))
1680 {
1681 maxFace = 0x05;
1682 maxHair = 0x0A;
1683 maxHairColorRed = 0xFF;
1684 maxHairColorBlue = 0xFF;
1685 maxHairColorGreen = 0xFF;
1686 maxCostume = 0x11;
1687 maxSkin = 0x03;
1688 maxHead = 0x00;
1689 }
1690 else
1691 {
1692 maxFace = 0x00;
1693 maxHair = 0x00;
1694 maxHairColorRed = 0x00;
1695 maxHairColorBlue = 0x00;
1696 maxHairColorGreen = 0x00;
1697 maxCostume = 0x00;
1698 maxSkin = 0x18;
1699 maxHead = 0x04;
1700 }
1701 if (clientchar->skinID > 0x06)
1702 clientchar->skinID = 0x00;
1703 clientchar->nameColorTransparency = 0xFF;
1704 if (clientchar->sectionID > 0x09)
1705 clientchar->sectionID = 0x00;
1706 if (clientchar->proportionX > 0x3F800000)
1707 clientchar->proportionX = 0x3F800000;
1708 if (clientchar->proportionY > 0x3F800000)
1709 clientchar->proportionY = 0x3F800000;
1710 if (clientchar->face > maxFace)
1711 clientchar->face = 0x00;
1712 if (clientchar->hair > maxHair)
1713 clientchar->hair = 0x00;
1714 if (clientchar->hairColorRed > maxHairColorRed)
1715 clientchar->hairColorRed = 0x00;
1716 if (clientchar->hairColorBlue > maxHairColorBlue)
1717 clientchar->hairColorBlue = 0x00;
1718 if (clientchar->hairColorGreen > maxHairColorGreen)
1719 clientchar->hairColorGreen = 0x00;
1720 if (clientchar->costume > maxCostume)
1721 clientchar->costume = 0x00;
1722 if (clientchar->skin > maxSkin)
1723 clientchar->skin = 0x00;
1724 if (clientchar->head > maxHead)
1725 clientchar->head = 0x00;
1726 for (ch=0;ch<8;ch++)
1727 clientchar->unknown5[ch] = 0x00;
1728 clientchar->playTime = 0;
1729
1730 if ( client->dress_flag == 0 )
1731 {
1732 /* Yeah! MySQL! :D */
1733
1734#ifndef NO_SQL
1735
1736 mysql_real_escape_string ( myData, &chardata[0], &client->decryptbuf[0x10], 0x78 );
1737
1738#endif
1739
1740 /* Let's construct the FULL character now... */
1741
1742 E7Base = &E7_Base;
1743 NewE7 = &E7_Work;
1744 memset (NewE7, 0, sizeof (CHARDATA) );
1745 NewE7->packetSize = 0x399C;
1746 NewE7->command = 0x00E7;
1747 memset (&NewE7->flags, 0, 4);
1748 NewE7->HPuse = 0;
1749 NewE7->TPuse = 0;
1750 NewE7->lang = 0;
1751 switch (clientchar->_class)
1752 {
1753 case CLASS_HUMAR:
1754 case CLASS_HUNEWEARL:
1755 case CLASS_HUCAST:
1756 case CLASS_HUCASEAL:
1757 // Saber
1758 NewE7->inventory[0].in_use = 0x01;
1759 NewE7->inventory[0].flags = 0x08;
1760 NewE7->inventory[0].item.data[1] = 0x01;
1761 NewE7->inventory[0].item.itemid = 0x00010000;
1762 break;
1763 case CLASS_RAMAR:
1764 case CLASS_RACAST:
1765 case CLASS_RACASEAL:
1766 case CLASS_RAMARL:
1767 // Handgun
1768 NewE7->inventory[0].in_use = 0x01;
1769 NewE7->inventory[0].flags = 0x08;
1770 NewE7->inventory[0].item.data[1] = 0x06;
1771 NewE7->inventory[0].item.itemid = 0x00010000;
1772 break;
1773 case CLASS_FONEWM:
1774 case CLASS_FONEWEARL:
1775 case CLASS_FOMARL:
1776 case CLASS_FOMAR:
1777 // Cane
1778 NewE7->inventory[0].in_use = 0x01;
1779 NewE7->inventory[0].flags = 0x08;
1780 NewE7->inventory[0].item.data[1] = 0x0A;
1781 NewE7->inventory[0].item.itemid = 0x00010000;
1782 break;
1783 default:
1784 break;
1785 }
1786
1787 // Frame
1788 NewE7->inventory[1].in_use = 0x01;
1789 NewE7->inventory[1].flags = 0x08;
1790 NewE7->inventory[1].item.data[0] = 0x01;
1791 NewE7->inventory[1].item.data[1] = 0x01;
1792 NewE7->inventory[1].item.itemid = 0x00010001;
1793
1794 // Mag
1795 NewE7->inventory[2].in_use = 0x01;
1796 NewE7->inventory[2].flags = 0x08;
1797 NewE7->inventory[2].item.data[0] = 0x02;
1798 NewE7->inventory[2].item.data[2] = 0x05;
1799 NewE7->inventory[2].item.data[4] = 0xF4;
1800 NewE7->inventory[2].item.data[5] = 0x01;
1801 NewE7->inventory[2].item.data2[0] = 0x14; // 20% synchro
1802 NewE7->inventory[2].item.itemid = 0x00010002;
1803
1804 if ((clientchar->_class == CLASS_HUCAST) || (clientchar->_class == CLASS_HUCASEAL) ||
1805 (clientchar->_class == CLASS_RACAST) || (clientchar->_class == CLASS_RACASEAL))
1806 NewE7->inventory[2].item.data2[3] = (unsigned char) clientchar->skin;
1807 else
1808 NewE7->inventory[2].item.data2[3] = (unsigned char) clientchar->costume;
1809
1810 if (NewE7->inventory[2].item.data2[3] > 0x11)
1811 NewE7->inventory[2].item.data2[3] -= 0x11;
1812
1813 // Monomates
1814 NewE7->inventory[3].in_use = 0x01;
1815 NewE7->inventory[3].item.data[0] = 0x03;
1816 NewE7->inventory[3].item.data[5] = 0x04;
1817 NewE7->inventory[3].item.itemid = 0x00010003;
1818
1819 memcpy (&NewE7->techniques, &E7Base->techniques, 20);
1820
1821 if ( ( clientchar->_class == CLASS_FONEWM ) || ( clientchar->_class == CLASS_FONEWEARL ) ||
1822 ( clientchar->_class == CLASS_FOMARL ) || ( clientchar->_class == CLASS_FOMAR ) )
1823 {
1824 // Monofluids
1825 NewE7->techniques[0] = 0x00;
1826 NewE7->inventory[4].in_use = 0x01;
1827 NewE7->inventory[4].flags = 0x00;
1828 NewE7->inventory[4].item.data[0] = 0x03;
1829 NewE7->inventory[4].item.data[1] = 0x01;
1830 NewE7->inventory[4].item.data[2] = 0x00;
1831 NewE7->inventory[4].item.data[3] = 0x00;
1832 memset (&NewE7->inventory[4].item.data[4], 0x00, 8);
1833 NewE7->inventory[4].item.data[5] = 0x04;
1834 NewE7->inventory[4].item.itemid = 0x00010004;
1835 memset (&NewE7->inventory[3].item.data2[0], 0x00, 4);
1836 NewE7->inventoryUse = 5;
1837 }
1838 else
1839 NewE7->inventoryUse = 4;
1840
1841 for (ch=NewE7->inventoryUse;ch<30;ch++)
1842 {
1843 NewE7->inventory[ch].in_use = 0x00;
1844 NewE7->inventory[ch].item.data[1] = 0xFF;
1845 NewE7->inventory[ch].item.itemid = 0xFFFFFFFF;
1846 }
1847
1848 memcpy (&NewE7->ATP, &startingStats[clientchar->_class * 14], 14);
1849 *(long long*) &NewE7->unknown = *(long long*) &E7Base->unknown;
1850 //NewE7->level = 0x00;
1851 NewE7->unknown2 = E7Base->unknown2;
1852 //NewE7->XP = 0;
1853 NewE7->meseta = 300;
1854 memset (&NewE7->gcString[0], 0x20, 2);
1855 *(long long*) &NewE7->gcString[2] = *(long long*) &client->guildcard_string[0];
1856 memcpy (&NewE7->unknown3, &clientchar->unknown2, 14 );
1857 *(unsigned *) &NewE7->nameColorBlue = *(unsigned *) &clientchar->nameColorBlue; // Will copy all 4 values.
1858 NewE7->skinID = clientchar->skinID;
1859 memcpy (&NewE7->unknown4, &clientchar->unknown3, 18);
1860 NewE7->sectionID = clientchar->sectionID;
1861 NewE7->_class = clientchar->_class;
1862 NewE7->skinFlag = clientchar->skinFlag;
1863 memcpy (&NewE7->unknown5, &clientchar->unknown4, 5);
1864 NewE7->costume = clientchar->costume;
1865 NewE7->skin = clientchar->skin;
1866 NewE7->face = clientchar->face;
1867 NewE7->head = clientchar->head;
1868 NewE7->hair = clientchar->hair;
1869 NewE7->hairColorRed = clientchar->hairColorRed;
1870 NewE7->hairColorBlue = clientchar->hairColorBlue;
1871 NewE7->hairColorGreen = clientchar->hairColorGreen;
1872 NewE7->proportionX = clientchar->proportionX;
1873 NewE7->proportionY = clientchar->proportionY;
1874 n = (unsigned short*) &clientchar->name[4];
1875 for (ch=0;ch<10;ch++)
1876 {
1877 if (*n == 0x0000)
1878 break;
1879 if ((*n == 0x0009) || (*n == 0x000A))
1880 *n = 0x0020;
1881 n++;
1882 }
1883 memcpy (&NewE7->name, &clientchar->name, 24);
1884 *(unsigned *) &NewE7->unknown6 = *(unsigned *) &clientchar->unknown5;
1885 memcpy (&NewE7->keyConfig, &E7Base->keyConfig, 232);
1886 // TO DO: Give Foie to starting Forces.
1887 memcpy (&NewE7->unknown7, &E7Base->unknown7, 16);
1888 *(unsigned *) &NewE7->options = *(unsigned *) &E7Base->options;
1889 memcpy (&NewE7->unknown8, &E7Base->unknown8, 520);
1890 NewE7->bankUse = E7Base->bankUse;
1891 NewE7->bankMeseta = E7Base->bankMeseta;
1892 memcpy (&NewE7->bankInventory, &E7Base->bankInventory, 24*200);
1893 NewE7->guildCard = client->guildcard;
1894 memcpy (&NewE7->name2, &clientchar->name, 24);
1895 memcpy (&NewE7->unknown9, &E7Base->unknown9, 232);
1896 NewE7->reserved1 = 0x01;
1897 NewE7->reserved2 = 0x01;
1898 NewE7->sectionID2 = clientchar->sectionID;
1899 NewE7->_class2 = clientchar->_class;
1900 *(unsigned *) &NewE7->unknown10[0] = *(unsigned *) &E7Base->unknown10[0];
1901 memcpy (&NewE7->symbol_chats, &E7Base->symbol_chats, 1248);
1902 memcpy (&NewE7->shortcuts, &E7Base->shortcuts, 2624);
1903 memcpy (&NewE7->unknown11, &E7Base->unknown11, 344);
1904 memcpy (&NewE7->GCBoard, &E7Base->GCBoard, 172);
1905 memcpy (&NewE7->unknown12, &E7Base->unknown12, 200);
1906 memcpy (&NewE7->challengeData, &E7Base->challengeData, 320);
1907 memcpy (&NewE7->unknown13, &E7Base->unknown13, 172);
1908 memcpy (&NewE7->unknown14, &E7Base->unknown14, 276);
1909 // TO DO: Actually, we should use the values from the database, but I haven't added columns for them yet...
1910 // For now, we'll use the "base" packet's values.
1911 memcpy (&NewE7->keyConfigGlobal, &E7Base->keyConfigGlobal, 364);
1912 memcpy (&NewE7->joyConfigGlobal, &E7Base->joyConfigGlobal, 56);
1913 memcpy (&NewE7->guildCard2, &E7Base->guildCard2, 2108);
1914
1915#ifndef NO_SQL
1916
1917 mysql_real_escape_string ( myData, &E7chardata[0], (unsigned char*) NewE7, sizeof (CHARDATA) );
1918
1919#endif
1920
1921 }
1922
1923 // Check to see if the character exists in that slot.
1924
1925#ifdef NO_SQL
1926
1927 ds_found = -1;
1928 free_record = -1;
1929
1930 for (ds=0;ds<num_characters;ds++)
1931 {
1932 if (character_data[ds]->guildcard == 0)
1933 free_record = ds;
1934
1935 if ((character_data[ds]->guildcard == client->guildcard) &&
1936 (character_data[ds]->slot == slotnum))
1937 {
1938 ds_found = ds;
1939 break;
1940 }
1941 }
1942
1943 if ( ( client->dress_flag ) && ( ds_found != -1 ) )
1944 {
1945 debug ("Update character %u", client->guildcard);
1946 NewE7 = &E7_Work;
1947 memcpy (NewE7, &character_data[ds_found]->data, sizeof (CHARDATA) );
1948 memcpy (&NewE7->gcString[0], &clientchar->gcString[0], 0x68);
1949 *(long long*) &clientchar->unknown5[0] = *(long long*) &NewE7->unknown6[0];
1950 //NewE7->playTime = 0;
1951 memcpy (&character_data[ds_found]->header, &client->decryptbuf[0x10], 0x78);
1952 memcpy (&character_data[ds_found]->data, NewE7, sizeof (CHARDATA));
1953 UpdateDataFile ("character.dat", ds_found, character_data[ds_found], sizeof(L_CHARACTER_DATA), 0);
1954 }
1955 else
1956 {
1957 if (ds_found == -1)
1958 {
1959 if (free_record != -1)
1960 {
1961 ds_found = free_record;
1962 new_record = 0;
1963 }
1964 else
1965 {
1966 ds_found = num_characters;
1967 new_record = 1;
1968 character_data[num_characters++] = malloc (sizeof(L_CHARACTER_DATA));
1969 }
1970 }
1971 else
1972 new_record = 0;
1973 character_data[ds_found]->guildcard = client->guildcard;
1974 character_data[ds_found]->slot = slotnum;
1975 memcpy (&character_data[ds_found]->data, NewE7, sizeof (CHARDATA));
1976 memcpy (&character_data[ds_found]->header, &client->decryptbuf[0x10], 0x78);
1977 UpdateDataFile ("character.dat", ds_found, character_data[ds_found], sizeof(L_CHARACTER_DATA), new_record);
1978 }
1979 PacketE4[0x00] = 0x10;
1980 PacketE4[0x02] = 0xE4;
1981 PacketE4[0x03] = 0x00;
1982 PacketE4[0x08] = slotnum;
1983 PacketE4[0x0C] = 0x00;
1984 cipher_ptr = &client->server_cipher;
1985 encryptcopy (client, &PacketE4[0], sizeof (PacketE4));
1986 ds_found = -1;
1987 for (ds=0;ds<num_security;ds++)
1988 {
1989 if (security_data[ds]->guildcard == client->guildcard)
1990 {
1991 ds_found = ds;
1992 security_data[ds]->slotnum = slotnum;
1993 UpdateDataFile ("security.dat", ds, security_data[ds], sizeof (L_SECURITY_DATA), 0);
1994 break;
1995 }
1996 }
1997
1998 if (ds_found == -1)
1999 {
2000 Send1A ("Could not select character.", client);
2001 client->todc = 1;
2002 }
2003
2004#else
2005
2006 sprintf (&myQuery[0], "SELECT * from character_data WHERE guildcard='%u' AND slot='%u'", client->guildcard, slotnum );
2007 //printf ("MySQL query %s\n", myQuery );
2008
2009 if ( ! mysql_query ( myData, &myQuery[0] ) )
2010 {
2011 myResult = mysql_store_result ( myData );
2012 char_exists = (int) mysql_num_rows ( myResult );
2013 if (char_exists)
2014 {
2015 if (client->dress_flag == 0)
2016 {
2017 // Delete character if recreating...
2018 sprintf (&myQuery[0], "DELETE from character_data WHERE guildcard='%u' AND slot ='%u'", client->guildcard, slotnum );
2019 mysql_query ( myData, &myQuery[0] );
2020 }
2021 else
2022 {
2023 // Updating character only...
2024 myRow = mysql_fetch_row ( myResult );
2025 NewE7 = &E7_Work;
2026 memcpy (NewE7, myRow[2], sizeof (CHARDATA) );
2027 memcpy (&NewE7->gcString[0], &clientchar->gcString[0], 0x68);
2028 *(long long*) &clientchar->unknown5[0] = *(long long*) &NewE7->unknown6[0];
2029 //NewE7->playTime = 0;
2030 mysql_real_escape_string ( myData, &chardata[0], &client->decryptbuf[0x10], 0x78 );
2031 mysql_real_escape_string ( myData, &E7chardata[0], (unsigned char*) NewE7, sizeof (CHARDATA) );
2032 }
2033 }
2034 mysql_free_result ( myResult );
2035 }
2036 else
2037 {
2038 Send1A ("Could not check character information.\n\nThere is a problem with the MySQL database.", client);
2039 client->todc = 1;
2040 return;
2041 }
2042 if (client->dress_flag == 0)
2043 sprintf (&myQuery[0], "INSERT INTO character_data (guildcard,slot,data,header) VALUES ('%u','%u','%s','%s')", client->guildcard, slotnum, (char*) &E7chardata[0], (char*) &chardata[0] );
2044 else
2045 {
2046 debug ("Update character...");
2047 sprintf (&myQuery[0], "UPDATE character_data SET data='%s', header='%s' WHERE guildcard='%u' AND slot='%u'", (char*) &E7chardata[0], (char*) &chardata[0], client->guildcard, slotnum );
2048 }
2049 if ( ! mysql_query ( myData, &myQuery[0] ) )
2050 {
2051 PacketE4[0x00] = 0x10;
2052 PacketE4[0x02] = 0xE4;
2053 PacketE4[0x03] = 0x00;
2054 PacketE4[0x08] = slotnum;
2055 PacketE4[0x0C] = 0x00;
2056 cipher_ptr = &client->server_cipher;
2057 encryptcopy (client, &PacketE4[0], sizeof (PacketE4));
2058 sprintf (&myQuery[0], "UPDATE security_data SET slotnum = '%u' WHERE guildcard = '%u'", slotnum, client->guildcard );
2059 if ( mysql_query ( myData, &myQuery[0] ) )
2060 {
2061 Send1A ("Could not select character.", client);
2062 client->todc = 1;
2063 }
2064 }
2065 else
2066 {
2067 Send1A ("Could not save character to database.\nPlease contact the server administrator.", client);
2068 client->todc = 1;
2069 }
2070#endif
2071 }
2072 else
2073 client->todc = 1;
2074}
2075void SendE4_E5(unsigned char slotnum, unsigned char selecting, BANANA* client)
2076{
2077 int char_exists = 0;
2078 MINICHAR* mc;
2079
2080 if ((client->guildcard) && (slotnum < 0x04))
2081 {
2082#ifdef NO_SQL
2083 ds_found = -1;
2084 for (ds=0;ds<num_characters;ds++)
2085 {
2086 if ((character_data[ds]->guildcard == client->guildcard) &&
2087 (character_data[ds]->slot == slotnum))
2088 {
2089 ds_found = ds;
2090 break;
2091 }
2092 }
2093 if (ds_found != -1)
2094 {
2095 char_exists = 1;
2096 if (!selecting)
2097 {
2098 mc = (MINICHAR*) &PacketE5[0x00];
2099 *(unsigned short*) &PacketE5[0x10] = character_data[ds_found]->data.level; // Updated level
2100 memcpy (&PacketE5[0x14], &character_data[ds_found]->data.gcString[0], 0x70 ); // Updated data
2101 *(unsigned *) &PacketE5[0x84] = character_data[ds_found]->data.playTime; // Updated playtime
2102 if ( mc->skinFlag )
2103 {
2104 // In case we got bots that crashed themselves...
2105 mc->skin = 0;
2106 mc->head = 0;
2107 mc->hair = 0;
2108 }
2109 }
2110 }
2111
2112
2113#else
2114 sprintf (&myQuery[0], "SELECT * from character_data WHERE guildcard='%u' AND slot='%u'", client->guildcard, slotnum );
2115 //printf ("MySQL query %s\n", myQuery );
2116
2117 // Check to see if the character exists in that slot.
2118
2119 if ( ! mysql_query ( myData, &myQuery[0] ) )
2120 {
2121 myResult = mysql_store_result ( myData );
2122 char_exists = (int) mysql_num_rows ( myResult );
2123
2124 if (char_exists)
2125 {
2126 if (!selecting)
2127 {
2128 myRow = mysql_fetch_row ( myResult );
2129 mc = (MINICHAR*) &PacketE5[0x00];
2130 memcpy (&PacketE5[0x10], myRow[2] + 0x36C, 2 ); // Updated level
2131 memcpy (&PacketE5[0x14], myRow[2] + 0x378, 0x70 ); // Updated data
2132 memcpy (&PacketE5[0x84], myRow[2] + 0x3E0, 4 ); // Updated playtime
2133 if ( mc->skinFlag )
2134 {
2135 // In case we got bots that crashed themselves...
2136 mc->skin = 0;
2137 mc->head = 0;
2138 mc->hair = 0;
2139 }
2140 }
2141 }
2142 mysql_free_result ( myResult );
2143 }
2144 else
2145 {
2146 Send1A ("Could not check character information.\n\nThere is a problem with the MySQL database.", client);
2147 client->todc = 1;
2148 return;
2149 }
2150#endif
2151
2152 if (!selecting)
2153 {
2154 if (char_exists)
2155 {
2156 PacketE5[0x00] = 0x88;
2157 PacketE5[0x02] = 0xE5;
2158 PacketE5[0x03] = 0x00;
2159 PacketE5[0x08] = slotnum;
2160 PacketE5[0x0C] = 0x00;
2161 if (client->sendCheck[SEND_PACKET_E5] < 0x04)
2162 {
2163 cipher_ptr = &client->server_cipher;
2164 encryptcopy (client, &PacketE5[0], sizeof (PacketE5));
2165 client->sendCheck[SEND_PACKET_E5] ++;
2166 }
2167 else
2168 client->todc = 1;
2169 }
2170 else
2171 {
2172 PacketE4[0x00] = 0x10;
2173 PacketE4[0x02] = 0xE4;
2174 PacketE4[0x03] = 0x00;
2175 PacketE4[0x08] = slotnum;
2176 PacketE4[0x0C] = 0x02;
2177 if (client->sendCheck[SEND_PACKET_E4] < 0x04)
2178 {
2179 cipher_ptr = &client->server_cipher;
2180 encryptcopy (client, &PacketE4[0], sizeof (PacketE4));
2181 client->sendCheck[SEND_PACKET_E4]++;
2182 }
2183 else
2184 client->todc = 1;
2185 }
2186 }
2187 else
2188 {
2189 if (char_exists)
2190 {
2191 PacketE4[0x00] = 0x10;
2192 PacketE4[0x02] = 0xE4;
2193 PacketE4[0x03] = 0x00;
2194 PacketE4[0x08] = slotnum;
2195 PacketE4[0x0C] = 0x01;
2196 if ((client->sendCheck[SEND_PACKET_E4] < 0x04) && (client->sendingchars == 0))
2197 {
2198 cipher_ptr = &client->server_cipher;
2199 encryptcopy (client, &PacketE4[0], sizeof (PacketE4));
2200#ifdef NO_SQL
2201 ds_found = -1;
2202 for (ds=0;ds<num_security;ds++)
2203 {
2204 if (security_data[ds]->guildcard == client->guildcard)
2205 {
2206 ds_found = ds;
2207 security_data[ds]->slotnum = slotnum;
2208 UpdateDataFile ("security.dat", ds, security_data[ds], sizeof (L_SECURITY_DATA), 0);
2209 break;
2210 }
2211 }
2212
2213 if (ds_found == -1)
2214 {
2215 Send1A ("Could not select character.", client);
2216 client->todc = 1;
2217 }
2218#else
2219 sprintf (&myQuery[0], "UPDATE security_data SET slotnum = '%u' WHERE guildcard = '%u'", slotnum, client->guildcard );
2220 if ( mysql_query ( myData, &myQuery[0] ) )
2221 {
2222 Send1A ("Could not select character.", client);
2223 client->todc = 1;
2224 }
2225#endif
2226 client->sendCheck[SEND_PACKET_E4]++;
2227 }
2228 else
2229 client->todc = 1;
2230 }
2231 else
2232 client->todc = 1;
2233 }
2234 }
2235 else
2236 client->todc = 1;
2237}
2238
2239void SendE8 (BANANA* client)
2240{
2241 if ((client->guildcard) && (!client->sendCheck[SEND_PACKET_E8]))
2242 {
2243 cipher_ptr = &client->server_cipher;
2244 encryptcopy (client, &PacketE8[0], sizeof (PacketE8));
2245 client->sendCheck[SEND_PACKET_E8] = 1;
2246 }
2247 else
2248 client->todc = 1;
2249}
2250
2251void SendEB (unsigned char subCommand, unsigned char EBOffset, BANANA* client)
2252{
2253 unsigned CalcOffset;
2254
2255 if ((client->guildcard) && (client->sendCheck[SEND_PACKET_EB] < 17))
2256 {
2257 client->sendCheck[SEND_PACKET_EB]++;
2258 switch (subCommand)
2259 {
2260 case 0x01:
2261 cipher_ptr = &client->server_cipher;
2262 encryptcopy (client, &PacketEB01[0], PacketEB01_Total);
2263 break;
2264 case 0x02:
2265 cipher_ptr = &client->server_cipher;
2266 CalcOffset = (unsigned) EBOffset * 26636;
2267 if (CalcOffset < PacketEB02_Total)
2268 {
2269 if (PacketEB02_Total - CalcOffset >= 26636)
2270 encryptcopy (client, &PacketEB02[CalcOffset], 26636 );
2271 else
2272 encryptcopy (client, &PacketEB02[CalcOffset], PacketEB02_Total - CalcOffset );
2273 }
2274 else
2275 client->todc = 1;
2276 break;
2277 }
2278 }
2279 else
2280 client->todc = 1;
2281}
2282
2283void SendDC (int sendChecksum, unsigned char PacketNum, BANANA* client)
2284{
2285 unsigned gc_ofs = 0,
2286 total_guilds = 0;
2287 unsigned friendid;
2288 unsigned short sectionid, _class;
2289 unsigned GCChecksum = 0;
2290 unsigned ch;
2291 unsigned CalcOffset;
2292 int numguilds = 0;
2293 unsigned to_send;
2294
2295 if ((client->guildcard) && (client->sendCheck[SEND_PACKET_DC] < 0x04))
2296 {
2297 client->sendCheck[SEND_PACKET_DC]++;
2298 if (sendChecksum)
2299 {
2300#ifdef NO_SQL
2301 for (ds=0;ds<num_guilds;ds++)
2302 {
2303 if (guild_data[ds]->accountid == client->guildcard)
2304 {
2305 if (total_guilds < 40)
2306 {
2307 friendid = guild_data[ds]->friendid;
2308 sectionid = guild_data[ds]->sectionid;
2309 _class = guild_data[ds]->pclass;
2310 for (ch=0;ch<444;ch++)
2311 client->guildcard_data[gc_ofs+ch] = 0x00;
2312 *(unsigned*) &client->guildcard_data[gc_ofs] = friendid;
2313 memcpy (&client->guildcard_data[gc_ofs+0x04], &guild_data[ds]->friendname, 0x18 );
2314 memcpy (&client->guildcard_data[gc_ofs+0x54], &guild_data[ds]->friendtext, 0xB0 );
2315 client->guildcard_data[gc_ofs+0x104] = 0x01;
2316 client->guildcard_data[gc_ofs+0x106] = (unsigned char) sectionid;
2317 *(unsigned short*) &client->guildcard_data[gc_ofs+0x107] = _class;
2318 // comment @ 0x10C
2319 memcpy (&client->guildcard_data[gc_ofs+0x10C], &guild_data[ds]->comment, 0x44 );
2320 total_guilds++;
2321 gc_ofs += 444;
2322 }
2323 else
2324 break;
2325 }
2326 }
2327#else
2328 sprintf (&myQuery[0], "SELECT * from guild_data WHERE accountid='%u' ORDER BY priority", client->guildcard );
2329 //printf ("MySQL query %s\n", myQuery );
2330
2331 // Check to see if the account has any guild cards.
2332
2333 if ( ! mysql_query ( myData, &myQuery[0] ) )
2334 {
2335
2336 myResult = mysql_store_result ( myData );
2337 numguilds = (int) mysql_num_rows ( myResult );
2338
2339 if (numguilds)
2340 {
2341 while ((myRow = mysql_fetch_row ( myResult )) && (total_guilds < 40))
2342 {
2343 friendid = atoi (myRow[1]);
2344 sectionid = (unsigned short) atoi (myRow[5]);
2345 _class = (unsigned short) atoi (myRow[6]);
2346 for (ch=0;ch<444;ch++)
2347 client->guildcard_data[gc_ofs+ch] = 0x00;
2348 *(unsigned*) &client->guildcard_data[gc_ofs] = friendid;
2349 memcpy (&client->guildcard_data[gc_ofs+0x04], myRow[2], 0x18 );
2350 memcpy (&client->guildcard_data[gc_ofs+0x54], myRow[3], 0xB0 );
2351 client->guildcard_data[gc_ofs+0x104] = 0x01;
2352 client->guildcard_data[gc_ofs+0x106] = (unsigned char) sectionid;
2353 *(unsigned short*) &client->guildcard_data[gc_ofs+0x107] = _class;
2354 // comment @ 0x10C
2355 memcpy (&client->guildcard_data[gc_ofs+0x10C], myRow[7], 0x44 );
2356 total_guilds++;
2357 gc_ofs += 444;
2358 }
2359 }
2360 mysql_free_result ( myResult );
2361 }
2362 else
2363 {
2364 Send1A ("Could not check guild card information.\n\nThere is a problem with the MySQL database.", client);
2365 client->todc = 1;
2366 return;
2367 }
2368#endif
2369
2370 if (total_guilds)
2371 {
2372 ch = 0x1F74 + (total_guilds * 444 );
2373 memcpy ( &PacketDC_Check[0x1F74], &client->guildcard_data[0], total_guilds * 444 );
2374 }
2375 else
2376 ch = 0x1F74;
2377 for (ch;ch<26624;ch++)
2378 PacketDC_Check[ch] = 0x00;
2379 PacketDC_Check[0x06] = 0x01;
2380 PacketDC_Check[0x07] = 0x02;
2381 GCChecksum = (unsigned) CalculateChecksum (&PacketDC_Check[0], 54672);
2382 PacketDC01[0x00] = 0x14;
2383 PacketDC01[0x02] = 0xDC;
2384 PacketDC01[0x03] = 0x01;
2385 PacketDC01[0x08] = 0x01;
2386 PacketDC01[0x0C] = 0x90;
2387 PacketDC01[0x0D] = 0xD5;
2388 *(unsigned *) &PacketDC01[0x10] = GCChecksum;
2389 cipher_ptr = &client->server_cipher;
2390 encryptcopy (client, &PacketDC01[0], sizeof (PacketDC01));
2391 }
2392 else
2393 {
2394 CalcOffset = ((unsigned) PacketNum * 26624);
2395 if (PacketNum > 0x02)
2396 client->todc = 1;
2397 else
2398 {
2399 if (PacketNum < 0x02)
2400 to_send = 26640;
2401 else
2402 to_send = 1440;
2403 *(unsigned short*) &PacketDC02[0x00] = to_send;
2404 PacketDC02[0x02] = 0xDC;
2405 PacketDC02[0x03] = 0x02;
2406 PacketDC02[0x0C] = PacketNum;
2407 memcpy (&client->encryptbuf[0x00], &PacketDC02[0], 0x10);
2408 memcpy (&client->encryptbuf[0x10], &PacketDC_Check[CalcOffset], to_send);
2409 cipher_ptr = &client->server_cipher;
2410 encryptcopy (client, &client->encryptbuf[0x00], to_send);
2411 }
2412 }
2413 }
2414 else
2415 client->todc = 1;
2416}
2417
2418/* Ship start authentication */
2419
2420const unsigned char RC4publicKey[32] = {
2421 103, 196, 247, 176, 71, 167, 89, 233, 200, 100, 044, 209, 190, 231, 83, 42,
2422 6, 95, 151, 28, 140, 243, 130, 61, 107, 234, 243, 172, 77, 24, 229, 156
2423};
2424
2425void ShipSend0F (unsigned char episode, unsigned char part, ORANGE* ship)
2426{
2427 ship->encryptbuf[0x00] = 0x0F;
2428 ship->encryptbuf[0x01] = episode;
2429 ship->encryptbuf[0x02] = part;
2430 switch (episode)
2431 {
2432 case 0x01:
2433 memcpy (&ship->encryptbuf[0x03], &rt_tables_ep1[(sizeof(rt_tables_ep1) >> 3) * part], sizeof(rt_tables_ep1) >> 1);
2434 break;
2435 case 0x02:
2436 memcpy (&ship->encryptbuf[0x03], &rt_tables_ep2[(sizeof(rt_tables_ep2) >> 3) * part], sizeof(rt_tables_ep2) >> 1);
2437 break;
2438 case 0x03:
2439 memcpy (&ship->encryptbuf[0x03], &rt_tables_ep4[(sizeof(rt_tables_ep4) >> 3) * part], sizeof(rt_tables_ep4) >> 1);
2440 break;
2441 }
2442 compressShipPacket ( ship, &ship->encryptbuf[0], 3 + (sizeof (rt_tables_ep1) >> 1) );
2443}
2444
2445void ShipSend10 (ORANGE* ship)
2446{
2447 ship->encryptbuf[0x00] = 0x10;
2448 ship->encryptbuf[0x01] = 0x00;
2449 memcpy (&ship->encryptbuf[0x02], &mob_rate[0], 32);
2450 compressShipPacket ( ship, &ship->encryptbuf[0], 34 );
2451}
2452
2453void ShipSend11 (ORANGE* ship)
2454{
2455 ship->encryptbuf[0x00] = 0x11;
2456 ship->encryptbuf[0x01] = 0x00;
2457 ship->encryptbuf[0x02] = 0x00;
2458 ship->encryptbuf[0x03] = 0x00;
2459 compressShipPacket ( ship, &ship->encryptbuf[0], 4 );
2460}
2461
2462
2463void ShipSend00 (ORANGE* ship)
2464{
2465 unsigned char ch, ch2;
2466
2467 ch2 = 0;
2468
2469 for (ch=0x18;ch<0x58;ch+=2) // change 32 bytes of the key
2470 {
2471 ShipPacket00[ch] = (unsigned char) rand() % 255;
2472 ShipPacket00[ch+1] = (unsigned char) rand() % 255;
2473 ship->key_change [ch2+(ShipPacket00[ch] % 4)] = ShipPacket00[ch+1];
2474 ch2 += 4;
2475 }
2476 compressShipPacket ( ship, &ShipPacket00[0], sizeof (ShipPacket00) );
2477 // use the public key to get the ship's index first...
2478 memcpy (&ship->user_key[0], &RC4publicKey[0], 32 );
2479 prepare_key(&ship->user_key[0], 32, &ship->cs_key);
2480 prepare_key(&ship->user_key[0], 32, &ship->sc_key);
2481 ship->crypt_on = 1;
2482}
2483
2484/* Ship authentication result */
2485
2486void ShipSend02 (unsigned char result, ORANGE* ship)
2487{
2488 unsigned si,ch,shipNum;
2489 ORANGE* tempShip;
2490
2491 ship->encryptbuf [0x00] = 0x02;
2492 ship->encryptbuf [0x01] = result;
2493 si = 0xFFFFFFFF;
2494 if ( result == 0x01 )
2495 {
2496 for (ch=0;ch<serverNumShips;ch++)
2497 {
2498 shipNum = serverShipList[ch];
2499 tempShip = ships[shipNum];
2500 if (tempShip->shipSockfd == ship->shipSockfd)
2501 {
2502 si = shipNum;
2503 ship->shipID = 0xFFFFFFFF - shipNum;
2504 construct0xA0();
2505 break;
2506 }
2507 }
2508 }
2509 *(unsigned *) &ship->encryptbuf[0x02] = si;
2510 *(unsigned *) &ship->encryptbuf[0x06] = *(unsigned *) &ship->shipAddr[0];
2511 *(unsigned *) &ship->encryptbuf[0x0A] = quest_numallows;
2512 memcpy (&ship->encryptbuf[0x0E], quest_allow, quest_numallows * 4 );
2513 si = 0x0E + ( quest_numallows * 4 );
2514 *(unsigned *) &ship->encryptbuf[si] = normalName;
2515 si += 4;
2516 *(unsigned *) &ship->encryptbuf[si] = localName;
2517 si += 4;
2518 *(unsigned *) &ship->encryptbuf[si] = globalName;
2519 si += 4;
2520 compressShipPacket ( ship, &ship->encryptbuf[0x00], si );
2521}
2522
2523void ShipSend08 (unsigned gcn, ORANGE* ship)
2524{
2525 // Tell the other ships this user logged on and to disconnect him/her if they're still active...
2526 ship->encryptbuf[0x00] = 0x08;
2527 ship->encryptbuf[0x01] = 0x00;
2528 *(unsigned *) &ship->encryptbuf[0x02] = gcn;
2529 compressShipPacket ( ship, &ship->encryptbuf[0x00], 0x06 );
2530}
2531
2532
2533void ShipSend0D (unsigned char command, ORANGE* ship)
2534{
2535 unsigned shipNum;
2536 ORANGE* tship;
2537
2538 switch (command)
2539 {
2540 case 0x00:
2541 {
2542 unsigned ch;
2543 // Send ship list data.
2544 unsigned short tempdw;
2545
2546 tempdw = *(unsigned short*) &PacketA0Data[0];
2547 // Ship requesting the ship list.
2548 memcpy (&ship->encryptbuf[0x00], &ship->decryptbuf[0x04], 6);
2549 memcpy (&ship->encryptbuf[0x06], &PacketA0Data[0], tempdw);
2550 ship->encryptbuf[0x01] = 0x01;
2551 tempdw += 6;
2552 for (ch=0;ch<serverNumShips;ch++)
2553 {
2554 shipNum = serverShipList[ch];
2555 tship = ships[shipNum];
2556 if ((tship->shipSockfd >= 0) && (tship->authed == 1))
2557 {
2558 *(unsigned *) &ship->encryptbuf[tempdw] = tship->shipID;
2559 tempdw += 4;
2560 *(unsigned *) &ship->encryptbuf[tempdw] = *(unsigned *) &tship->shipAddr[0];
2561 tempdw += 4;
2562 *(unsigned short*) &ship->encryptbuf[tempdw] = (unsigned short) tship->shipPort;
2563 tempdw += 2;
2564 }
2565 }
2566 //display_packet (&ship->encryptbuf[0x00], tempdw);
2567 compressShipPacket ( ship, &ship->encryptbuf[0x00], tempdw );
2568 }
2569 break;
2570 default:
2571 break;
2572 }
2573}
2574
2575
2576void FixItem (ITEM* i)
2577{
2578 unsigned ch3;
2579
2580 if (i->data[0] == 2) // Mag
2581 {
2582 MAG* m;
2583 short mDefense, mPower, mDex, mMind;
2584 int total_levels;
2585
2586 m = (MAG*) &i->data[0];
2587
2588 if ( m->synchro > 120 )
2589 m->synchro = 120;
2590
2591 if ( m->synchro < 0 )
2592 m->synchro = 0;
2593
2594 if ( m->IQ > 200 )
2595 m->IQ = 200;
2596
2597 if ((m->defense < 0) || (m->power < 0) || (m->dex < 0) || (m->mind < 0))
2598 total_levels = 201;
2599 else
2600 {
2601
2602 mDefense = m->defense / 100;
2603 mPower = m->power / 100;
2604 mDex = m->dex / 100;
2605 mMind = m->mind / 100;
2606
2607 total_levels = mDefense + mPower + mDex + mMind;
2608 }
2609
2610 if ( ( total_levels > 200 ) || ( m->level > 200 ) )
2611 {
2612 // Mag fails IRL, initialize it
2613
2614 m->defense = 500;
2615 m->power = 0;
2616 m->dex = 0;
2617 m->mind = 0;
2618 m->level = 5;
2619 m->blasts = 0;
2620 m->IQ = 0;
2621 m->synchro = 20;
2622 m->mtype = 0;
2623 m->PBflags = 0;
2624 }
2625 }
2626
2627 if (i->data[0] == 0) // Weapon
2628 {
2629 signed char percent_table[6];
2630 signed char percent;
2631 unsigned max_percents, num_percents;
2632 int srank;
2633
2634 if ( ( i->data[1] == 0x33 ) || // SJS & Lame max 2 percents
2635 ( i->data[1] == 0xAB ) )
2636 max_percents = 2;
2637 else
2638 max_percents = 3;
2639
2640 srank = 0;
2641 memset (&percent_table[0], 0, 6);
2642 num_percents = 0;
2643
2644 for (ch3=6;ch3<=4+(max_percents*2);ch3+=2)
2645 {
2646 if ( i->data[ch3] & 128 )
2647 {
2648 srank = 1; // S-Rank
2649 break;
2650 }
2651
2652 if ( ( i->data[ch3] ) &&
2653 ( i->data[ch3] < 0x06 ) )
2654 {
2655 // Percents over 100 or under -100 get set to 0
2656 percent = (char) i->data[ch3+1];
2657 if ( ( percent > 100 ) || ( percent < -100 ) )
2658 percent = 0;
2659 // Save percent
2660 percent_table[i->data[ch3]] =
2661 percent;
2662 }
2663 }
2664
2665 if (!srank)
2666 {
2667 for (ch3=6;ch3<=4+(max_percents*2);ch3+=2)
2668 {
2669 // Reset all %s
2670 i->data[ch3] = 0;
2671 i->data[ch3+1] = 0;
2672 }
2673
2674 for (ch3=1;ch3<=5;ch3++)
2675 {
2676 // Rebuild %s
2677 if ( percent_table[ch3] )
2678 {
2679 i->data[6 + ( num_percents * 2 )] = ch3;
2680 i->data[7 + ( num_percents * 2 )] = (unsigned char) percent_table[ch3];
2681 num_percents ++;
2682 if ( num_percents == max_percents )
2683 break;
2684 }
2685 }
2686 }
2687 }
2688}
2689
2690
2691unsigned char gcname[24*2];
2692unsigned char gctext[176*2];
2693unsigned short gccomment[45] = {0x305C};
2694unsigned char check_key[32];
2695unsigned char check_key2[32];
2696
2697void ShipProcessPacket (ORANGE* ship)
2698{
2699 unsigned cv, shipNum;
2700 int pass;
2701 unsigned char sv;
2702 unsigned shop_checksum;
2703 int key_exists;
2704#ifndef NO_CONNECT_TEST
2705 int tempfd;
2706 struct sockaddr_in sa;
2707#endif
2708
2709 switch (ship->decryptbuf[0x04])
2710 {
2711 case 0x01:
2712 // Authentication
2713 //
2714 // Remember to reconstruct the A0 packet upon a successful authentication!
2715 // Also, reset the playerCount.
2716 //
2717 pass = 1;
2718 for (sv=0x06;sv<0x14;sv++)
2719 if (ship->decryptbuf[sv] != ShipPacket00[sv-0x04])
2720 {
2721 // Yadda
2722 pass = 0;
2723 break;
2724 }
2725 if (pass == 0)
2726 {
2727 printf ("Ship connected but invalid authorization values were received.\n");
2728 ShipSend02 (0x00, ship);
2729 ship->todc = 1;
2730 }
2731 else
2732 {
2733 //unsigned ch, sameIP;
2734 unsigned ch2, shipOK;
2735 //ORANGE* tship;
2736
2737 shipOK = 1;
2738
2739 memcpy (&ship->name[0], &ship->decryptbuf[0x2C], 12);
2740 ship->name[13] = 0x00;
2741 ship->playerCount = *(unsigned *) &ship->decryptbuf[0x38];
2742 if (ship->decryptbuf[0x3C] == 0x00)
2743 *(unsigned *) &ship->shipAddr[0] = *(unsigned *) &ship->listenedAddr[0];
2744 else
2745 *(unsigned *) &ship->shipAddr[0] = *(unsigned *) &ship->decryptbuf[0x3C];
2746 ship->shipAddr[5] = 0;
2747 ship->shipPort = *(unsigned short*) &ship->decryptbuf[0x40];
2748
2749 /*
2750 for (ch=0;ch<serverNumShips;ch++)
2751 {
2752 shipNum = serverShipList[ch];
2753 tship = ships[shipNum];
2754 if ((tship->shipSockfd >= 0) && (tship->authed == 1))
2755 {
2756 sameIP = 1;
2757 for (ch2=0;ch2<4;ch2++)
2758 if (ship->shipAddr[ch2] != tship->shipAddr[ch2])
2759 sameIP = 0;
2760 if (sameIP == 1)
2761 {
2762 printf ("Ship IP address was already registered. Disconnecting...\n");
2763 ShipSend02 (0x02, ship);
2764 ship->todc = 1;
2765 shipOK = 0;
2766 }
2767 }
2768 }*/
2769
2770 if (shipOK == 1)
2771 {
2772 // if (ship->shipAddr[0] == 10) shipOK = 0;
2773 // if ((ship->shipAddr[0] == 192) && (ship->shipAddr[1] == 168)) shipOK = 0;
2774 // if ((ship->shipAddr[0] == 127) && (ship->shipAddr[1] == 0) &&
2775 // (ship->shipAddr[2] == 0) && (ship->shipAddr[3] == 1)) shipOK = 0;
2776
2777 shop_checksum = *(unsigned *) &ship->decryptbuf[0x42];
2778 memcpy (&check_key[0], &ship->decryptbuf[0x4A], 32);
2779
2780 if ( shop_checksum != 0xa3552fda )
2781 {
2782 ShipSend02 ( 0x04, ship );
2783 ship->todc = 1;
2784 shipOK = 0;
2785 }
2786 else
2787 if ( shipOK )
2788 {
2789 ship->key_index = *(unsigned *) &ship->decryptbuf[0x46];
2790
2791 // update max ship key count on the fly
2792#ifdef NO_SQL
2793 max_ship_keys = 0;
2794 for (ds=0;ds<num_shipkeys;ds++)
2795 {
2796 if (ship_data[ds]->idx >= max_ship_keys)
2797 max_ship_keys = ship_data[ds]->idx;
2798 }
2799#else
2800
2801 sprintf (&myQuery[0], "SELECT * from ship_data" );
2802
2803 if ( ! mysql_query ( myData, &myQuery[0] ) )
2804 {
2805 unsigned key_rows;
2806
2807 myResult = mysql_store_result ( myData );
2808 key_rows = (int) mysql_num_rows ( myResult );
2809 max_ship_keys = 0;
2810 while ( key_rows )
2811 {
2812 myRow = mysql_fetch_row ( myResult );
2813 if ( (unsigned) atoi ( myRow[1] ) > max_ship_keys )
2814 max_ship_keys = atoi ( myRow[1] );
2815 key_rows --;
2816 }
2817 mysql_free_result ( myResult );
2818 }
2819 else
2820 {
2821 ship->key_index = 0xFFFF; // MySQL problem, don't allow the ship to connect.
2822 printf ("Unable to query the key database.\n");
2823 }
2824
2825#endif
2826
2827 if ( ( ship->key_index ) && ( ship->key_index <= max_ship_keys ) )
2828 {
2829 if ( keys_in_use [ ship->key_index ] ) // key already in use?
2830 {
2831 ShipSend02 ( 0x06, ship );
2832 ship->todc = 1;
2833 shipOK = 0;
2834 }
2835 else
2836 {
2837 key_exists = 0;
2838#ifdef NO_SQL
2839 ds_found = -1;
2840
2841 for (ds=0;ds<num_shipkeys;ds++)
2842 {
2843 if (ship_data[ds]->idx == ship->key_index)
2844 {
2845 ds_found = ds;
2846 for (ch2=0;ch2<32;ch2++)
2847 if (ship_data[ds]->rc4key[ch2] != check_key[ch2])
2848 {
2849 ds_found = -1;
2850 break;
2851 }
2852 break;
2853 }
2854 }
2855
2856 if (ds_found != -1)
2857 key_exists = 1;
2858 else
2859 {
2860 ShipSend02 (0x05, ship); // Ship key doesn't exist
2861 ship->todc = 1;
2862 shipOK = 0;
2863 }
2864#else
2865 sprintf (&myQuery[0], "SELECT * from ship_data WHERE idx='%u'", ship->key_index );
2866
2867 if ( ! mysql_query ( myData, &myQuery[0] ) )
2868 {
2869 myResult = mysql_store_result ( myData );
2870 key_exists = (int) mysql_num_rows ( myResult );
2871 myRow = mysql_fetch_row ( myResult );
2872 memcpy (&check_key2[0], myRow[0], 32 ); // 1024-bit key
2873 for (ch2=0;ch2<32;ch2++)
2874 if (check_key2[ch2] != check_key[ch2])
2875 {
2876 key_exists = 0;
2877 break;
2878 }
2879 }
2880 else
2881 {
2882 ShipSend02 (0x05, ship); // Could not query MySQL or ship key doesn't exist
2883 mysql_free_result ( myResult );
2884 ship->todc = 1;
2885 shipOK = 0;
2886 }
2887#endif
2888
2889 if ( key_exists )
2890 {
2891#ifndef NO_CONNECT_TEST
2892 tempfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2893
2894 memset (&sa, 0, sizeof(sa));
2895 sa.sin_family = AF_INET;
2896 *(unsigned *) &sa.sin_addr.s_addr = *(unsigned *) &ship->shipAddr[0];
2897 sa.sin_port = htons((unsigned short) ship->shipPort);
2898
2899 if ((tempfd >= 0) && (connect(tempfd, (struct sockaddr*) &sa, sizeof(sa)) >= 0))
2900 {
2901 closesocket ( tempfd );
2902#endif
2903
2904 printf ("Ship %s (%u.%u.%u.%u:%u) has been successfully registered.\nPlayer count: %u\nShip key index: %u\n", ship->name,
2905 ship->shipAddr[0], ship->shipAddr[1], ship->shipAddr[2], ship->shipAddr[3], ship->shipPort,
2906 ship->playerCount, ship->key_index );
2907
2908 ship->authed = 1;
2909 ShipSend02 (0x01, ship); // At this point, we should change keys...
2910
2911#ifdef NO_SQL
2912 memcpy (&ship->user_key[0], &ship_data[ds_found]->rc4key, 128);
2913#else
2914 memcpy (&ship->user_key[0], myRow[0], 128 ); // 1024-bit key
2915 mysql_free_result ( myResult );
2916#endif
2917
2918 // change keys
2919
2920 for (ch2=0;ch2<128;ch2++)
2921 if (ship->key_change[ch2] != -1)
2922 ship->user_key[ch2] = (unsigned char) ship->key_change[ch2]; // update the key
2923
2924 prepare_key(&ship->user_key[0], sizeof(ship->user_key), &ship->cs_key);
2925 prepare_key(&ship->user_key[0], sizeof(ship->user_key), &ship->sc_key);
2926#ifndef NO_CONNECT_TEST
2927 }
2928 else
2929 {
2930 debug ("Could not make a connection to the registering ship... Disconnecting...\n");
2931 ShipSend02 (0x03, ship);
2932 ship->todc = 1;
2933 shipOK = 0;
2934 }
2935#endif
2936
2937 }
2938 else
2939 {
2940 ShipSend02 ( 0x05, ship );
2941 ship->todc = 1;
2942 shipOK = 0;
2943 }
2944
2945 }
2946 }
2947 else
2948 initialize_ship ( ship );
2949 }
2950 }
2951 }
2952 break;
2953 case 0x03:
2954 break;
2955 case 0x04:
2956 switch (ship->decryptbuf[0x05])
2957 {
2958 case 0x00:
2959 {
2960 // Send full player data here.
2961
2962 unsigned guildcard;
2963 unsigned short slotnum;
2964 unsigned size;
2965 int char_exists = 0;
2966 int bank_exists = 0;
2967 int teamid;
2968 unsigned short privlevel;
2969 CHARDATA* PlayerData;
2970 unsigned shipid;
2971 int sockfd;
2972
2973 guildcard = *(unsigned*) &ship->decryptbuf[0x06];
2974 slotnum = *(unsigned short*) &ship->decryptbuf[0x0A];
2975 sockfd = *(int *) &ship->decryptbuf[0x0C];
2976 shipid = *(unsigned*) &ship->decryptbuf[0x10];
2977
2978 ship->encryptbuf[0x00] = 0x04;
2979
2980 *(unsigned*) &ship->encryptbuf[0x02] = *(unsigned*) &ship->decryptbuf[0x06];
2981 *(unsigned short*) &ship->encryptbuf[0x06] = *(unsigned short*) &ship->decryptbuf[0x0A];
2982 *(unsigned*) &ship->encryptbuf[0x08] = *(unsigned*) &ship->decryptbuf[0x0C];
2983
2984#ifdef NO_SQL
2985 size = 0x0C;
2986
2987 ds_found = -1;
2988
2989 for (ds=0;ds<num_characters;ds++)
2990 {
2991 if ((character_data[ds]->guildcard == guildcard) &&
2992 (character_data[ds]->slot == slotnum))
2993 {
2994 ds_found = ds;
2995 break;
2996 }
2997 }
2998
2999 if (ds_found == -1)
3000 ship->encryptbuf[0x01] = 0x02; // fail
3001 else
3002 {
3003 PlayerData = (CHARDATA*) &ship->encryptbuf[0x0C];
3004 memcpy (&ship->encryptbuf[0x0C], &character_data[ds_found]->data, sizeof (CHARDATA) );
3005 size += sizeof (CHARDATA);
3006 ship->encryptbuf[0x01] = 0x01; // success
3007
3008 // Copy common bank into packet.
3009
3010 ds_found = -1;
3011
3012 for (ds=0;ds<num_bankdata;ds++)
3013 {
3014 if (bank_data[ds]->guildcard == guildcard)
3015 {
3016 ds_found = ds;
3017 memcpy (&ship->encryptbuf[0x0C+sizeof(CHARDATA)], &bank_data[ds]->common_bank, sizeof(BANK));
3018 break;
3019 }
3020 }
3021
3022 if (ds_found == -1)
3023 {
3024 // Common bank needs to be created.
3025
3026 bank_data[num_bankdata] = malloc (sizeof(L_BANK_DATA));
3027 bank_data[num_bankdata]->guildcard = guildcard;
3028 memcpy (&bank_data[num_bankdata]->common_bank, &empty_bank, sizeof (BANK));
3029 memcpy (&ship->encryptbuf[0x0C+sizeof(CHARDATA)], &empty_bank, sizeof(BANK));
3030 UpdateDataFile ("bank.dat", num_bankdata, bank_data[num_bankdata], sizeof (L_BANK_DATA), 1);
3031 num_bankdata++;
3032 }
3033
3034 size += sizeof (BANK);
3035
3036 ds_found = 1;
3037 for (ds=0;ds<num_accounts;ds++)
3038 {
3039 if (account_data[ds]->guildcard == guildcard)
3040 {
3041 memcpy (&account_data[ds]->lastchar[0], &PlayerData->name[0], 24);
3042 teamid = account_data[ds]->teamid;
3043 privlevel = account_data[ds]->privlevel;
3044 UpdateDataFile ("account.dat", ds, account_data[ds], sizeof (L_ACCOUNT_DATA), 0);
3045 break;
3046 }
3047 }
3048
3049 if (teamid != -1)
3050 {
3051 //debug ("Retrieving some shit... ");
3052 // Store the team information in the E7 packet...
3053 PlayerData->guildCard2 = PlayerData->guildCard;
3054 PlayerData->teamID = (unsigned) teamid;
3055 PlayerData->privilegeLevel = privlevel;
3056 ds_found = -1;
3057 for (ds=0;ds<num_teams;ds++)
3058 {
3059 if (team_data[ds]->teamid == teamid)
3060 {
3061 PlayerData->teamName[0] = 0x09;
3062 PlayerData->teamName[2] = 0x45;
3063 memcpy ( &PlayerData->teamName[4], team_data[ds]->name, 24 );
3064 memcpy ( &PlayerData->teamFlag[0], team_data[ds]->flag, 2048 );
3065 break;
3066 }
3067 }
3068 }
3069 else
3070 memset ( &PlayerData->guildCard2, 0, 0x83C );
3071
3072 PlayerData->unknown15 = 0x00986C84; // ??
3073 memset ( &PlayerData->teamRewards[0], 0xFF, 4 );
3074 }
3075
3076 compressShipPacket ( ship, &ship->encryptbuf[0x00], size );
3077#else
3078
3079 sprintf (&myQuery[0], "SELECT * from character_data WHERE guildcard='%u' AND slot='%u'", guildcard, slotnum );
3080
3081 //debug ("MySQL query executing ... %s ", &myQuery[0] );
3082
3083 if ( ! mysql_query ( myData, &myQuery[0] ) )
3084 {
3085 myResult = mysql_store_result ( myData );
3086 char_exists = (int) mysql_num_rows ( myResult );
3087
3088 size = 0x0C;
3089
3090 PlayerData = (CHARDATA*) &ship->encryptbuf[0x0C];
3091
3092 if (char_exists)
3093 {
3094 myRow = mysql_fetch_row ( myResult );
3095 memcpy (&ship->encryptbuf[0x0C], myRow[2], sizeof (CHARDATA) );
3096 size += sizeof (CHARDATA);
3097 ship->encryptbuf[0x01] = 0x01; // success
3098
3099 // Get the common bank or create it
3100
3101 sprintf (&myQuery[0], "SELECT * from bank_data WHERE guildcard='%u'", guildcard );
3102
3103 //debug ("MySQL query executing ... %s ", &myQuery[0] );
3104
3105 if ( ! mysql_query ( myData, &myQuery[0] ) )
3106 {
3107 myResult = mysql_store_result ( myData );
3108 bank_exists = (int) mysql_num_rows ( myResult );
3109
3110 if (bank_exists)
3111 {
3112 // Copy bank
3113 myRow = mysql_fetch_row ( myResult );
3114 memcpy (&ship->encryptbuf[0x0C+sizeof(CHARDATA)], myRow[1], sizeof (BANK));
3115 }
3116 else
3117 {
3118 // Create bank
3119 memcpy (&ship->encryptbuf[0x0C+sizeof(CHARDATA)], &empty_bank, sizeof (BANK));
3120 mysql_real_escape_string ( myData, &E7chardata[0], (unsigned char*) &empty_bank, sizeof (BANK) );
3121
3122 sprintf (&myQuery[0], "INSERT into bank_data (guildcard, data) VALUES ('%u','%s')", guildcard, (char*) &E7chardata[0] );
3123 if ( mysql_query ( myData, &myQuery[0] ) )
3124 {
3125 debug ("Could not create common bank for guild card %u.", guildcard);
3126 return;
3127 }
3128 }
3129 }
3130 else
3131 {
3132 // Something goofed up, let's just copy the blank bank.
3133 memcpy (&ship->encryptbuf[0x0C+sizeof(CHARDATA)], &empty_bank, sizeof (BANK));
3134 }
3135
3136 size += sizeof (BANK);
3137
3138
3139 // Update the last used character info...
3140
3141 mysql_real_escape_string ( myData, &E7chardata[0], (unsigned char*) &PlayerData->name[0], 24 );
3142 sprintf (&myQuery[0], "UPDATE account_data SET lastchar = '%s' WHERE guildcard = '%u'", (char*) &E7chardata[0], PlayerData->guildCard );
3143 mysql_query ( myData, &myQuery[0] );
3144
3145 }
3146 else
3147 ship->encryptbuf[0x01] = 0x02; // fail
3148
3149 mysql_free_result ( myResult );
3150
3151 if ( ship->encryptbuf[0x01] != 0x02 )
3152 {
3153 sprintf (&myQuery[0], "SELECT teamid,privlevel from account_data WHERE guildcard='%u'", guildcard );
3154
3155 if ( ! mysql_query ( myData, &myQuery[0] ) )
3156 {
3157 myResult = mysql_store_result ( myData );
3158 myRow = mysql_fetch_row ( myResult );
3159
3160 teamid = atoi (myRow[0]);
3161 privlevel = atoi (myRow[1]);
3162
3163 mysql_free_result ( myResult );
3164
3165 if (teamid != -1)
3166 {
3167 //debug ("Retrieving some shit... ");
3168 // Store the team information in the E7 packet...
3169 PlayerData->guildCard2 = PlayerData->guildCard;
3170 PlayerData->teamID = (unsigned) teamid;
3171 PlayerData->privilegeLevel = privlevel;
3172 sprintf (&myQuery[0], "SELECT name,flag from team_data WHERE teamid = '%i'", teamid);
3173 if ( ! mysql_query ( myData, &myQuery[0] ) )
3174 {
3175 myResult = mysql_store_result ( myData );
3176 myRow = mysql_fetch_row ( myResult );
3177 PlayerData->teamName[0] = 0x09;
3178 PlayerData->teamName[2] = 0x45;
3179 memcpy ( &PlayerData->teamName[4], myRow[0], 24 );
3180 memcpy ( &PlayerData->teamFlag[0], myRow[1], 2048);
3181
3182 mysql_free_result ( myResult );
3183 }
3184 }
3185 else
3186 memset ( &PlayerData->guildCard2, 0, 0x83C );
3187 }
3188 else
3189 ship->encryptbuf[0x01] = 0x02; // fail
3190
3191 PlayerData->unknown15 = 0x00986C84; // ??
3192 memset ( &PlayerData->teamRewards[0], 0xFF, 4 );
3193 }
3194
3195 compressShipPacket ( ship, &ship->encryptbuf[0x00], size );
3196 }
3197 else
3198 debug ("Could not select character information for user %u", guildcard);
3199#endif
3200 }
3201 break;
3202 case 0x02:
3203 {
3204 unsigned guildcard, ch2;
3205 unsigned short slotnum;
3206 CHARDATA* character;
3207 unsigned short maxFace, maxHair, maxHairColorRed, maxHairColorBlue, maxHairColorGreen,
3208 maxCostume, maxSkin, maxHead;
3209
3210 guildcard = *(unsigned*) &ship->decryptbuf[0x06];
3211 slotnum = *(unsigned short*) &ship->decryptbuf[0x0A];
3212
3213 character = (CHARDATA*) &ship->decryptbuf[0x0C];
3214
3215 // Update common bank (A common bank SHOULD exist since they've logged on...)
3216
3217#ifdef NO_SQL
3218
3219 for (ds=0;ds<num_bankdata;ds++)
3220 {
3221 if (bank_data[ds]->guildcard == guildcard)
3222 {
3223 memcpy (&bank_data[ds]->common_bank, &ship->decryptbuf[0x0C+sizeof(CHARDATA)], sizeof (BANK));
3224 UpdateDataFile ("bank.dat", ds, bank_data[ds], sizeof (L_BANK_DATA), 0);
3225 break;
3226 }
3227 }
3228
3229#else
3230
3231 mysql_real_escape_string ( myData, &E7chardata[0], (unsigned char*) &ship->decryptbuf[0x0C+sizeof(CHARDATA)], sizeof (BANK) );
3232 sprintf (&myQuery[0], "UPDATE bank_data set data = '%s' WHERE guildcard = '%u'", (char*) &E7chardata[0], guildcard );
3233 if ( mysql_query ( myData, &myQuery[0] ) )
3234 {
3235 debug ("Could not save common bank for guild card %u.", guildcard);
3236 return;
3237 }
3238
3239#endif
3240 // Repair malformed data
3241
3242 character->name[0] = 0x09; // Filter colored names
3243 character->name[1] = 0x00;
3244 character->name[2] = 0x45;
3245 character->name[3] = 0x00;
3246 character->name[22] = 0x00;
3247 character->name[23] = 0x00; // Truncate names too long.
3248 if (character->level > 199) // Bad levels?
3249 character->level = 199;
3250
3251 if ((character->_class == CLASS_HUMAR) ||
3252 (character->_class == CLASS_HUNEWEARL) ||
3253 (character->_class == CLASS_RAMAR) ||
3254 (character->_class == CLASS_RAMARL) ||
3255 (character->_class == CLASS_FOMARL) ||
3256 (character->_class == CLASS_FONEWM) ||
3257 (character->_class == CLASS_FONEWEARL) ||
3258 (character->_class == CLASS_FOMAR))
3259 {
3260 maxFace = 0x05;
3261 maxHair = 0x0A;
3262 maxHairColorRed = 0xFF;
3263 maxHairColorBlue = 0xFF;
3264 maxHairColorGreen = 0xFF;
3265 maxCostume = 0x11;
3266 maxSkin = 0x03;
3267 maxHead = 0x00;
3268 }
3269 else
3270 {
3271 maxFace = 0x00;
3272 maxHair = 0x00;
3273 maxHairColorRed = 0x00;
3274 maxHairColorBlue = 0x00;
3275 maxHairColorGreen = 0x00;
3276 maxCostume = 0x00;
3277 maxSkin = 0x18;
3278 maxHead = 0x04;
3279 }
3280 character->nameColorTransparency = 0xFF;
3281 if (character->sectionID > 0x09)
3282 character->sectionID = 0x00;
3283 if (character->proportionX > 0x3F800000)
3284 character->proportionX = 0x3F800000;
3285 if (character->proportionY > 0x3F800000)
3286 character->proportionY = 0x3F800000;
3287 if (character->face > maxFace)
3288 character->face = 0x00;
3289 if (character->hair > maxHair)
3290 character->hair = 0x00;
3291 if (character->hairColorRed > maxHairColorRed)
3292 character->hairColorRed = 0x00;
3293 if (character->hairColorBlue > maxHairColorBlue)
3294 character->hairColorBlue = 0x00;
3295 if (character->hairColorGreen > maxHairColorGreen)
3296 character->hairColorGreen = 0x00;
3297 if (character->costume > maxCostume)
3298 character->costume = 0x00;
3299 if (character->skin > maxSkin)
3300 character->skin = 0x00;
3301 if (character->head > maxHead)
3302 character->head = 0x00;
3303
3304 // Let's fix hacked mags and weapons
3305 for (ch2=0;ch2<character->inventoryUse;ch2++)
3306 {
3307 if (character->inventory[ch2].in_use)
3308 FixItem ( &character->inventory[ch2].item );
3309 }
3310
3311 for (ch2=0;ch2<character->bankUse;ch2++)
3312 {
3313 if (character->inventory[ch2].in_use)
3314 FixItem ( (ITEM*) &character->bankInventory[ch2] );
3315 }
3316
3317#ifdef NO_SQL
3318 for (ds=0;ds<num_characters;ds++)
3319 {
3320 if ((character_data[ds]->guildcard == guildcard) &&
3321 (character_data[ds]->slot == slotnum))
3322 {
3323 memcpy (&character_data[ds]->data, &ship->decryptbuf[0x0C], sizeof (CHARDATA));
3324 UpdateDataFile ("character.dat", ds, character_data[ds], sizeof (L_CHARACTER_DATA), 0);
3325 break;
3326 }
3327 }
3328#else
3329 mysql_real_escape_string ( myData, &E7chardata[0], (unsigned char*) &ship->decryptbuf[0x0C], sizeof (CHARDATA) );
3330 sprintf (&myQuery[0], "UPDATE character_data set data = '%s' WHERE guildcard = '%u' AND slot = '%u'", (char*) &E7chardata[0], guildcard, slotnum );
3331 if ( mysql_query ( myData, &myQuery[0] ) )
3332 {
3333 debug ("Could not save character information for guild card user %u (%02x)", guildcard, slotnum);
3334 return;
3335 }
3336 else
3337#endif
3338 {
3339 ship->encryptbuf[0x00] = 0x04;
3340 ship->encryptbuf[0x01] = 0x03;
3341 *(unsigned*) &ship->encryptbuf[0x02] = guildcard;
3342 // Send the OK, data saved.
3343 compressShipPacket ( ship, &ship->encryptbuf[0x00], 0x06 );
3344 }
3345#ifdef NO_SQL
3346 for (ds=0;ds<num_keydata;ds++)
3347 {
3348 if (key_data[ds]->guildcard == guildcard)
3349 {
3350 memcpy (&key_data[ds]->controls, &ship->decryptbuf[0x2FCC], 420);
3351 UpdateDataFile ("keydata.dat", ds, key_data[ds], sizeof (L_KEY_DATA), 0);
3352 break;
3353 }
3354 }
3355#else
3356 mysql_real_escape_string ( myData, &E7chardata[0], (unsigned char*) &ship->decryptbuf[0x2FCC], 420 );
3357 sprintf (&myQuery[0], "UPDATE key_data set controls = '%s' WHERE guildcard = '%u'", (char*) &E7chardata[0], guildcard );
3358 if ( mysql_query ( myData, &myQuery[0] ) )
3359 debug ("Could not save control information for guild card user %u", guildcard);
3360#endif
3361 }
3362 }
3363 break;
3364 case 0x05:
3365 break;
3366 case 0x06:
3367 break;
3368 case 0x07:
3369 switch (ship->decryptbuf[0x05])
3370 {
3371 case 0x00:
3372 // Add a guild card here.
3373 {
3374 unsigned clientGcn, friendGcn;
3375 int gc_priority;
3376#ifdef NO_SQL
3377 unsigned ch2;
3378#endif
3379#ifndef NO_SQL
3380 unsigned num_gcs;
3381 int gc_exists;
3382 unsigned char friendSecID, friendClass;
3383#endif
3384
3385 clientGcn = *(unsigned*) &ship->decryptbuf[0x06];
3386 friendGcn = *(unsigned*) &ship->decryptbuf[0x0A];
3387
3388#ifdef NO_SQL
3389 ds_found = -1;
3390 for (ds=0;ds<num_guilds;ds++)
3391 {
3392 if ((guild_data[ds]->accountid == clientGcn) &&
3393 (guild_data[ds]->friendid == friendGcn))
3394 {
3395 ds_found = ds;
3396 break;
3397 }
3398 }
3399 gc_priority = 0;
3400 ch2 = 0;
3401 free_record = -1;
3402 for (ds=0;ds<num_guilds;ds++)
3403 {
3404 if (guild_data[ds]->accountid == clientGcn)
3405 {
3406 ch2++;
3407 if (guild_data[ds]->priority > gc_priority)
3408 gc_priority = guild_data[ds]->priority;
3409 }
3410 if (guild_data[ds]->accountid == 0)
3411 free_record = ds;
3412 }
3413 gc_priority++;
3414 if ( ( ch2 < 40 ) || ( ds_found != -1 ) )
3415 {
3416 if ( ds_found != -1 )
3417 new_record = 0;
3418 else
3419 {
3420 if (free_record != -1)
3421 ds_found = free_record;
3422 else
3423 {
3424 new_record = 1;
3425 ds_found = num_guilds;
3426 guild_data[num_guilds++] = malloc ( sizeof (L_GUILD_DATA) );
3427 }
3428 }
3429
3430 guild_data[ds_found]->sectionid = ship->decryptbuf[0xD6];
3431 guild_data[ds_found]->pclass = ship->decryptbuf[0xD7];
3432
3433 gccomment[44] = 0x0000;
3434
3435 guild_data[ds_found]->accountid = clientGcn;
3436 guild_data[ds_found]->friendid = friendGcn;
3437 guild_data[ds_found]->reserved = 257;
3438 memcpy (&guild_data[ds_found]->friendname[0], &ship->decryptbuf[0x0E], 24);
3439 memcpy (&guild_data[ds_found]->friendtext[0], &ship->decryptbuf[0x26], 176);
3440 memcpy (&guild_data[ds_found]->comment[0], &gccomment[0], 90);
3441 guild_data[ds_found]->priority = gc_priority;
3442 UpdateDataFile ("guild.dat", ds_found, guild_data[ds_found], sizeof(L_GUILD_DATA), new_record);
3443 }
3444 else
3445 {
3446 // Card list full.
3447 ship->encryptbuf[0x00] = 0x07;
3448 ship->encryptbuf[0x01] = 0x00;
3449 *(unsigned*) &ship->encryptbuf[0x02] = clientGcn;
3450 compressShipPacket (ship, &ship->encryptbuf[0x00], 6);
3451 }
3452
3453#else
3454
3455 // Delete guild card if it exists...
3456
3457 sprintf (&myQuery[0], "SELECT * from guild_data WHERE accountid='%u' AND friendid='%u'", clientGcn, friendGcn );
3458
3459 //printf ("MySQL query %s\n", myQuery );
3460
3461 if ( ! mysql_query ( myData, &myQuery[0] ) )
3462 {
3463 myResult = mysql_store_result ( myData );
3464 gc_exists = (int) mysql_num_rows ( myResult );
3465 mysql_free_result ( myResult );
3466 if ( gc_exists )
3467 {
3468 sprintf (&myQuery[0], "DELETE from guild_data WHERE accountid='%u' AND friendid='%u'", clientGcn, friendGcn );
3469 mysql_query ( myData, &myQuery[0] );
3470 }
3471 }
3472 else
3473 {
3474 debug ("Could not delete existing guild card information for user %u", clientGcn);
3475 return;
3476 }
3477
3478 gc_priority = 1;
3479
3480 sprintf (&myQuery[0], "SELECT * from guild_data WHERE accountid='%u'", clientGcn );
3481
3482 if ( ! mysql_query ( myData, &myQuery[0] ) )
3483 {
3484 myResult = mysql_store_result ( myData );
3485
3486 num_gcs = (int) mysql_num_rows ( myResult );
3487 mysql_free_result ( myResult );
3488
3489 if (num_gcs)
3490 {
3491 sprintf (&myQuery[0], "SELECT * from guild_data WHERE accountid='%u' ORDER by priority DESC", clientGcn );
3492 if ( ! mysql_query ( myData, &myQuery[0] ) )
3493 {
3494 myResult = mysql_store_result ( myData );
3495 myRow = mysql_fetch_row ( myResult );
3496 gc_priority = atoi ( myRow[8] ) + 1;
3497 mysql_free_result ( myResult );
3498 }
3499 }
3500 }
3501 else
3502 {
3503 debug ("Could not select existing guild card information for user %u", clientGcn);
3504 return;
3505 }
3506
3507 if ( num_gcs < 40 )
3508 {
3509 mysql_real_escape_string (myData, &gcname[0], &ship->decryptbuf[0x0E], 24);
3510 mysql_real_escape_string (myData, &gctext[0], &ship->decryptbuf[0x26], 176);
3511
3512 friendSecID = ship->decryptbuf[0xD6];
3513 friendClass = ship->decryptbuf[0xD7];
3514
3515 gccomment[44] = 0x0000;
3516
3517 sprintf (&myQuery[0], "INSERT INTO guild_data (accountid,friendid,friendname,friendtext,sectionid,class,comment,priority) VALUES ('%u','%u','%s','%s','%u','%u','%s','%u')",
3518 clientGcn, friendGcn, (char*) &gcname[0], (char*) &gctext[0], friendSecID, friendClass, (char*) &gccomment[0], gc_priority );
3519
3520 if ( mysql_query ( myData, &myQuery[0] ) )
3521 debug ("Could not insert guild card into database for user %u", clientGcn);
3522 }
3523 else
3524 {
3525 // Card list full.
3526 ship->encryptbuf[0x00] = 0x07;
3527 ship->encryptbuf[0x01] = 0x00;
3528 *(unsigned*) &ship->encryptbuf[0x02] = clientGcn;
3529 compressShipPacket (ship, &ship->encryptbuf[0x00], 6);
3530 }
3531#endif
3532 }
3533 break;
3534 case 0x01:
3535 // Delete a guild card here.
3536 {
3537 unsigned clientGcn, deletedGcn;
3538
3539 clientGcn = *(unsigned*) &ship->decryptbuf[0x06];
3540 deletedGcn = *(unsigned*) &ship->decryptbuf[0x0A];
3541
3542#ifdef NO_SQL
3543 for (ds=0;ds<num_guilds;ds++)
3544 {
3545 if ((guild_data[ds]->accountid == clientGcn) &&
3546 (guild_data[ds]->friendid == deletedGcn))
3547 {
3548 guild_data[ds]->accountid = 0;
3549 UpdateDataFile ("guild.dat", ds, guild_data[ds], sizeof (L_GUILD_DATA), 0);
3550 break;
3551 }
3552 }
3553#else
3554
3555 sprintf (&myQuery[0], "DELETE from guild_data WHERE accountid = '%u' AND friendid = '%u'", clientGcn, deletedGcn );
3556 if ( mysql_query ( myData, &myQuery[0] ) )
3557 debug ("Could not delete guild card for user %u", clientGcn );
3558#endif
3559 }
3560 break;
3561 case 0x02:
3562 // Modify guild card comment.
3563 {
3564 unsigned clientGcn, friendGcn;
3565
3566 clientGcn = *(unsigned*) &ship->decryptbuf[0x06];
3567 friendGcn = *(unsigned*) &ship->decryptbuf[0x0A];
3568#ifdef NO_SQL
3569 for (ds=0;ds<num_guilds;ds++)
3570 {
3571 if ((guild_data[ds]->accountid == clientGcn) &&
3572 (guild_data[ds]->friendid == friendGcn))
3573 {
3574 memcpy (&guild_data[ds]->comment[0], &ship->decryptbuf[0x0E], 0x44);
3575 guild_data[ds]->comment[34] = 0; // ??
3576 UpdateDataFile ("guild.dat", ds, guild_data[ds], sizeof(L_GUILD_DATA), 0);
3577 }
3578 }
3579#else
3580 mysql_real_escape_string (myData, &gctext[0], &ship->decryptbuf[0x0E], 0x44);
3581
3582 sprintf (&myQuery[0], "UPDATE guild_data set comment = '%s' WHERE accountid = '%u' AND friendid = '%u'", (char*) &gctext[0], clientGcn, friendGcn );
3583
3584 if ( mysql_query ( myData, &myQuery[0] ) )
3585 debug ("Could not update guild card comment for user %u", clientGcn );
3586#endif
3587 }
3588 break;
3589 case 0x03:
3590 // Sort guild card
3591 {
3592 unsigned clientGcn, gcn1, gcn2;
3593 int priority1, priority2, priority_save;
3594#ifdef NO_SQL
3595 L_GUILD_DATA tempgc;
3596#endif
3597
3598 priority1 = -1;
3599 priority2 = -1;
3600
3601 clientGcn = *(unsigned*) &ship->decryptbuf[0x06];
3602 gcn1 = *(unsigned*) &ship->decryptbuf[0x0A];
3603 gcn2 = *(unsigned*) &ship->decryptbuf[0x0E];
3604
3605#ifdef NO_SQL
3606 for (ds=0;ds<num_guilds;ds++)
3607 {
3608 if ((guild_data[ds]->accountid == clientGcn) &&
3609 (guild_data[ds]->friendid == gcn1))
3610 {
3611 priority1 = guild_data[ds]->priority;
3612 ds_found = ds;
3613 break;
3614 }
3615 }
3616#else
3617 sprintf (&myQuery[0], "SELECT * from guild_data WHERE accountid='%u' AND friendid='%u'", clientGcn, gcn1 );
3618
3619 if ( ! mysql_query ( myData, &myQuery[0] ) )
3620 {
3621 myResult = mysql_store_result ( myData );
3622 if ( mysql_num_rows ( myResult ) )
3623 {
3624 myRow = mysql_fetch_row ( myResult );
3625 priority1 = atoi (myRow[8]);
3626 }
3627 mysql_free_result ( myResult );
3628 }
3629 else
3630 {
3631 debug ("Could not select existing guild card information for user %u", clientGcn);
3632 return;
3633 }
3634#endif
3635
3636#ifdef NO_SQL
3637 for (ds=0;ds<num_guilds;ds++)
3638 {
3639 if ((guild_data[ds]->accountid == clientGcn) &&
3640 (guild_data[ds]->friendid == gcn2))
3641 {
3642 priority2 = guild_data[ds]->priority;
3643 ds2 = ds;
3644 break;
3645 }
3646 }
3647#else
3648 sprintf (&myQuery[0], "SELECT * from guild_data WHERE accountid='%u' AND friendid='%u'", clientGcn, gcn2 );
3649
3650 if ( ! mysql_query ( myData, &myQuery[0] ) )
3651 {
3652 myResult = mysql_store_result ( myData );
3653 if ( mysql_num_rows ( myResult ) )
3654 {
3655 myRow = mysql_fetch_row ( myResult );
3656 priority2 = atoi (myRow[8]);
3657 }
3658 mysql_free_result ( myResult );
3659 }
3660 else
3661 {
3662 debug ("Could not select existing guild card information for user %u", clientGcn);
3663 return;
3664 }
3665#endif
3666
3667 if ((priority1 != -1) && (priority2 != -1))
3668 {
3669 priority_save = priority1;
3670 priority1 = priority2;
3671 priority2 = priority_save;
3672
3673#ifdef NO_SQL
3674 guild_data[ds_found]->priority = priority2;
3675 guild_data[ds2]->priority = priority_save;
3676 UpdateDataFile ("guild.dat", ds_found, guild_data[ds2], sizeof (L_GUILD_DATA), 0);
3677 UpdateDataFile ("guild.dat", ds2, guild_data[ds_found], sizeof (L_GUILD_DATA), 0);
3678 memcpy (&tempgc, guild_data[ds_found], sizeof (L_GUILD_DATA));
3679 memcpy (guild_data[ds_found], guild_data[ds2], sizeof (L_GUILD_DATA));
3680 memcpy (guild_data[ds2], &tempgc, sizeof (L_GUILD_DATA));
3681#else
3682 sprintf (&myQuery[0], "UPDATE guild_data SET priority = '%u' WHERE accountid = '%u' AND friendid = '%u'", priority1, clientGcn, gcn1 );
3683 if ( mysql_query ( myData, &myQuery[0] ) )
3684 debug ("Could not update guild card sort information for user %u", clientGcn);
3685 sprintf (&myQuery[0], "UPDATE guild_data SET priority = '%u' WHERE accountid = '%u' AND friendid = '%u'", priority2, clientGcn, gcn2 );
3686 if ( mysql_query ( myData, &myQuery[0] ) )
3687 debug ("Could not update guild card sort information for user %u", clientGcn);
3688#endif
3689 }
3690 }
3691 break;
3692 }
3693 break;
3694 case 0x08:
3695 switch (ship->decryptbuf[0x05])
3696 {
3697 case 0x01:
3698 // Ship requesting a guild search
3699 {
3700 unsigned clientGcn, friendGcn, ch, teamid;
3701 int gc_exists = 0;
3702 ORANGE* tship;
3703
3704 friendGcn = *(unsigned*) &ship->decryptbuf[0x06];
3705 clientGcn = *(unsigned*) &ship->decryptbuf[0x0A];
3706 teamid = *(unsigned*) &ship->decryptbuf[0x12];
3707
3708 // First let's be sure our friend has this person's guild card....
3709
3710#ifdef NO_SQL
3711 for (ds=0;ds<num_guilds;ds++)
3712 {
3713 if ((guild_data[ds]->accountid == clientGcn) &&
3714 (guild_data[ds]->friendid == friendGcn))
3715 {
3716 gc_exists = 1;
3717 break;
3718 }
3719 }
3720#else
3721
3722 sprintf (&myQuery[0], "SELECT * from guild_data WHERE accountid='%u' AND friendid='%u'", clientGcn, friendGcn );
3723
3724 //printf ("MySQL query %s\n", myQuery );
3725
3726 if ( ! mysql_query ( myData, &myQuery[0] ) )
3727 {
3728 myResult = mysql_store_result ( myData );
3729 gc_exists = (int) mysql_num_rows ( myResult );
3730 mysql_free_result ( myResult );
3731 }
3732 else
3733 {
3734 debug ("Could not select existing guild card information for user %u", clientGcn);
3735 return;
3736 }
3737#endif
3738
3739#ifdef NO_SQL
3740 if ( ( gc_exists == 0 ) && ( teamid != 0 ) )
3741 {
3742 for (ds=0;ds<num_accounts;ds++)
3743 {
3744 if ((account_data[ds]->guildcard == friendGcn) &&
3745 (account_data[ds]->teamid == teamid))
3746 {
3747 gc_exists = 1;
3748 break;
3749 }
3750 }
3751 }
3752#else
3753 if ( ( gc_exists == 0 ) && ( teamid != 0 ) )
3754 {
3755 // Well, they don't appear to have this person's guild card... so let's check the team list...
3756 sprintf (&myQuery[0], "SELECT * from account_data WHERE guildcard='%u' AND teamid='%u'", friendGcn, teamid );
3757
3758 //printf ("MySQL query %s\n", myQuery );
3759
3760 if ( ! mysql_query ( myData, &myQuery[0] ) )
3761 {
3762 myResult = mysql_store_result ( myData );
3763 gc_exists = (int) mysql_num_rows ( myResult );
3764 mysql_free_result ( myResult );
3765 }
3766 else
3767 {
3768 debug ("Could not select account information for user %u", friendGcn);
3769 return;
3770 }
3771 }
3772#endif
3773
3774 if ( gc_exists )
3775 {
3776 // OK! Let's tell the ships to do the search...
3777 for (ch=0;ch<serverNumShips;ch++)
3778 {
3779 shipNum = serverShipList[ch];
3780 tship = ships[shipNum];
3781 if ((tship->shipSockfd >= 0) && (tship->authed == 1))
3782 compressShipPacket ( tship, &ship->decryptbuf[0x04], 0x1D);
3783 }
3784 }
3785 }
3786 break;
3787 case 0x02:
3788 // Got a hit on a guild search
3789 cv = *(unsigned*) &ship->decryptbuf[0x0A];
3790 cv--;
3791 if (cv < serverMaxShips)
3792 {
3793 ORANGE* tship;
3794
3795 tship = ships[cv];
3796 if ((tship->shipSockfd >= 0) && (tship->authed == 1))
3797 compressShipPacket ( tship, &ship->decryptbuf[0x04], 0x140 );
3798 }
3799 break;
3800 case 0x03:
3801 // Send mail
3802 {
3803 unsigned clientGcn, friendGcn, ch, teamid;
3804 int gc_exists = 0;
3805 ORANGE* tship;
3806
3807 friendGcn = *(unsigned*) &ship->decryptbuf[0x36];
3808 clientGcn = *(unsigned*) &ship->decryptbuf[0x12];
3809 teamid = *(unsigned*) &ship->decryptbuf[0x462];
3810
3811 // First let's be sure our friend has this person's guild card....
3812
3813#ifdef NO_SQL
3814 for (ds=0;ds<num_guilds;ds++)
3815 {
3816 if ((guild_data[ds]->accountid == clientGcn) &&
3817 (guild_data[ds]->friendid == friendGcn))
3818 {
3819 gc_exists = 1;
3820 break;
3821 }
3822 }
3823#else
3824 sprintf (&myQuery[0], "SELECT * from guild_data WHERE accountid='%u' AND friendid='%u'", clientGcn, friendGcn );
3825
3826 //printf ("MySQL query %s\n", myQuery );
3827
3828 if ( ! mysql_query ( myData, &myQuery[0] ) )
3829 {
3830 myResult = mysql_store_result ( myData );
3831 gc_exists = (int) mysql_num_rows ( myResult );
3832 mysql_free_result ( myResult );
3833 }
3834 else
3835 {
3836 debug ("Could not select existing guild card information for user %u", clientGcn);
3837 return;
3838 }
3839#endif
3840
3841
3842#ifdef NO_SQL
3843 if ( ( gc_exists == 0 ) && ( teamid != 0 ) )
3844 {
3845 for (ds=0;ds<num_accounts;ds++)
3846 {
3847 if ((account_data[ds]->guildcard == friendGcn) &&
3848 (account_data[ds]->teamid == teamid))
3849 {
3850 gc_exists = 1;
3851 break;
3852 }
3853 }
3854 }
3855#else
3856 if ( ( gc_exists == 0 ) && ( teamid != 0 ) )
3857 {
3858 // Well, they don't appear to have this person's guild card... so let's check the team list...
3859 sprintf (&myQuery[0], "SELECT * from account_data WHERE guildcard='%u' AND teamid='%u'", friendGcn, teamid );
3860
3861 //printf ("MySQL query %s\n", myQuery );
3862
3863 if ( ! mysql_query ( myData, &myQuery[0] ) )
3864 {
3865 myResult = mysql_store_result ( myData );
3866 gc_exists = (int) mysql_num_rows ( myResult );
3867 mysql_free_result ( myResult );
3868 }
3869 else
3870 {
3871 debug ("Could not select existing account information for user %u", friendGcn);
3872 return;
3873 }
3874 }
3875#endif
3876
3877 if ( gc_exists )
3878 {
3879 // OK! Let's tell the ships to do the search...
3880 for (ch=0;ch<serverNumShips;ch++)
3881 {
3882 shipNum = serverShipList[ch];
3883 tship = ships[shipNum];
3884 if ((tship->shipSockfd >= 0) && (tship->authed == 1))
3885 compressShipPacket ( tship, &ship->decryptbuf[0x04], 0x45E );
3886 }
3887 }
3888 }
3889 break;
3890 case 0x04:
3891 // Flag account
3892 break;
3893 case 0x05:
3894 // Ban guild card.
3895 break;
3896 case 0x06:
3897 // Ban IP address.
3898 break;
3899 case 0x07:
3900 // Ban HW info.
3901 break;
3902 }
3903 break;
3904 case 0x09:
3905 // Reserved for team functions.
3906 switch (ship->decryptbuf[0x05])
3907 {
3908 case 0x00:
3909 {
3910 // Create Team
3911 //
3912 // 0x06 = Team name (pre-stripped)
3913 // 0x1E = Guild card of creator
3914 //
3915 //
3916 unsigned char CreateResult;
3917 int team_exists, teamid;
3918 unsigned highid;
3919 unsigned gcn;
3920#ifndef NO_SQL
3921 unsigned char TeamNameCheck[50];
3922#else
3923 unsigned short char_check;
3924 int match;
3925#endif
3926
3927 gcn = *(unsigned*) &ship->decryptbuf[0x1E];
3928 // First check to see if the team exists...
3929
3930 team_exists = 0;
3931 highid = 0;
3932
3933#ifdef NO_SQL
3934 free_record = -1;
3935 for (ds=0;ds<num_teams;ds++)
3936 {
3937 if (team_data[ds]->owner == 0)
3938 free_record = ds;
3939 if (team_data[ds]->teamid >= highid)
3940 highid = team_data[ds]->teamid;
3941 match = 1;
3942 for (ds2=0;ds2<12;ds2++)
3943 {
3944 char_check = *(unsigned short*) &ship->decryptbuf[0x06+(ds2*2)];
3945 if (team_data[ds]->name[ds2] != char_check)
3946 {
3947 match = 0;
3948 break;
3949 }
3950 if (char_check == 0x0000)
3951 break;
3952 }
3953 if (match)
3954 {
3955 team_exists = 1;
3956 break;
3957 }
3958 }
3959#else
3960 mysql_real_escape_string (myData, &TeamNameCheck[0], &ship->decryptbuf[0x06], 24);
3961 sprintf (&myQuery[0], "SELECT * from team_data WHERE name='%s'", (char*) &TeamNameCheck[0] );
3962 if ( ! mysql_query ( myData, &myQuery[0] ) )
3963 {
3964 myResult = mysql_store_result ( myData );
3965 team_exists = (int) mysql_num_rows ( myResult );
3966 mysql_free_result ( myResult );
3967 }
3968 else
3969 CreateResult = 1;
3970#endif
3971
3972 if ( !team_exists )
3973 {
3974 // It doesn't... but it will now. :)
3975#ifdef NO_SQL
3976 if (free_record != -1)
3977 {
3978 new_record = 0;
3979 ds_found = free_record;
3980 }
3981 else
3982 {
3983 new_record = 1;
3984 ds_found = num_teams;
3985 team_data[num_teams++] = malloc ( sizeof (L_TEAM_DATA) );
3986 }
3987 memcpy (&team_data[ds_found]->name[0], &ship->decryptbuf[0x06], 24);
3988 memcpy (&team_data[ds_found]->flag, &DefaultTeamFlag, 2048);
3989 team_data[ds_found]->owner = gcn;
3990 highid++;
3991 team_data[ds_found]->teamid = teamid = highid;
3992 UpdateDataFile ("team.dat", ds_found, team_data[ds_found], sizeof (L_TEAM_DATA), new_record);
3993 CreateResult = 0;
3994 for (ds=0;ds<num_accounts;ds++)
3995 {
3996 if (account_data[ds]->guildcard == gcn)
3997 {
3998 account_data[ds]->teamid = highid;
3999 account_data[ds]->privlevel = 0x40;
4000 UpdateDataFile ("account.dat", ds, account_data[ds], sizeof (L_ACCOUNT_DATA), 0);
4001 break;
4002 }
4003 }
4004#else
4005 sprintf (&myQuery[0], "INSERT into team_data (name,owner,flag) VALUES ('%s','%u','%s')", (char*) &TeamNameCheck[0], gcn, (char*) &DefaultTeamFlagSlashes[0]);
4006 if ( ! mysql_query ( myData, &myQuery[0] ) )
4007 {
4008 teamid = (unsigned) mysql_insert_id( myData );
4009 sprintf (&myQuery[0], "UPDATE account_data SET teamid='%u', privlevel='%u' WHERE guildcard='%u'", teamid, 0x40, gcn );
4010 if ( mysql_query ( myData, &myQuery[0] ) )
4011 CreateResult = 1;
4012 else
4013 CreateResult = 0;
4014 }
4015 else
4016 CreateResult = 1;
4017#endif
4018 }
4019 else
4020 CreateResult = 2;
4021 // 1 = MySQL error
4022 // 2 = Team Exists
4023 ship->encryptbuf[0x00] = 0x09;
4024 ship->encryptbuf[0x01] = 0x00;
4025 ship->encryptbuf[0x02] = CreateResult;
4026 *(unsigned*) &ship->encryptbuf[0x03] = gcn;
4027 memcpy (&ship->encryptbuf[0x07], &DefaultTeamFlag[0], 0x800);
4028 memcpy (&ship->encryptbuf[0x807], &ship->decryptbuf[0x06], 24);
4029 *(unsigned*) &ship->encryptbuf[0x81F] = teamid;
4030 compressShipPacket (ship, &ship->encryptbuf[0x00], 0x823);
4031 }
4032 break;
4033 case 0x01:
4034 // Update Team Flag
4035 //
4036 // 0x06 = Flag (2048/0x800) bytes
4037 // 0x806 = Guild card of invoking person
4038 //
4039 {
4040 unsigned teamid;
4041
4042 teamid = *(unsigned*) &ship->decryptbuf[0x806];
4043#ifdef NO_SQL
4044 for (ds=0;ds<num_teams;ds++)
4045 {
4046 if (team_data[ds]->teamid == teamid)
4047 {
4048 memcpy (&team_data[ds]->flag, &ship->decryptbuf[0x06], 0x800);
4049 ship->encryptbuf[0x00] = 0x09;
4050 ship->encryptbuf[0x01] = 0x01;
4051 ship->encryptbuf[0x02] = 0x01;
4052 *(unsigned*) &ship->encryptbuf[0x03] = teamid;
4053 memcpy ( &ship->encryptbuf[0x07], &ship->decryptbuf[0x06], 0x800 );
4054 compressShipPacket (ship, &ship->encryptbuf[0x00], 0x807);
4055 UpdateDataFile ("team.dat", ds, team_data[ds], sizeof (L_TEAM_DATA), 0);
4056 break;
4057 }
4058 }
4059#else
4060 mysql_real_escape_string ( myData, &FlagSlashes[0], &ship->decryptbuf[0x06], 0x800 );
4061 sprintf ( &myQuery[0], "UPDATE team_data SET flag='%s' WHERE teamid='%u'", (char*) &FlagSlashes[0], teamid );
4062 if (! mysql_query ( myData, &myQuery[0] ) )
4063 {
4064 ship->encryptbuf[0x00] = 0x09;
4065 ship->encryptbuf[0x01] = 0x01;
4066 ship->encryptbuf[0x02] = 0x01;
4067 *(unsigned*) &ship->encryptbuf[0x03] = teamid;
4068 memcpy ( &ship->encryptbuf[0x07], &ship->decryptbuf[0x06], 0x800 );
4069 compressShipPacket (ship, &ship->encryptbuf[0x00], 0x807);
4070 }
4071 else
4072 {
4073 debug ("Could not update team flag for team %u", teamid);
4074 return;
4075 }
4076#endif
4077
4078 }
4079 break;
4080 case 0x02:
4081 // Dissolve Team
4082 //
4083 // 0x06 = Guild card of invoking person
4084 //
4085 {
4086 unsigned teamid;
4087
4088 teamid = *(unsigned*) &ship->decryptbuf[0x06];
4089#ifdef NO_SQL
4090 for (ds=0;ds<num_teams;ds++)
4091 {
4092 if (team_data[ds]->teamid == teamid)
4093 {
4094 team_data[ds]->teamid = 0;
4095 team_data[ds]->owner = 0;
4096 UpdateDataFile ("team.dat", ds, team_data[ds], sizeof (L_TEAM_DATA), 0);
4097 break;
4098 }
4099 }
4100
4101 for (ds=0;ds<num_accounts;ds++)
4102 {
4103 if (account_data[ds]->teamid == teamid)
4104 account_data[ds]->teamid = -1;
4105 UpdateDataFile ("account.dat", ds, account_data[ds], sizeof (L_ACCOUNT_DATA), 0);
4106 }
4107#else
4108 sprintf (&myQuery[0], "DELETE from team_data WHERE teamid='%u'", teamid );
4109 mysql_query (myData, &myQuery[0]);
4110 sprintf (&myQuery[0], "UPDATE account_data SET teamid='-1' WHERE teamid='%u'", teamid);
4111 mysql_query (myData, &myQuery[0]);
4112#endif
4113 ship->encryptbuf[0x00] = 0x09;
4114 ship->encryptbuf[0x01] = 0x02;
4115 ship->encryptbuf[0x02] = 0x01;
4116 *(unsigned*) &ship->encryptbuf[0x03] = teamid;
4117 compressShipPacket (ship, &ship->encryptbuf[0x00], 7);
4118 }
4119 break;
4120 case 0x03:
4121 // Remove member
4122 //
4123 // 0x06 = Team ID
4124 // 0x0A = Guild card
4125 //
4126 {
4127 unsigned gcn, teamid;
4128
4129 teamid = *(unsigned*) &ship->decryptbuf[0x06];
4130 gcn = *(unsigned*) &ship->decryptbuf[0x0A];
4131#ifdef NO_SQL
4132 for (ds=0;ds<num_accounts;ds++)
4133 {
4134 if ((account_data[ds]->guildcard == gcn) &&
4135 (account_data[ds]->teamid == teamid))
4136 {
4137 account_data[ds]->teamid = -1;
4138 UpdateDataFile ("account.dat", ds, account_data[ds], sizeof (L_ACCOUNT_DATA), 0);
4139 break;
4140 }
4141 }
4142#else
4143 sprintf (&myQuery[0], "UPDATE account_data SET teamid='-1' WHERE guildcard='%u' AND teamid = '%u'", gcn, teamid);
4144 mysql_query (myData, &myQuery[0]);
4145#endif
4146 ship->encryptbuf[0x00] = 0x09;
4147 ship->encryptbuf[0x01] = 0x03;
4148 ship->encryptbuf[0x02] = 0x01;
4149 compressShipPacket (ship, &ship->encryptbuf[0x00], 3);
4150 }
4151 break;
4152 case 0x04:
4153 // Team Chat
4154 {
4155 ORANGE* tship;
4156 unsigned size,ch;
4157
4158 size = *(unsigned*) &ship->decryptbuf[0x00];
4159 size -= 4;
4160
4161 // Just pass the packet along...
4162 for (ch=0;ch<serverNumShips;ch++)
4163 {
4164 shipNum = serverShipList[ch];
4165 tship = ships[shipNum];
4166 if ((tship->shipSockfd >= 0) && (tship->authed == 1))
4167 compressShipPacket ( tship, &ship->decryptbuf[0x04], size );
4168 }
4169 }
4170 break;
4171 case 0x05:
4172 // Request team list
4173 {
4174 unsigned teamid, packet_offset;
4175 int num_mates;
4176#ifndef NO_SQL
4177 int ch;
4178 unsigned guildcard, privlevel;
4179#else
4180 unsigned save_offset;
4181#endif
4182
4183
4184 teamid = *(unsigned*) &ship->decryptbuf[0x06];
4185 ship->encryptbuf[0x00] = 0x09;
4186 ship->encryptbuf[0x01] = 0x05;
4187 *(unsigned*) &ship->encryptbuf[0x02] = teamid;
4188 *(unsigned*) &ship->encryptbuf[0x06] = *(unsigned*) &ship->decryptbuf[0x0A];
4189 // @ 0x0A store the size
4190 ship->encryptbuf[0x0C] = 0xEA;
4191 ship->encryptbuf[0x0D] = 0x09;
4192 memset (&ship->encryptbuf[0x0E], 0, 4);
4193 packet_offset = 0x12;
4194#ifdef NO_SQL
4195 save_offset = packet_offset;
4196 packet_offset += 4;
4197 num_mates = 0;
4198 for (ds=0;ds<num_accounts;ds++)
4199 {
4200 if (account_data[ds]->teamid == teamid)
4201 {
4202 num_mates++;
4203 *(unsigned*) &ship->encryptbuf[packet_offset] = num_mates;
4204 packet_offset += 4;
4205 *(unsigned*) &ship->encryptbuf[packet_offset] = account_data[ds]->privlevel;
4206 packet_offset += 4;
4207 *(unsigned*) &ship->encryptbuf[packet_offset] = account_data[ds]->guildcard;
4208 packet_offset += 4;
4209 memcpy (&ship->encryptbuf[packet_offset], &account_data[ds]->lastchar, 24);
4210 packet_offset += 24;
4211 memset (&ship->encryptbuf[packet_offset], 0, 8);
4212 packet_offset += 8;
4213 }
4214 }
4215 *(unsigned*) &ship->encryptbuf[save_offset] = num_mates;
4216 packet_offset -= 0x0A;
4217 *(unsigned short*) &ship->encryptbuf[0x0A] = (unsigned short) packet_offset;
4218 packet_offset += 0x0A;
4219 compressShipPacket (ship, &ship->encryptbuf[0x00], packet_offset);
4220#else
4221 sprintf (&myQuery[0], "SELECT guildcard,privlevel,lastchar from account_data WHERE teamid='%u'", teamid );
4222 if ( ! mysql_query ( myData, &myQuery[0] ) )
4223 {
4224 myResult = mysql_store_result ( myData );
4225 num_mates = (int) mysql_num_rows ( myResult );
4226 *(unsigned*) &ship->encryptbuf[packet_offset] = num_mates;
4227 packet_offset += 4;
4228 for (ch=1;ch<=num_mates;ch++)
4229 {
4230 myRow = mysql_fetch_row ( myResult );
4231 guildcard = atoi (myRow[0]);
4232 privlevel = atoi (myRow[1]);
4233 *(unsigned*) &ship->encryptbuf[packet_offset] = ch;
4234 packet_offset += 4;
4235 *(unsigned*) &ship->encryptbuf[packet_offset] = privlevel;
4236 packet_offset += 4;
4237 *(unsigned*) &ship->encryptbuf[packet_offset] = guildcard;
4238 packet_offset += 4;
4239 memcpy (&ship->encryptbuf[packet_offset], myRow[2], 24);
4240 packet_offset += 24;
4241 memset (&ship->encryptbuf[packet_offset], 0, 8);
4242 packet_offset += 8;
4243 }
4244 mysql_free_result ( myResult );
4245 packet_offset -= 0x0A;
4246 *(unsigned short*) &ship->encryptbuf[0x0A] = (unsigned short) packet_offset;
4247 packet_offset += 0x0A;
4248 compressShipPacket (ship, &ship->encryptbuf[0x00], packet_offset);
4249 }
4250 else
4251 {
4252 debug ("Could not get team list for team %u", teamid);
4253 return;
4254 }
4255#endif
4256 }
4257 break;
4258 case 0x06:
4259 // Promote member
4260 //
4261 // 0x06 = Team ID
4262 // 0x0A = Guild card
4263 // 0x0B = New level
4264 //
4265 {
4266 unsigned gcn, teamid;
4267 unsigned char privlevel;
4268
4269 teamid = *(unsigned*) &ship->decryptbuf[0x06];
4270 gcn = *(unsigned*) &ship->decryptbuf[0x0A];
4271 privlevel = (unsigned char) ship->decryptbuf[0x0E];
4272#ifdef NO_SQL
4273 for (ds=0;ds<num_accounts;ds++)
4274 {
4275 if ((account_data[ds]->guildcard == gcn) &&
4276 (account_data[ds]->teamid == teamid))
4277 {
4278 account_data[ds]->privlevel = privlevel;
4279 UpdateDataFile ("account.dat", ds, account_data[ds], sizeof (L_ACCOUNT_DATA), 0);
4280 break;
4281 }
4282 }
4283
4284 if (privlevel == 0x40)
4285 {
4286 for (ds=0;ds<num_accounts;ds++)
4287 {
4288 if (team_data[ds]->teamid == teamid)
4289 {
4290 team_data[ds]->owner = gcn;
4291 UpdateDataFile ("team.dat", ds, team_data[ds], sizeof (L_TEAM_DATA), 0);
4292 break;
4293 }
4294 }
4295 }
4296#else
4297 sprintf (&myQuery[0], "UPDATE account_data SET privlevel='%u' WHERE guildcard='%u' AND teamid='%u'", privlevel, gcn, teamid);
4298 mysql_query (myData, &myQuery[0]);
4299 if (privlevel == 0x40) // Master Transfer
4300 sprintf (&myQuery[0], "UPDATE team_data SET owner='%u' WHERE teamid='%u'", gcn, teamid);
4301 mysql_query (myData, &myQuery[0]);
4302#endif
4303 ship->encryptbuf[0x00] = 0x09;
4304 ship->encryptbuf[0x01] = 0x06;
4305 ship->encryptbuf[0x02] = 0x01;
4306 compressShipPacket (ship, &ship->encryptbuf[0x00], 3);
4307 }
4308 break;
4309 case 0x07:
4310 // Add member
4311 //
4312 // 0x06 = Team ID
4313 // 0x0A = Guild card
4314 //
4315 {
4316 unsigned gcn, teamid;
4317
4318 teamid = *(unsigned*) &ship->decryptbuf[0x06];
4319 gcn = *(unsigned*) &ship->decryptbuf[0x0A];
4320#ifdef NO_SQL
4321 for (ds=0;ds<num_accounts;ds++)
4322 {
4323 if (account_data[ds]->guildcard == gcn)
4324 {
4325 account_data[ds]->teamid = teamid;
4326 account_data[ds]->privlevel = 0;
4327 UpdateDataFile ("account.dat", ds, account_data[ds], sizeof (L_ACCOUNT_DATA), 0);
4328 break;
4329 }
4330 }
4331#else
4332 sprintf (&myQuery[0], "UPDATE account_data SET teamid='%u', privlevel='0' WHERE guildcard='%u'", teamid, gcn);
4333 mysql_query (myData, &myQuery[0]);
4334#endif
4335 ship->encryptbuf[0x00] = 0x09;
4336 ship->encryptbuf[0x01] = 0x07;
4337 ship->encryptbuf[0x02] = 0x01;
4338 compressShipPacket (ship, &ship->encryptbuf[0x00], 3);
4339 }
4340 break;
4341 }
4342 break;
4343 case 0x0A:
4344 break;
4345 case 0x0B:
4346 // Checking authentication...
4347 switch (ship->decryptbuf[0x05])
4348 {
4349 case 0x00:
4350 {
4351 int security_client_thirtytwo, security_thirtytwo_check;
4352 long long security_client_sixtyfour, security_sixtyfour_check;
4353 unsigned char fail_to_auth = 0;
4354 unsigned gcn;
4355 unsigned char slotnum;
4356 unsigned char isgm;
4357
4358 gcn = *(unsigned*) &ship->decryptbuf[0x06];
4359#ifdef NO_SQL
4360 for (ds=0;ds<num_security;ds++)
4361 {
4362 if (security_data[ds]->guildcard == gcn)
4363 {
4364 int found_match;
4365
4366 security_thirtytwo_check = security_data[ds]->thirtytwo;
4367 security_sixtyfour_check = security_data[ds]->sixtyfour;
4368 slotnum = security_data[ds]->slotnum;
4369 isgm = security_data[ds]->isgm;
4370
4371 found_match = 0;
4372
4373 security_client_sixtyfour = *(long long*) &ship->decryptbuf[0x0E];
4374 if (security_client_sixtyfour == security_sixtyfour_check)
4375 found_match = 1;
4376
4377 security_client_sixtyfour = *(long long*) &ship->decryptbuf[0x16];
4378 if (security_client_sixtyfour == security_sixtyfour_check)
4379 found_match = 1;
4380
4381 security_client_sixtyfour = *(long long*) &ship->decryptbuf[0x1E];
4382 if (security_client_sixtyfour == security_sixtyfour_check)
4383 found_match = 1;
4384
4385 security_client_sixtyfour = *(long long*) &ship->decryptbuf[0x26];
4386 if (security_client_sixtyfour == security_sixtyfour_check)
4387 found_match = 1;
4388
4389 security_client_sixtyfour = *(long long*) &ship->decryptbuf[0x2E];
4390 if (security_client_sixtyfour == security_sixtyfour_check)
4391 found_match = 1;
4392
4393 if (found_match == 0)
4394 fail_to_auth = 1;
4395
4396 security_client_thirtytwo = *(unsigned *) &ship->decryptbuf[0x0A];
4397
4398 if (security_client_thirtytwo != security_thirtytwo_check)
4399 fail_to_auth = 1;
4400
4401 break;
4402 }
4403 }
4404#else
4405 sprintf (&myQuery[0], "SELECT * from security_data WHERE guildcard='%u'", gcn );
4406 // Nom nom nom
4407 if ( ! mysql_query ( myData, &myQuery[0] ) )
4408 {
4409 int num_rows, found_match;
4410
4411 found_match = 0;
4412
4413 myResult = mysql_store_result ( myData );
4414 num_rows = (int) mysql_num_rows ( myResult );
4415
4416 if (num_rows)
4417 {
4418 myRow = mysql_fetch_row ( myResult );
4419
4420 security_thirtytwo_check = atoi ( myRow[1] );
4421 memcpy (&security_sixtyfour_check, myRow[2], 8 );
4422 slotnum = atoi (myRow[3]);
4423 isgm = atoi (myRow[4]);
4424
4425 security_client_sixtyfour = *(long long*) &ship->decryptbuf[0x0E];
4426 if (security_client_sixtyfour == security_sixtyfour_check)
4427 found_match = 1;
4428
4429 security_client_sixtyfour = *(long long*) &ship->decryptbuf[0x16];
4430 if (security_client_sixtyfour == security_sixtyfour_check)
4431 found_match = 1;
4432
4433 security_client_sixtyfour = *(long long*) &ship->decryptbuf[0x1E];
4434 if (security_client_sixtyfour == security_sixtyfour_check)
4435 found_match = 1;
4436
4437 security_client_sixtyfour = *(long long*) &ship->decryptbuf[0x26];
4438 if (security_client_sixtyfour == security_sixtyfour_check)
4439 found_match = 1;
4440
4441 security_client_sixtyfour = *(long long*) &ship->decryptbuf[0x2E];
4442 if (security_client_sixtyfour == security_sixtyfour_check)
4443 found_match = 1;
4444
4445 if (found_match == 0)
4446 fail_to_auth = 1;
4447 }
4448 else
4449 fail_to_auth = 1;
4450
4451 security_client_thirtytwo = *(unsigned *) &ship->decryptbuf[0x0A];
4452
4453 if (security_client_thirtytwo != security_thirtytwo_check)
4454 fail_to_auth = 1;
4455
4456 mysql_free_result ( myResult );
4457 }
4458 else
4459 fail_to_auth = 1;
4460#endif
4461 ship->encryptbuf[0x00] = 0x0B;
4462 ship->encryptbuf[0x01] = fail_to_auth;
4463 *(unsigned *) &ship->encryptbuf[0x02] = gcn;
4464 ship->encryptbuf[0x06] = slotnum;
4465 ship->encryptbuf[0x07] = isgm;
4466 *(unsigned *) &ship->encryptbuf[0x08] = security_thirtytwo_check;
4467 *(long long*) &ship->encryptbuf[0x0C] = security_sixtyfour_check;
4468 compressShipPacket ( ship, &ship->encryptbuf[0x00], 0x14 );
4469 }
4470 break;
4471 }
4472 break;
4473 case 0x0C:
4474 break;
4475 case 0x0D:
4476 // Various commands related to ship transfers...
4477 ShipSend0D (ship->decryptbuf[0x05], ship);
4478 break;
4479 case 0x0E:
4480 {
4481 // Update player count.
4482 unsigned updateID;
4483
4484 updateID = *(unsigned *) &ship->decryptbuf[0x06];
4485 updateID--;
4486
4487 if ( updateID < serverMaxShips )
4488 ships[updateID]->playerCount = *(unsigned *) &ship->decryptbuf[0x0A];
4489
4490 construct0xA0();
4491 }
4492 break;
4493 case 0x0F:
4494 switch ( ship->decryptbuf[0x05] )
4495 {
4496 case 0x00:
4497 keys_in_use[ ship->key_index ] = 1;
4498 ShipSend0F (0x01, 0x00, ship);
4499 break;
4500 case 0x01:
4501 if ( ship->decryptbuf[0x06] == 0 )
4502 ShipSend0F (0x01, 0x01, ship);
4503 else
4504 ShipSend0F (0x02, 0x00, ship);
4505 break;
4506 case 0x02:
4507 if ( ship->decryptbuf[0x06] == 0 )
4508 ShipSend0F (0x02, 0x01, ship);
4509 else
4510 ShipSend0F (0x03, 0x00, ship);
4511 break;
4512 case 0x03:
4513 if ( ship->decryptbuf[0x06] == 0 )
4514 ShipSend0F (0x03, 0x01, ship);
4515 else
4516 ShipSend10 (ship);
4517 break;
4518 default:
4519 break;
4520 }
4521 break;
4522 case 0x11:
4523 ship->last_ping = (unsigned) servertime;
4524 ship->sent_ping = 0;
4525 break;
4526 case 0x12:
4527 // Global announcement
4528 {
4529 ORANGE* tship;
4530 unsigned size,ch;
4531
4532 size = *(unsigned *) &ship->decryptbuf[0x00];
4533 size -= 4;
4534
4535 // Just pass the packet along...
4536 for (ch=0;ch<serverNumShips;ch++)
4537 {
4538 shipNum = serverShipList[ch];
4539 tship = ships[shipNum];
4540 if ((tship->shipSockfd >= 0) && (tship->authed == 1))
4541 compressShipPacket ( tship, &ship->decryptbuf[0x04], size );
4542 }
4543 }
4544 break;
4545 default:
4546 // Unknown packet received from ship?
4547 ship->todc = 1;
4548 break;
4549 }
4550}
4551
4552
4553void CharacterProcessPacket (BANANA* client)
4554{
4555 char username[17];
4556 char password[34];
4557 char hwinfo[18];
4558 unsigned short clientver;
4559 char md5password[34] = {0};
4560 unsigned char MDBuffer[17] = {0};
4561 unsigned gcn;
4562 unsigned ch;
4563 unsigned selected;
4564 unsigned shipNum;
4565 int security_client_thirtytwo, security_thirtytwo_check;
4566 long long security_client_sixtyfour, security_sixtyfour_check;
4567#ifdef NO_SQL
4568 long long truehwinfo;
4569#endif
4570
4571 switch (client->decryptbuf[0x02])
4572 {
4573 case 0x05:
4574 printf ("Client has closed the connection.\n");
4575 client->todc = 1;
4576 break;
4577 case 0x10:
4578 if ((client->guildcard) && (client->slotnum != -1))
4579 {
4580 ORANGE* tship;
4581
4582 selected = *(unsigned *) &client->decryptbuf[0x0C];
4583 for (ch=0;ch<serverNumShips;ch++)
4584 {
4585 shipNum = serverShipList[ch];
4586 tship = ships[shipNum];
4587
4588 if ((tship->shipSockfd >= 0) && (tship->authed == 1) &&
4589 (tship->shipID == selected))
4590 {
4591 Send19 (tship->shipAddr[0], tship->shipAddr[1],
4592 tship->shipAddr[2], tship->shipAddr[3],
4593 tship->shipPort, client);
4594 break;
4595 }
4596 }
4597 }
4598 break;
4599 case 0x1D:
4600 // Do nothing.
4601 break;
4602 case 0x93:
4603 if (!client->sendCheck[RECEIVE_PACKET_93])
4604 {
4605 int fail_to_auth = 0;
4606
4607 clientver = *(unsigned short*) &client->decryptbuf[0x10];
4608 memcpy (&username[0], &client->decryptbuf[0x1C], 17 );
4609 memcpy (&password[0], &client->decryptbuf[0x4C], 17 );
4610 memset (&hwinfo[0], 0, 18);
4611#ifdef NO_SQL
4612 *(long long*) &client->hwinfo[0] = *(long long*) &client->decryptbuf[0x84];
4613 truehwinfo = *(long long*) &client->decryptbuf[0x84];
4614 fail_to_auth = 2; // default fail with wrong username
4615 for (ds=0;ds<num_accounts;ds++)
4616 {
4617 if (!strcmp(&account_data[ds]->username[0], &username[0]))
4618 {
4619 fail_to_auth = 0;
4620 sprintf (&password[strlen(password)], "_%u_salt", account_data[ds]->regtime );
4621 MDString (&password[0], &MDBuffer[0] );
4622 for (ch=0;ch<16;ch++)
4623 sprintf (&md5password[ch*2], "%02x", (unsigned char) MDBuffer[ch]);
4624 md5password[32] = 0;
4625 if (!strcmp(&md5password[0],&account_data[ds]->password[0]))
4626 {
4627 if (account_data[ds]->isbanned)
4628 fail_to_auth = 3;
4629 if (!account_data[ds]->isactive)
4630 fail_to_auth = 5;
4631 if (!fail_to_auth)
4632 gcn = account_data[ds]->guildcard;
4633 if (client->decryptbuf[0x10] != PSO_CLIENT_VER)
4634 fail_to_auth = 7;
4635 client->isgm = account_data[ds]->isgm;
4636 }
4637 else
4638 fail_to_auth = 2;
4639 break;
4640 }
4641 }
4642
4643 // DO HW BAN LATER
4644
4645 if (!fail_to_auth)
4646 {
4647 for (ds=0;ds<num_security;ds++)
4648 {
4649 if (security_data[ds]->guildcard == gcn)
4650 {
4651 int found_match;
4652
4653 client->dress_flag = 0;
4654 for (ch=0;ch<MAX_DRESS_FLAGS;ch++)
4655 {
4656 if (dress_flags[ch].guildcard == gcn)
4657 client->dress_flag = 1;
4658 }
4659
4660 security_thirtytwo_check = security_data[ds]->thirtytwo;
4661 security_sixtyfour_check = security_data[ds]->sixtyfour;
4662 client->slotnum = security_data[ds]->slotnum;
4663
4664 found_match = 0;
4665
4666 security_client_sixtyfour = *(long long*) &client->decryptbuf[0x8C];
4667 if (security_client_sixtyfour == security_sixtyfour_check)
4668 found_match = 1;
4669
4670 security_client_sixtyfour = *(long long*) &client->decryptbuf[0x94];
4671 if (security_client_sixtyfour == security_sixtyfour_check)
4672 found_match = 1;
4673
4674 security_client_sixtyfour = *(long long*) &client->decryptbuf[0x9C];
4675 if (security_client_sixtyfour == security_sixtyfour_check)
4676 found_match = 1;
4677
4678 security_client_sixtyfour = *(long long*) &client->decryptbuf[0xA4];
4679 if (security_client_sixtyfour == security_sixtyfour_check)
4680 found_match = 1;
4681
4682 security_client_sixtyfour = *(long long*) &client->decryptbuf[0xAC];
4683 if (security_client_sixtyfour == security_sixtyfour_check)
4684 found_match = 1;
4685
4686 if (found_match == 0)
4687 fail_to_auth = 6;
4688
4689 security_client_thirtytwo = *(unsigned *) &client->decryptbuf[0x18];
4690
4691 if (security_client_thirtytwo == 0)
4692 client->sendingchars = 1;
4693 else
4694 {
4695 client->sendingchars = 0;
4696 if (security_client_thirtytwo != security_thirtytwo_check)
4697 fail_to_auth = 6;
4698 }
4699 break;
4700 }
4701 }
4702 }
4703
4704#else
4705 mysql_real_escape_string ( myData, &hwinfo[0], &client->decryptbuf[0x84], 8);
4706 memcpy (&client->hwinfo[0], &hwinfo[0], 18);
4707 sprintf (&myQuery[0], "SELECT * from account_data WHERE username='%s'", username );
4708
4709 // Check to see if that account already exists.
4710 if ( ! mysql_query ( myData, &myQuery[0] ) )
4711 {
4712 int num_rows, max_fields;
4713
4714 myResult = mysql_store_result ( myData );
4715 num_rows = (int) mysql_num_rows ( myResult );
4716
4717 if (num_rows)
4718 {
4719 myRow = mysql_fetch_row ( myResult );
4720 max_fields = mysql_num_fields ( myResult );
4721 sprintf (&password[strlen(password)], "_%s_salt", myRow[3] );
4722 MDString (&password[0], &MDBuffer[0] );
4723 for (ch=0;ch<16;ch++)
4724 sprintf (&md5password[ch*2], "%02x", (unsigned char) MDBuffer[ch]);
4725 md5password[32] = 0;
4726 if (!strcmp(&md5password[0],myRow[1]))
4727 {
4728 if (!strcmp("1", myRow[8]))
4729 fail_to_auth = 3;
4730 if (!strcmp("1", myRow[9]))
4731 fail_to_auth = 4;
4732 if (!strcmp("0", myRow[10]))
4733 fail_to_auth = 5;
4734 if (!fail_to_auth)
4735 gcn = atoi (myRow[6]);
4736 if (client->decryptbuf[0x10] != PSO_CLIENT_VER)
4737 fail_to_auth = 7;
4738 client->isgm = atoi (myRow[7]);
4739 }
4740 else
4741 fail_to_auth = 2;
4742 }
4743 else
4744 fail_to_auth = 2;
4745
4746 mysql_free_result ( myResult );
4747 }
4748 else
4749 fail_to_auth = 1; // MySQL error.
4750
4751 // Hardware info ban check...
4752
4753 sprintf (&myQuery[0], "SELECT * from hw_bans WHERE hwinfo='%s'", hwinfo );
4754 if ( ! mysql_query ( myData, &myQuery[0] ) )
4755 {
4756 myResult = mysql_store_result ( myData );
4757 if ((int) mysql_num_rows ( myResult ))
4758 fail_to_auth = 3;
4759 mysql_free_result ( myResult );
4760 }
4761 else
4762 fail_to_auth = 1;
4763
4764 if ( fail_to_auth == 0)
4765 {
4766 sprintf (&myQuery[0], "SELECT * from security_data WHERE guildcard='%u'", gcn );
4767 // Nom nom nom
4768 if ( ! mysql_query ( myData, &myQuery[0] ) )
4769 {
4770 int num_rows, found_match;
4771
4772 found_match = 0;
4773
4774 myResult = mysql_store_result ( myData );
4775 num_rows = (int) mysql_num_rows ( myResult );
4776
4777 if (num_rows)
4778 {
4779 myRow = mysql_fetch_row ( myResult );
4780
4781 client->dress_flag = 0;
4782 for (ch=0;ch<MAX_DRESS_FLAGS;ch++)
4783 {
4784 if (dress_flags[ch].guildcard == gcn)
4785 client->dress_flag = 1;
4786 }
4787
4788 security_thirtytwo_check = atoi ( myRow[1] );
4789 memcpy (&security_sixtyfour_check, myRow[2], 8 );
4790 client->slotnum = atoi (myRow[3]);
4791
4792 security_client_sixtyfour = *(long long*) &client->decryptbuf[0x8C];
4793 if (security_client_sixtyfour == security_sixtyfour_check)
4794 found_match = 1;
4795
4796 security_client_sixtyfour = *(long long*) &client->decryptbuf[0x94];
4797 if (security_client_sixtyfour == security_sixtyfour_check)
4798 found_match = 1;
4799
4800 security_client_sixtyfour = *(long long*) &client->decryptbuf[0x9C];
4801 if (security_client_sixtyfour == security_sixtyfour_check)
4802 found_match = 1;
4803
4804 security_client_sixtyfour = *(long long*) &client->decryptbuf[0xA4];
4805 if (security_client_sixtyfour == security_sixtyfour_check)
4806 found_match = 1;
4807
4808 security_client_sixtyfour = *(long long*) &client->decryptbuf[0xAC];
4809 if (security_client_sixtyfour == security_sixtyfour_check)
4810 found_match = 1;
4811
4812 if (found_match == 0)
4813 {
4814 debug ("Couldn't find 64-bit information.");
4815 fail_to_auth = 6;
4816 }
4817 }
4818 else
4819 fail_to_auth = 6;
4820
4821 security_client_thirtytwo = *(unsigned *) &client->decryptbuf[0x18];
4822
4823 if (security_client_thirtytwo == 0)
4824 client->sendingchars = 1;
4825 else
4826 {
4827 client->sendingchars = 0;
4828 if (security_client_thirtytwo != security_thirtytwo_check)
4829 {
4830 fail_to_auth = 6;
4831 debug ("Couldn't find 32-bit information.");
4832 debug ("Looking for %i, have %i", security_thirtytwo_check, security_client_thirtytwo);
4833 }
4834 }
4835 mysql_free_result ( myResult );
4836 }
4837 }
4838#endif
4839
4840 switch (fail_to_auth)
4841 {
4842 case 0x00:
4843 // OK
4844 memcpy (&client->encryptbuf[0], &PacketE6[0], sizeof (PacketE6));
4845 *(unsigned *) &client->encryptbuf[0x10] = gcn;
4846 client->guildcard = gcn;
4847 _itoa (gcn, &client->guildcard_string[0], 10); /* auth'd, bitch */
4848 // Store some security shit in the E6 packet.
4849 *(long long*) &client->encryptbuf[0x38] = security_sixtyfour_check;
4850 if (security_thirtytwo_check == 0)
4851 {
4852 for (ch=0;ch<4;ch++)
4853 MDBuffer[ch] = (unsigned char)( rand() % 256 );
4854 security_thirtytwo_check = *(unsigned *) &MDBuffer[0];
4855#ifdef NO_SQL
4856 for (ds=0;ds<num_security;ds++)
4857 {
4858 if (security_data[ds]->guildcard == gcn)
4859 {
4860 security_data[ds]->thirtytwo = security_thirtytwo_check;
4861 UpdateDataFile ("security.dat", ds, security_data[ds], sizeof (L_SECURITY_DATA), 0);
4862 break;
4863 }
4864 }
4865#else
4866 sprintf (&myQuery[0], "UPDATE security_data set thirtytwo = '%i' WHERE guildcard = '%u'", security_thirtytwo_check, gcn );
4867 // Nom, nom, nom.
4868 if ( mysql_query ( myData, &myQuery[0] ) )
4869 {
4870 Send1A ("Couldn't update security information in MySQL database.\nPlease contact the server administrator.", client);
4871 client->todc = 1;
4872 return;
4873 }
4874#endif
4875 }
4876 *(unsigned *) &client->encryptbuf[0x14] = security_thirtytwo_check;
4877 cipher_ptr = &client->server_cipher;
4878 encryptcopy (client, &client->encryptbuf[0], sizeof (PacketE6));
4879 if (client->slotnum != -1)
4880 {
4881 if (client->decryptbuf[0x16] != 0x04)
4882 {
4883 Send1A ("Client/Server synchronization error.", client);
4884 client->todc = 1;
4885 }
4886 else
4887 {
4888 // User has completed the login process, after updating the SQL info with their
4889 // access information, give 'em the ship select screen.
4890#ifdef NO_SQL
4891 for (ds=0;ds<num_accounts;ds++)
4892 {
4893 if (account_data[ds]->guildcard == gcn)
4894 {
4895 memcpy (&account_data[ds]->lastip[0], &client->IP_Address[0], 16);
4896 account_data[ds]->lasthwinfo = truehwinfo;
4897 UpdateDataFile ("account.dat", ds, account_data[ds], sizeof (L_ACCOUNT_DATA), 0);
4898 break;
4899 }
4900 }
4901#else
4902 sprintf (&myQuery[0], "UPDATE account_data set lastip = '%s', lasthwinfo = '%s' WHERE username = '%s'", client->IP_Address, hwinfo, username );
4903 mysql_query ( myData, &myQuery[0] );
4904#endif
4905 client->lastTick = (unsigned) servertime;
4906 SendB1 (client);
4907 SendA0 (client);
4908 SendEE (&Welcome_Message[0], client);
4909 }
4910 }
4911 break;
4912 case 0x01:
4913 // MySQL error.
4914 Send1A ("There is a problem with the MySQL database.\n\nPlease contact the server administrator.", client);
4915 break;
4916 case 0x02:
4917 // Username or password incorrect.
4918 Send1A ("Username or password is incorrect.", client);
4919 break;
4920 case 0x03:
4921 // Account is banned.
4922 Send1A ("You are banned from this server.", client);
4923 break;
4924 case 0x04:
4925 // Already logged on.
4926 Send1A ("This account is already logged on.\n\nPlease wait 120 seconds and try again.", client);
4927 break;
4928 case 0x05:
4929 // Account has not completed e-mail validation.
4930 Send1A ("Please complete the registration of this account through\ne-mail validation.\n\nThank you.", client);
4931 break;
4932 case 0x06:
4933 // Security violation.
4934 Send1A ("Security violation.", client);
4935 break;
4936 case 0x07:
4937 // Client version too old.
4938 Send1A ("Your client executable is too old.\nPlease update your client through the patch server.", client);
4939 break;
4940 default:
4941 Send1A ("Unknown error.", client);
4942 break;
4943 }
4944 client->sendCheck[RECEIVE_PACKET_93] = 0x01;
4945 }
4946 break;
4947 case 0xDC:
4948 switch (client->decryptbuf[0x03])
4949 {
4950 case 0x03:
4951 // Send another chunk of guild card data.
4952 if ((client->decryptbuf[0x08] == 0x01) && (client->decryptbuf[0x10] == 0x01))
4953 SendDC (0x00, client->decryptbuf[0x0C], client );
4954 break;
4955 default:
4956 break;
4957 }
4958 break;
4959 case 0xE0:
4960 // The gamepad, keyboard config, and other options....
4961 SendE2 (client);
4962 break;
4963 case 0xE3:
4964 // Client selecting or requesting character.
4965 SendE4_E5(client->decryptbuf[0x08], client->decryptbuf[0x0C], client);
4966 break;
4967 case 0xE5:
4968 // Create a character in slot.
4969 // Check invalid data and store character in MySQL store.
4970 AckCharacter_Creation ( client->decryptbuf[0x08], client );
4971 break;
4972 case 0xE8:
4973 switch (client->decryptbuf[0x03])
4974 {
4975 case 0x01:
4976 // Client just communicating the expected guild card checksum. (Ignoring for now.)
4977 SendE8 (client);
4978 break;
4979 case 0x03:
4980 // Client requesting guild card checksum.
4981 SendDC (0x01, 0, client);
4982 break;
4983 default:
4984 break;
4985 }
4986 break;
4987 case 0xEB:
4988 switch (client->decryptbuf[0x03])
4989 {
4990 case 0x03:
4991 // Send another chunk of the parameter files.
4992 SendEB (0x02, client->decryptbuf[0x04], client );
4993 break;
4994 case 0x04:
4995 // Send header for parameter files.
4996 SendEB (0x01, 0x00, client);
4997 break;
4998 }
4999 break;
5000 case 0xEC:
5001 if (client->decryptbuf[0x08] == 0x02)
5002 {
5003 // Set the dressing room flag (Don't overwrite the character...)
5004 for (ch=0;ch<MAX_DRESS_FLAGS;ch++)
5005 if (dress_flags[ch].guildcard == 0)
5006 {
5007 dress_flags[ch].guildcard = client->guildcard;
5008 dress_flags[ch].flagtime = (unsigned) servertime;
5009 break;
5010 if (ch == (MAX_DRESS_FLAGS - 1))
5011 {
5012 Send1A ("Unable to save dress flag.", client);
5013 client->todc = 1;
5014 }
5015 }
5016 client->dress_flag = 1;
5017 }
5018 break;
5019 default:
5020 break;
5021 }
5022}
5023
5024void LoginProcessPacket (BANANA* client)
5025{
5026 char username[17];
5027 char password[34];
5028 long long security_sixtyfour_check;
5029 char hwinfo[18];
5030 unsigned short clientver;
5031 char md5password[34] = {0};
5032 unsigned char MDBuffer[17] = {0};
5033 unsigned gcn;
5034 unsigned ch,connectNum,shipNum;
5035#ifdef NO_SQL
5036 long long truehwinfo;
5037#endif
5038 ORANGE* tship;
5039#ifndef NO_SQL
5040 char security_sixtyfour_binary[18];
5041#endif
5042
5043
5044 /* Only packet we're expecting during the login is 0x93 and 0x05. */
5045
5046 switch (client->decryptbuf[0x02])
5047 {
5048 case 0x05:
5049 printf ("Client has closed the connection.\n");
5050 client->todc = 1;
5051 break;
5052 case 0x93:
5053 if (!client->sendCheck[RECEIVE_PACKET_93])
5054 {
5055 int fail_to_auth = 0;
5056 clientver = *(unsigned short*) &client->decryptbuf[0x10];
5057 memcpy (&username[0], &client->decryptbuf[0x1C], 17 );
5058 memcpy (&password[0], &client->decryptbuf[0x4C], 17 );
5059 memset (&hwinfo[0], 0, 18);
5060#ifdef NO_SQL
5061 *(long long*) &client->hwinfo[0] = *(long long*) &client->decryptbuf[0x84];
5062 truehwinfo = *(long long*) &client->decryptbuf[0x84];
5063 fail_to_auth = 2; // default fail with wrong username
5064 for (ds=0;ds<num_accounts;ds++)
5065 {
5066 if (!strcmp(&account_data[ds]->username[0], &username[0]))
5067 {
5068 fail_to_auth = 0;
5069 sprintf (&password[strlen(password)], "_%u_salt", account_data[ds]->regtime );
5070 MDString (&password[0], &MDBuffer[0] );
5071 for (ch=0;ch<16;ch++)
5072 sprintf (&md5password[ch*2], "%02x", (unsigned char) MDBuffer[ch]);
5073 md5password[32] = 0;
5074 if (!strcmp(&md5password[0],&account_data[ds]->password[0]))
5075 {
5076 if (account_data[ds]->isbanned)
5077 fail_to_auth = 3;
5078 if (!account_data[ds]->isactive)
5079 fail_to_auth = 5;
5080 if (!fail_to_auth)
5081 gcn = account_data[ds]->guildcard;
5082 if ((strcmp(&client->decryptbuf[0x8C], PSO_CLIENT_VER_STRING) != 0) || (client->decryptbuf[0x10] != PSO_CLIENT_VER))
5083 fail_to_auth = 7;
5084 client->isgm = account_data[ds]->isgm;
5085 }
5086 else
5087 fail_to_auth = 2;
5088 break;
5089 }
5090 }
5091
5092 // DO HW BAN LATER
5093
5094#else
5095 mysql_real_escape_string ( myData, &hwinfo[0], &client->decryptbuf[0x84], 8);
5096 memcpy (&client->hwinfo[0], &hwinfo[0], 18);
5097
5098 sprintf (&myQuery[0], "SELECT * from account_data WHERE username='%s'", username );
5099
5100 // Check to see if that account already exists.
5101 if ( ! mysql_query ( myData, &myQuery[0] ) )
5102 {
5103 int num_rows, max_fields;
5104
5105 myResult = mysql_store_result ( myData );
5106 num_rows = (int) mysql_num_rows ( myResult );
5107
5108 if (num_rows)
5109 {
5110 myRow = mysql_fetch_row ( myResult );
5111 max_fields = mysql_num_fields ( myResult );
5112 sprintf (&password[strlen(password)], "_%s_salt", myRow[3] );
5113 MDString (&password[0], &MDBuffer[0] );
5114 for (ch=0;ch<16;ch++)
5115 sprintf (&md5password[ch*2], "%02x", (unsigned char) MDBuffer[ch]);
5116 md5password[32] = 0;
5117 if (!strcmp(&md5password[0],myRow[1]))
5118 {
5119 if (!strcmp("1", myRow[8]))
5120 fail_to_auth = 3;
5121 if (!strcmp("1", myRow[9]))
5122 fail_to_auth = 4;
5123 if (!strcmp("0", myRow[10]))
5124 fail_to_auth = 5;
5125 if (!fail_to_auth)
5126 gcn = atoi (myRow[6]);
5127 if ((strcmp(&client->decryptbuf[0x8C], PSO_CLIENT_VER_STRING) != 0) || (client->decryptbuf[0x10] != PSO_CLIENT_VER))
5128 fail_to_auth = 7;
5129 client->isgm = atoi (myRow[7]);
5130 }
5131 else
5132 fail_to_auth = 2;
5133 }
5134 else
5135 fail_to_auth = 2;
5136 mysql_free_result ( myResult );
5137 }
5138 else
5139 fail_to_auth = 1; // MySQL error.
5140
5141 // Hardware info ban check...
5142
5143 sprintf (&myQuery[0], "SELECT * from hw_bans WHERE hwinfo='%s'", hwinfo );
5144 if ( ! mysql_query ( myData, &myQuery[0] ) )
5145 {
5146 myResult = mysql_store_result ( myData );
5147 if ((int) mysql_num_rows ( myResult ))
5148 fail_to_auth = 3;
5149 mysql_free_result ( myResult );
5150 }
5151 else
5152 fail_to_auth = 1;
5153#endif
5154
5155 switch (fail_to_auth)
5156 {
5157 case 0x00:
5158 // OK
5159
5160 // If guild card is connected to the login server already, disconnect it.
5161
5162 for (ch=0;ch<serverNumConnections;ch++)
5163 {
5164 connectNum = serverConnectionList[ch];
5165 if (connections[connectNum]->guildcard == gcn)
5166 {
5167 Send1A ("This account has just logged on.\n\nYou are now being disconnected.", connections[connectNum]);
5168 connections[connectNum]->todc = 1;
5169 break;
5170 }
5171 }
5172
5173 // If guild card is connected to ships, disconnect it.
5174
5175 for (ch=0;ch<serverNumShips;ch++)
5176 {
5177 shipNum = serverShipList[ch];
5178 tship = ships[shipNum];
5179 if ((tship->shipSockfd >= 0) && (tship->authed == 1))
5180 ShipSend08 (gcn, tship);
5181 }
5182
5183
5184 memcpy (&client->encryptbuf[0], &PacketE6[0], sizeof (PacketE6));
5185 *(unsigned *) &client->encryptbuf[0x10] = gcn;
5186
5187 // Store some security shit
5188 for (ch=0;ch<8;ch++)
5189 client->encryptbuf[0x38+ch] = (unsigned char) rand() % 255;
5190
5191 security_sixtyfour_check = *(long long*) &client->encryptbuf[0x38];
5192
5193 // Nom, nom, nom.
5194
5195#ifdef NO_SQL
5196 free_record = -1;
5197 new_record = 1;
5198 for (ds=0;ds<num_security;ds++)
5199 {
5200 if (security_data[ds]->guildcard == gcn)
5201 security_data[ds]->guildcard = 0;
5202 UpdateDataFile ("security.dat", ds, security_data[ds], sizeof (L_SECURITY_DATA), 0);
5203 if (security_data[ds]->guildcard == 0)
5204 {
5205 free_record = ds;
5206 new_record = 0;
5207 }
5208 }
5209 if (new_record)
5210 {
5211 free_record = num_security++;
5212 security_data[free_record] = malloc ( sizeof (L_SECURITY_DATA) );
5213 }
5214 security_data[free_record]->guildcard = gcn;
5215 security_data[free_record]->thirtytwo = 0;
5216 security_data[free_record]->sixtyfour = security_sixtyfour_check;
5217 security_data[free_record]->isgm = client->isgm;
5218 security_data[free_record]->slotnum = -1;
5219 UpdateDataFile ("security.dat", free_record, security_data[free_record], sizeof (L_SECURITY_DATA), new_record);
5220#else
5221 sprintf (&myQuery[0], "DELETE from security_data WHERE guildcard = '%u'", gcn );
5222 mysql_query ( myData, &myQuery[0] );
5223 mysql_real_escape_string ( myData, &security_sixtyfour_binary[0], (char*) &security_sixtyfour_check, 8);
5224 sprintf (&myQuery[0], "INSERT INTO security_data (guildcard, thirtytwo, sixtyfour, isgm) VALUES ('%u','0','%s', '%u')", gcn, (char*) &security_sixtyfour_binary, client->isgm );
5225 if ( mysql_query ( myData, &myQuery[0] ) )
5226 {
5227 Send1A ("Couldn't update security information in MySQL database.\nPlease contact the server administrator.", client);
5228 client->todc = 1;
5229 return;
5230 }
5231#endif
5232
5233 cipher_ptr = &client->server_cipher;
5234 encryptcopy (client, &client->encryptbuf[0], sizeof (PacketE6));
5235
5236 Send19 (serverIP[0], serverIP[1], serverIP[2], serverIP[3], serverPort+1, client );
5237 for (ch=0;ch<MAX_DRESS_FLAGS;ch++)
5238 {
5239 if ((dress_flags[ch].guildcard == gcn) || ((unsigned) servertime - dress_flags[ch].flagtime > DRESS_FLAG_EXPIRY))
5240 dress_flags[ch].guildcard = 0;
5241 }
5242 break;
5243 case 0x01:
5244 // MySQL error.
5245 Send1A ("There is a problem with the MySQL database.\n\nPlease contact the server administrator.", client);
5246 break;
5247 case 0x02:
5248 // Username or password incorrect.
5249 Send1A ("Username or password is incorrect.", client);
5250 break;
5251 case 0x03:
5252 // Account is banned.
5253 Send1A ("You are banned from this server.", client);
5254 break;
5255 case 0x04:
5256 // Already logged on.
5257 Send1A ("This account is already logged on.\n\nPlease wait 120 seconds and try again.", client);
5258 break;
5259 case 0x05:
5260 // Account has not completed e-mail validation.
5261 Send1A ("Please complete the registration of this account through\ne-mail validation.\n\nThank you.", client);
5262 break;
5263 case 0x07:
5264 // Client version too old.
5265 Send1A ("Your client executable is too old.\nPlease update your client through the patch server.", client);
5266 break;
5267 default:
5268 Send1A ("Unknown error.", client);
5269 break;
5270 }
5271 client->sendCheck[RECEIVE_PACKET_93] = 0x01;
5272 }
5273 break;
5274 default:
5275 client->todc = 1;
5276 break;
5277 }
5278}
5279
5280void LoadQuestAllow ()
5281{
5282 unsigned ch;
5283 char allow_data[256];
5284 unsigned char* qa;
5285 FILE* fp;
5286
5287 quest_numallows = 0;
5288 if ( ( fp = fopen ("questitem.txt", "r" ) ) == NULL )
5289 {
5290 printf ("questitem.txt is missing.\n");
5291 printf ("Press [ENTER] to quit...");
5292 gets(&dp[0]);
5293 exit (1);
5294 }
5295 else
5296 {
5297 while (fgets (&allow_data[0], 255, fp) != NULL)
5298 {
5299 if ((allow_data[0] != 35) && (strlen(&allow_data[0]) > 5))
5300 quest_numallows++;
5301 }
5302 quest_allow = malloc (quest_numallows * 4);
5303 ch = 0;
5304 fseek ( fp, 0, SEEK_SET );
5305 while (fgets (&allow_data[0], 255, fp) != NULL)
5306 {
5307 if ((allow_data[0] != 35) && (strlen(&allow_data[0]) > 5))
5308 {
5309 quest_allow[ch] = 0;
5310 qa = (unsigned char*) &quest_allow[ch++];
5311 qa[0] = hexToByte (&allow_data[0]);
5312 qa[1] = hexToByte (&allow_data[2]);
5313 qa[2] = hexToByte (&allow_data[4]);
5314 }
5315 }
5316 fclose ( fp );
5317 }
5318 printf ("Number of quest item allowances: %u\n", quest_numallows);
5319}
5320
5321
5322void LoadDropData()
5323{
5324 unsigned ch,ch2,ch3,d;
5325 unsigned char* rt_table;
5326 char id_file[256];
5327 FILE* fp;
5328 char convert_ch[10];
5329 int look_rate;
5330
5331 printf ("Loading drop data...\n");
5332
5333 // Each episode
5334 for (ch=1;ch<5;ch++)
5335 {
5336 if (ch != 3)
5337 {
5338 switch (ch)
5339 {
5340 case 0x01:
5341 rt_table = (unsigned char*) &rt_tables_ep1[0];
5342 break;
5343 case 0x02:
5344 rt_table = (unsigned char*) &rt_tables_ep2[0];
5345 break;
5346 case 0x04:
5347 rt_table = (unsigned char*) &rt_tables_ep4[0];
5348 break;
5349 }
5350 // Each difficulty
5351 for (d=0;d<4;d++)
5352 {
5353 // Each section ID
5354 for (ch2=0;ch2<10;ch2++)
5355 {
5356 id_file[0] = 0;
5357 switch (ch)
5358 {
5359 case 0x01:
5360 strcat (&id_file[0], "drop\\ep1_mob_");
5361 break;
5362 case 0x02:
5363 strcat (&id_file[0], "drop\\ep2_mob_");
5364 break;
5365 case 0x04:
5366 strcat (&id_file[0], "drop\\ep4_mob_");
5367 break;
5368 }
5369 _itoa (d, &convert_ch[0], 10);
5370 strcat (&id_file[0], &convert_ch[0]);
5371 strcat (&id_file[0], "_");
5372 _itoa (ch2, &convert_ch[0], 10);
5373 strcat (&id_file[0], &convert_ch[0]);
5374 strcat (&id_file[0], ".txt");
5375 ch3 = 0;
5376 fp = fopen ( &id_file[0], "r" );
5377 if (!fp)
5378 {
5379 printf ("Drop table not found \"%s\"", id_file[0] );
5380 printf ("Hit [ENTER] to quit...");
5381 gets (&dp[0]);
5382 exit (1);
5383 }
5384 look_rate = 1;
5385 while ( fgets ( &dp[0], 255, fp ) != NULL )
5386 {
5387 if ( dp[0] != 35 ) // not a comment
5388 {
5389 if ( look_rate )
5390 {
5391 rt_table[ch3++] = (unsigned char) atoi (&dp[0]);
5392 look_rate = 0;
5393 }
5394 else
5395 {
5396 if ( strlen ( &dp[0] ) < 6 )
5397 {
5398 printf ("Corrupted drop table \"%s\"", id_file[0] );
5399 printf ("Hit [ENTER] to quit...");
5400 gets (&dp[0]);
5401 exit (1);
5402 }
5403 _strupr ( &dp[0] );
5404 rt_table[ch3++] = hexToByte ( &dp[0] );
5405 rt_table[ch3++] = hexToByte ( &dp[2] );
5406 rt_table[ch3++] = hexToByte ( &dp[4] );
5407 look_rate = 1;
5408 }
5409 }
5410 }
5411 fclose (fp);
5412 ch3 = 0x194;
5413 memset (&rt_table[ch3], 0xFF, 30);
5414 id_file[9] = 98;
5415 id_file[10] = 111;
5416 id_file[11] = 120;
5417 fp = fopen ( &id_file[0], "r" );
5418 if (!fp)
5419 {
5420 printf ("Drop table not found \"%s\"", id_file[0] );
5421 printf ("Hit [ENTER] to quit...");
5422 gets (&dp[0]);
5423 exit (1);
5424 }
5425 look_rate = 0;
5426 while ( ( fgets ( &dp[0], 255, fp ) != NULL ) && ( ch3 < 0x1B2 ) )
5427 {
5428 if ( dp[0] != 35 ) // not a comment
5429 {
5430 switch ( look_rate )
5431 {
5432 case 0x00:
5433 rt_table[ch3] = (unsigned char) atoi (&dp[0]);
5434 look_rate = 1;
5435 break;
5436 case 0x01:
5437 rt_table[0x1B2 + ((ch3-0x194)*4)] = (unsigned char) atoi (&dp[0]);
5438 look_rate = 2;
5439 break;
5440 case 0x02:
5441 if ( strlen ( &dp[0] ) < 6 )
5442 {
5443 printf ("Corrupted drop table \"%s\"", id_file[0] );
5444 printf ("Hit [ENTER] to quit...");
5445 gets (&dp[0]);
5446 exit (1);
5447 }
5448 _strupr ( &dp[0] );
5449 rt_table[0x1B3 + ((ch3-0x194)*4)] = hexToByte ( &dp[0] );
5450 rt_table[0x1B4 + ((ch3-0x194)*4)] = hexToByte ( &dp[2] );
5451 rt_table[0x1B5 + ((ch3-0x194)*4)] = hexToByte ( &dp[4] );
5452 look_rate = 0;
5453 ch3++;
5454 break;
5455 }
5456 }
5457 }
5458 fclose (fp);
5459 rt_table += 0x800;
5460 }
5461 }
5462 }
5463 }
5464}
5465
5466#ifdef NO_SQL
5467
5468void UpdateDataFile ( const char* filename, unsigned count, void* data, unsigned record_size, int new_record )
5469{
5470 FILE* fp;
5471 unsigned fs;
5472
5473 fp = fopen (filename, "r+b");
5474 if (fp)
5475 {
5476 fseek (fp, 0, SEEK_END);
5477 fs = ftell (fp);
5478 if ((count * record_size) <= fs)
5479 {
5480 fseek (fp, count * record_size, SEEK_SET);
5481 fwrite (data, 1, record_size, fp);
5482 }
5483 else
5484 debug ("Could not seek to record for updating in %s", filename);
5485 fclose (fp);
5486 }
5487 else
5488 {
5489 fp = fopen (filename, "wb");
5490 if (fp)
5491 {
5492 fwrite (data, 1, record_size, fp); // Has to be the first record...
5493 fclose (fp);
5494 }
5495 else
5496 debug ("Could not open %s for writing!\n", filename);
5497 }
5498}
5499
5500
5501void DumpDataFile ( const char* filename, unsigned* count, void** data, unsigned record_size )
5502{
5503 FILE* fp;
5504 unsigned ch;
5505
5506 printf ("Dumping \"%s\" ... ", filename);
5507 fp = fopen (filename, "wb");
5508 if (fp)
5509 {
5510 for (ch=0;ch<*count;ch++)
5511 fwrite (data[ch], 1, record_size, fp);
5512 fclose (fp);
5513 }
5514 else
5515 debug ("Could not open %s for writing!\n", filename);
5516 printf ("done!\n");
5517}
5518
5519void LoadDataFile ( const char* filename, unsigned* count, void** data, unsigned record_size )
5520{
5521 FILE* fp;
5522 unsigned ch;
5523
5524 printf ("Loading \"%s\" ... ", filename);
5525 fp = fopen (filename, "rb");
5526 if (fp)
5527 {
5528 fseek (fp, 0, SEEK_END);
5529 *count = ftell (fp) / record_size;
5530 fseek (fp, 0, SEEK_SET);
5531 for (ch=0;ch<*count;ch++)
5532 {
5533 data[ch] = malloc (record_size);
5534 if (!data[ch])
5535 {
5536 printf ("Out of memory!\nHit [ENTER]");
5537 gets (&dp[0]);
5538 exit (1);
5539 }
5540 fread (data[ch], 1, record_size, fp);
5541 }
5542 fclose (fp);
5543 }
5544 printf ("done!\n");
5545}
5546
5547#endif
5548
5549
5550/*LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
5551{
5552 if(message == MYWM_NOTIFYICON)
5553 {
5554 switch (lParam)
5555 {
5556 case WM_LBUTTONDBLCLK:
5557 switch (wParam)
5558 {
5559 case 100:
5560 if (program_hidden)
5561 {
5562 program_hidden = 0;
5563 ShowWindow (consoleHwnd, SW_NORMAL);
5564 SetForegroundWindow (consoleHwnd);
5565 SetFocus(consoleHwnd);
5566 }
5567 else
5568 {
5569 program_hidden = 1;
5570 ShowWindow (consoleHwnd, SW_HIDE);
5571 }
5572 return TRUE;
5573 break;
5574 }
5575 break;
5576 }
5577 }
5578 return DefWindowProc( hwnd, message, wParam, lParam );
5579}*/
5580
5581
5582/********************************************************
5583**
5584** main :-
5585**
5586********************************************************/
5587
5588int
5589main( int argc, char * argv[] )
5590{
5591 unsigned ch,ch2;
5592 struct in_addr login_in;
5593 struct in_addr character_in;
5594 struct in_addr ship_in;
5595 struct sockaddr_in listen_in;
5596 unsigned listen_length;
5597 int login_sockfd = -1, character_sockfd = -1, ship_sockfd = -1;
5598 int pkt_len, pkt_c, bytes_sent;
5599 unsigned short this_packet;
5600 unsigned ship_this_packet;
5601
5602 FILE* fp;
5603 //int wserror;
5604 unsigned char MDBuffer[17] = {0};
5605 unsigned connectNum, shipNum;
5606 //HINSTANCE hinst;
5607 //NOTIFYICONDATA nid = {0};
5608 //WNDCLASS wc = {0};
5609 //HWND hwndWindow;
5610 //MSG msg;
5611 //WSADATA winsock_data;
5612
5613 //consoleHwnd = GetConsoleWindow();
5614 //hinst = GetModuleHandle(NULL);
5615
5616 dp[0] = 0;
5617
5618 memset (&dp[0], 0, sizeof (dp));
5619
5620 strcat (&dp[0], "Tethealla Login Server version ");
5621 strcat (&dp[0], SERVER_VERSION );
5622 strcat (&dp[0], " coded by Sodaboy");
5623 //SetConsoleTitle (&dp[0]);
5624
5625 printf ("\nTethealla Login Server version %s Copyright (C) 2008 Terry Chatman Jr.\n", SERVER_VERSION);
5626 printf ("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
5627 printf ("This program comes with ABSOLUTELY NO WARRANTY; for details\n");
5628 printf ("see section 15 in gpl-3.0.txt\n");
5629 printf ("This is free software, and you are welcome to redistribute it\n");
5630 printf ("under certain conditions; see gpl-3.0.txt for details.\n");
5631/*
5632 for (ch=0;ch<5;ch++)
5633 {
5634 printf (".");
5635 Sleep (1000);
5636 }*/
5637 printf ("\n\n");
5638
5639 //WSAStartup(MAKEWORD(1,1), &winsock_data);
5640
5641 srand ( (unsigned) time(NULL) );
5642
5643 memset ( &dress_flags[0], 0, sizeof (DRESSFLAG) * MAX_DRESS_FLAGS);
5644
5645 printf ("Loading configuration from tethealla.ini ...");
5646 load_config_file();
5647 printf (" OK!\n");
5648
5649 /* Set this up for later. */
5650
5651 memset (&empty_bank, 0, sizeof (BANK));
5652
5653 for (ch=0;ch<200;ch++)
5654 empty_bank.bankInventory[ch].itemid = 0xFFFFFFFF;
5655
5656#ifdef NO_SQL
5657 LoadDataFile ("account.dat", &num_accounts, &account_data[0], sizeof(L_ACCOUNT_DATA));
5658 LoadDataFile ("bank.dat", &num_bankdata, &bank_data[0], sizeof(L_BANK_DATA));
5659 LoadDataFile ("character.dat", &num_characters, &character_data[0], sizeof(L_CHARACTER_DATA));
5660 LoadDataFile ("guild.dat", &num_guilds, &guild_data[0], sizeof(L_GUILD_DATA));
5661 //LoadDataFile ("hwbans.dat", &num_hwbans, &hw_bans[0], sizeof(L_HW_BANS));
5662 //LoadDataFile ("ipbans.dat", &num_ipbans, &ip_bans[0], sizeof(L_IP_BANS));
5663 LoadDataFile ("keydata.dat", &num_keydata, &key_data[0], sizeof(L_KEY_DATA));
5664 LoadDataFile ("security.dat", &num_security, &security_data[0], sizeof(L_SECURITY_DATA));
5665 LoadDataFile ("shipkey.dat", &num_shipkeys, &ship_data[0], sizeof(L_SHIP_DATA));
5666 LoadDataFile ("team.dat", &num_teams, &team_data[0], sizeof(L_TEAM_DATA));
5667#endif
5668 printf ("Loading PlyLevelTbl.bin ...");
5669 fp = fopen ( "PlyLevelTbl.bin", "rb" );
5670 if (!fp)
5671 {
5672 printf ("Can't proceed without plyleveltbl.bin!\n");
5673 printf ("Hit [ENTER]");
5674 gets (&dp[0]);
5675 exit (1);
5676 }
5677 fread ( &startingStats[0], 1, 12*14, fp );
5678 fclose ( fp );
5679 printf (" OK!\n");
5680 printf ("Loading 0xE2 base packet ...");
5681 fp = fopen ( "e2base.bin", "rb" );
5682 if (!fp)
5683 {
5684 printf ("Can't proceed without e2base.bin!\n");
5685 printf ("Hit [ENTER]");
5686 gets (&dp[0]);
5687 exit (1);
5688 }
5689 fread ( &E2_Base[0], 1, 2808, fp );
5690 fclose ( fp );
5691 printf (" OK!\n");
5692 printf ("Loading 0xE7 base packet ...");
5693 fp = fopen ( "e7base.bin", "rb" );
5694 if (!fp)
5695 {
5696 printf ("Can't proceed without e7base.bin!\n");
5697 printf ("Hit [ENTER]");
5698 gets (&dp[0]);
5699 exit (1);
5700 }
5701 fread ( &E7_Base, 1, sizeof(CHARDATA), fp );
5702 fclose ( fp );
5703 printf (" OK!\n");
5704 printf ("Loading parameter files specified in e8send.txt ...");
5705 construct0xEB();
5706 memcpy (&Packet03[0x54], &Message03[0], sizeof (Message03));
5707 printf ("\nLoading quest item allowances...\n");
5708 LoadQuestAllow();
5709 LoadDropData();
5710 printf ("... done!\n");
5711#ifdef DEBUG_OUTPUT
5712#ifndef NO_SQL
5713 printf ("\nMySQL connection parameters\n");
5714 printf ("///////////////////////////\n");
5715 printf ("Host: %s\n", mySQL_Host );
5716 printf ("Port: %u\n", mySQL_Port );
5717 printf ("Username: %s\n", mySQL_Username );
5718 printf ("Password: %s\n", mySQL_Password );
5719 printf ("Database: %s\n", mySQL_Database );
5720#endif
5721#endif
5722 printf ("\nLogin server parameters\n");
5723 printf ("///////////////////////\n");
5724 if (override_on)
5725 printf ("NOTE: IP override feature is turned on.\nThe server will bind to %u.%u.%u.%u but will send out the IP listed below.\n", overrideIP[0], overrideIP[1], overrideIP[2], overrideIP[3] );
5726 printf ("IP: %u.%u.%u.%u\n", serverIP[0], serverIP[1], serverIP[2], serverIP[3] );
5727 printf ("Login Port: %u\n", serverPort );
5728 printf ("Character Port: %u\n", serverPort+1 );
5729 printf ("Maximum Connections: %u\n", serverMaxConnections );
5730 printf ("Maximum Ships: %u\n\n", serverMaxShips );
5731 printf ("Allocating %u bytes of memory for connections...", sizeof (BANANA) * serverMaxConnections );
5732 for (ch=0;ch<serverMaxConnections;ch++)
5733 {
5734 connections[ch] = malloc ( sizeof (BANANA) );
5735 if ( !connections[ch] )
5736 {
5737 printf ("Out of memory!\n");
5738 printf ("Hit [ENTER]");
5739 gets (&dp[0]);
5740 exit (1);
5741 }
5742 initialize_connection (connections[ch]);
5743 }
5744 printf (" OK!\n");
5745 printf ("Allocating %u bytes of memory for ships...", sizeof (ORANGE) * serverMaxShips );
5746 memset (&ships, 0, 4 * serverMaxShips);
5747 for (ch=0;ch<serverMaxShips;ch++)
5748 {
5749 ships[ch] = malloc ( sizeof (ORANGE) );
5750 if ( !ships[ch] )
5751 {
5752 printf ("Out of memory!\n");
5753 printf ("Hit [ENTER]");
5754 gets (&dp[0]);
5755 exit (1);
5756 }
5757 initialize_ship (ships[ch]);
5758 }
5759 printf (" OK!\n\n");
5760 printf ("Constructing default ship list packet ...");
5761 construct0xA0();
5762 printf (" OK!\n\n");
5763
5764#ifndef NO_SQL
5765 printf ("Connecting up to the MySQL database ...");
5766
5767 if ( (myData = mysql_init((MYSQL*) 0)) &&
5768 mysql_real_connect( myData, &mySQL_Host[0], &mySQL_Username[0], &mySQL_Password[0], NULL, mySQL_Port,
5769 NULL, 0 ) )
5770 {
5771 if ( mysql_select_db( myData, &mySQL_Database[0] ) < 0 ) {
5772 printf( "Can't select the %s database !\n", mySQL_Database ) ;
5773 mysql_close( myData ) ;
5774 return 2 ;
5775 }
5776 }
5777 else {
5778 printf( "Can't connect to the mysql server (%s) on port %d !\nmysql_error = %s\n",
5779 mySQL_Host, mySQL_Port, mysql_error(myData) ) ;
5780
5781 mysql_close( myData ) ;
5782 return 1 ;
5783 }
5784
5785 printf (" OK!\n\n");
5786
5787 printf ("Setting session wait_timeout ...");
5788
5789 /* Set MySQL to time out after 7 days of inactivity... lulz :D */
5790
5791 sprintf (&myQuery[0], "SET SESSION wait_timeout = 604800");
5792 mysql_query (myData, &myQuery[0]);
5793 printf (" OK!\n\n");
5794
5795#endif
5796
5797 printf ("Getting max ship key count... ");
5798
5799#ifdef NO_SQL
5800
5801 max_ship_keys = 0;
5802 for (ds=0;ds<num_shipkeys;ds++)
5803 {
5804 if (ship_data[ds]->idx >= max_ship_keys)
5805 max_ship_keys = ship_data[ds]->idx;
5806 }
5807
5808#else
5809
5810 sprintf (&myQuery[0], "SELECT * from ship_data" );
5811
5812 if ( ! mysql_query ( myData, &myQuery[0] ) )
5813 {
5814 unsigned key_rows;
5815
5816 myResult = mysql_store_result ( myData );
5817 key_rows = (int) mysql_num_rows ( myResult );
5818 max_ship_keys = 0;
5819 while ( key_rows )
5820 {
5821 myRow = mysql_fetch_row ( myResult );
5822 if ( (unsigned) atoi ( myRow[1] ) > max_ship_keys )
5823 max_ship_keys = atoi ( myRow[1] );
5824 key_rows --;
5825 }
5826 printf ("(%u) ", max_ship_keys);
5827 mysql_free_result ( myResult );
5828
5829 }
5830 else
5831 {
5832 printf ("Unable to query the key database.\n");
5833 }
5834
5835#endif
5836
5837 printf (" OK!\n");
5838
5839 printf ("Loading default.flag ...");
5840 fp = fopen ( "default.flag", "rb" );
5841 if (!fp)
5842 {
5843 printf ("Can't proceed without default.flag!\n");
5844 printf ("Hit [ENTER]");
5845 gets (&dp[0]);
5846 exit (1);
5847 }
5848 fread ( &DefaultTeamFlag[0], 1, 2048, fp );
5849 fclose ( fp );
5850#ifndef NO_SQL
5851 mysql_real_escape_string (myData, &DefaultTeamFlagSlashes[0], &DefaultTeamFlag[0], 2048);
5852#endif
5853 printf (" OK!\n");
5854
5855 /* Open the PSO BB Login Server Port... */
5856
5857 printf ("Opening server login port %u for connections.\n", serverPort);
5858
5859#ifdef USEADDR_ANY
5860 login_in.s_addr = INADDR_ANY;
5861#else
5862 if (override_on)
5863 *(unsigned *) &login_in.s_addr = *(unsigned *) &overrideIP[0];
5864 else
5865 *(unsigned *) &login_in.s_addr = *(unsigned *) &serverIP[0];
5866#endif
5867 login_sockfd = tcp_sock_open( login_in, serverPort );
5868
5869 tcp_listen (login_sockfd);
5870
5871 /* Open the PSO BB Character Server Port... */
5872
5873 printf ("Opening server character port %u for connections.\n", serverPort + 1);
5874
5875#ifdef USEADDR_ANY
5876 character_in.s_addr = INADDR_ANY;
5877#else
5878 if (override_on)
5879 *(unsigned *) &character_in.s_addr = *(unsigned*) &overrideIP[0];
5880 else
5881 *(unsigned *) &character_in.s_addr = *(unsigned *) &serverIP[0];
5882#endif
5883 character_sockfd = tcp_sock_open( character_in, serverPort + 1 );
5884
5885 tcp_listen (character_sockfd);
5886
5887 /* Open the Ship Port... */
5888
5889 printf ("Opening ship port 3455 for connections.\n" );
5890
5891#ifdef USEADDR_ANY
5892 ship_in.s_addr = INADDR_ANY;
5893#else
5894 if (override_on)
5895 *(unsigned *) &ship_in.s_addr = *(unsigned *) &overrideIP[0];
5896 else
5897 *(unsigned *) &ship_in.s_addr = *(unsigned *) &serverIP[0];
5898#endif
5899 ship_sockfd = tcp_sock_open( ship_in, 3455 );
5900
5901 tcp_listen (ship_sockfd);
5902
5903 if ((login_sockfd<0) || (character_sockfd<0) || (ship_sockfd<0))
5904 {
5905 printf ("Failed to open ports for connections.\n");
5906 printf ("Hit [ENTER]");
5907 gets (&dp[0]);
5908 exit (1);
5909 }
5910
5911 printf ("\nListening...\n");
5912
5913 //wc.hbrBackground =(HBRUSH)GetStockObject(WHITE_BRUSH);
5914 //wc.hIcon = LoadIcon( hinst, IDI_APPLICATION );
5915 //wc.hCursor = LoadCursor( hinst, IDC_ARROW );
5916 //wc.hInstance = hinst;
5917 //wc.lpfnWndProc = WndProc;
5918 //wc.lpszClassName = "sodaboy";
5919 //wc.style = CS_HREDRAW | CS_VREDRAW;
5920
5921 //if (! RegisterClass( &wc ) )
5922 //{
5923 // printf ("RegisterClass failure.\n");
5924 // exit (1);
5925 //}
5926
5927 //hwndWindow = CreateWindow ("sodaboy","hidden window", WS_MINIMIZE, 1, 1, 1, 1,
5928 // NULL,
5929 // NULL,
5930 // hinst,
5931 // NULL );
5932
5933 //backupHwnd = hwndWindow;
5934
5935 /*if (!hwndWindow)
5936 {
5937 printf ("Failed to create window.");
5938 exit (1);
5939 }
5940
5941 ShowWindow ( hwndWindow, SW_HIDE );
5942 UpdateWindow ( hwndWindow );
5943 ShowWindow ( consoleHwnd, SW_HIDE );
5944 UpdateWindow ( consoleHwnd );
5945
5946 nid.cbSize = sizeof(nid);
5947 nid.hWnd = hwndWindow;
5948 nid.uID = 100;
5949 nid.uCallbackMessage = MYWM_NOTIFYICON;
5950 nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
5951 nid.hIcon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_ICON1));
5952 nid.szTip[0] = 0;
5953 strcat (&nid.szTip[0], "Tethealla Login ");
5954 strcat (&nid.szTip[0], SERVER_VERSION);
5955 strcat (&nid.szTip[0], " - Double click to show/hide");
5956 Shell_NotifyIcon(NIM_ADD, &nid);
5957
5958*/
5959#ifdef NO_SQL
5960
5961 lastdump = (unsigned) time(NULL);
5962
5963#endif
5964
5965 for (;;)
5966 {
5967 int nfds = 0;
5968
5969 /* Ping pong?! */
5970
5971 servertime = time(NULL);
5972
5973 /* Process the system tray icon */
5974
5975 /*if ( backupHwnd != hwndWindow )
5976 {
5977 debug ("hwndWindow has been corrupted...");
5978 display_packet ( (unsigned char*) &hwndWindow, sizeof (HWND));
5979 hwndWindow = backupHwnd;
5980 WriteLog ("hwndWindow corrupted %s", (char*) &dp[0] );
5981 }
5982
5983 if ( PeekMessage( &msg, hwndWindow, 0, 0, 1 ) )
5984 {
5985 TranslateMessage(&msg);
5986 DispatchMessage(&msg);
5987 }*/
5988
5989
5990#ifdef NO_SQL
5991
5992 if ( (unsigned) servertime - lastdump > 600 )
5993 {
5994 printf ("Refreshing account and ship key databases...\n");
5995 for (ch=0;ch<num_accounts;ch++)
5996 free (account_data[ch]);
5997 num_accounts = 0;
5998 LoadDataFile ("account.dat", &num_accounts, &account_data[0], sizeof(L_ACCOUNT_DATA));
5999 for (ch=0;ch<num_shipkeys;ch++)
6000 free (ship_data[ch]);
6001 num_shipkeys = 0;
6002 LoadDataFile ("shipkey.dat", &num_shipkeys, &ship_data[0], sizeof(L_SHIP_DATA));
6003 lastdump = (unsigned) servertime;
6004 }
6005
6006#endif
6007
6008 /* Clear socket activity flags. */
6009
6010 FD_ZERO (&ReadFDs);
6011 FD_ZERO (&WriteFDs);
6012 FD_ZERO (&ExceptFDs);
6013
6014 for (ch=0;ch<serverNumConnections;ch++)
6015 {
6016 connectNum = serverConnectionList[ch];
6017 workConnect = connections[connectNum];
6018
6019 if (workConnect->plySockfd >= 0)
6020 {
6021 if (workConnect->packetdata)
6022 {
6023 this_packet = *(unsigned short*) &workConnect->packet[workConnect->packetread];
6024 memcpy (&workConnect->decryptbuf[0], &workConnect->packet[workConnect->packetread], this_packet);
6025
6026 switch (workConnect->login)
6027 {
6028 case 0x01:
6029 // Login server
6030 LoginProcessPacket (workConnect);
6031 break;
6032 case 0x02:
6033 // Character server
6034 CharacterProcessPacket (workConnect);
6035 break;
6036 }
6037 workConnect->packetread += this_packet;
6038 if (workConnect->packetread == workConnect->packetdata)
6039 workConnect->packetread = workConnect->packetdata = 0;
6040 }
6041
6042 if (workConnect->lastTick != (unsigned) servertime)
6043 {
6044 if (workConnect->lastTick > (unsigned) servertime)
6045 ch2 = 1;
6046 else
6047 ch2 = 1 + ((unsigned) servertime - workConnect->lastTick);
6048 workConnect->lastTick = (unsigned) servertime;
6049 workConnect->packetsSec /= ch2;
6050 workConnect->toBytesSec /= ch2;
6051 workConnect->fromBytesSec /= ch2;
6052 }
6053
6054 /*
6055 if (((unsigned) servertime - workConnect->connected >= 300) ||
6056 (workConnect->connected > (unsigned) servertime))
6057 {
6058 Send1A ("You have been idle for too long. Disconnecting...", workConnect);
6059 workConnect->todc = 1;
6060 }
6061 */
6062
6063 FD_SET (workConnect->plySockfd, &ReadFDs);
6064 nfds = max (nfds, workConnect->plySockfd);
6065 FD_SET (workConnect->plySockfd, &ExceptFDs);
6066 nfds = max (nfds, workConnect->plySockfd);
6067 if (workConnect->snddata - workConnect->sndwritten)
6068 {
6069 FD_SET (workConnect->plySockfd, &WriteFDs);
6070 nfds = max (nfds, workConnect->plySockfd);
6071 }
6072 }
6073 }
6074
6075 for (ch=0;ch<serverNumShips;ch++)
6076 {
6077 shipNum = serverShipList[ch];
6078 workShip = ships[shipNum];
6079
6080 if (workShip->shipSockfd >= 0)
6081 {
6082 // Send a ping request to the ship when 30 seconds passes...
6083 if (((unsigned) servertime - workShip->last_ping >= 30) && (workShip->sent_ping == 0))
6084 {
6085 workShip->sent_ping = 1;
6086 ShipSend11 (workShip);
6087 }
6088
6089 // If it's been over a minute since we've heard from a ship, terminate
6090 // the connection with it.
6091
6092 if ((unsigned) servertime - workShip->last_ping > 60)
6093 {
6094 printf ("%s ship ping timeout.\n", workShip->name );
6095 initialize_ship (workShip);
6096 }
6097 else
6098 {
6099 if (workShip->packetdata)
6100 {
6101 ship_this_packet = *(unsigned *)&workShip->packet[workShip->packetread];
6102 memcpy (&workShip->decryptbuf[0], &workShip->packet[workShip->packetread], ship_this_packet);
6103
6104 ShipProcessPacket (workShip);
6105
6106 workShip->packetread += ship_this_packet;
6107
6108 if (workShip->packetread == workShip->packetdata)
6109 workShip->packetread = workShip->packetdata = 0;
6110 }
6111
6112
6113 /* Limit time of authorization to 60 seconds... */
6114
6115 if ((workShip->authed == 0) && ((unsigned) servertime - workShip->connected >= 60))
6116 workShip->todc = 1;
6117
6118
6119 FD_SET (workShip->shipSockfd, &ReadFDs);
6120 nfds = max (nfds, workShip->shipSockfd);
6121 if (workShip->snddata - workShip->sndwritten)
6122 {
6123 FD_SET (workShip->shipSockfd, &WriteFDs);
6124 nfds = max (nfds, workShip->shipSockfd);
6125 }
6126 }
6127 }
6128 }
6129
6130 FD_SET (login_sockfd, &ReadFDs);
6131 nfds = max (nfds, login_sockfd);
6132 FD_SET (character_sockfd, &ReadFDs);
6133 nfds = max (nfds, character_sockfd);
6134 FD_SET (ship_sockfd, &ReadFDs);
6135 nfds = max (nfds, ship_sockfd);
6136
6137 /* Check sockets for activity. */
6138
6139 if ( select ( nfds + 1, &ReadFDs, &WriteFDs, &ExceptFDs, &select_timeout ) > 0 )
6140 {
6141 if (FD_ISSET (login_sockfd, &ReadFDs))
6142 {
6143 // Someone's attempting to connect to the login server.
6144 ch = free_connection();
6145 if (ch != 0xFFFF)
6146 {
6147 listen_length = sizeof (listen_in);
6148 workConnect = connections[ch];
6149 if ( ( workConnect->plySockfd = tcp_accept ( login_sockfd, (struct sockaddr*) &listen_in, &listen_length ) ) >= 0 )
6150 {
6151 workConnect->connection_index = ch;
6152 serverConnectionList[serverNumConnections++] = ch;
6153 memcpy ( &workConnect->IP_Address[0], inet_ntoa (listen_in.sin_addr), 16 );
6154 printf ("Accepted LOGIN connection from %s:%u\n", workConnect->IP_Address, listen_in.sin_port );
6155 start_encryption (workConnect);
6156 /* Doin' login process... */
6157 workConnect->login = 1;
6158 }
6159 }
6160 }
6161
6162 if (FD_ISSET (character_sockfd, &ReadFDs))
6163 {
6164 // Someone's attempting to connect to the character server.
6165 ch = free_connection();
6166 if (ch != 0xFFFF)
6167 {
6168 listen_length = sizeof (listen_in);
6169 workConnect = connections[ch];
6170 if ( ( workConnect->plySockfd = tcp_accept ( character_sockfd, (struct sockaddr*) &listen_in, &listen_length ) ) >= 0 )
6171 {
6172 workConnect->connection_index = ch;
6173 serverConnectionList[serverNumConnections++] = ch;
6174 memcpy ( &workConnect->IP_Address[0], inet_ntoa (listen_in.sin_addr), 16 );
6175 printf ("Accepted CHARACTER connection from %s:%u\n", inet_ntoa (listen_in.sin_addr), listen_in.sin_port );
6176 start_encryption (workConnect);
6177 /* Doin' character process... */
6178 workConnect->login = 2;
6179 }
6180 }
6181 }
6182
6183 if (FD_ISSET (ship_sockfd, &ReadFDs))
6184 {
6185 // A ship is attempting to connect to the ship transfer port.
6186 ch = free_shipconnection();
6187 if (ch != 0xFFFF)
6188 {
6189 listen_length = sizeof (listen_in);
6190 workShip = ships[ch];
6191 if ( ( workShip->shipSockfd = tcp_accept ( ship_sockfd, (struct sockaddr*) &listen_in, &listen_length ) ) >= 0 )
6192 {
6193 workShip->connection_index = ch;
6194 serverShipList[serverNumShips++] = ch;
6195 printf ("Accepted SHIP connection from %s:%u\n", inet_ntoa (listen_in.sin_addr), listen_in.sin_port );
6196 *(unsigned *) &workShip->listenedAddr[0] = *(unsigned*) &listen_in.sin_addr;
6197 workShip->connected = workShip->last_ping = (unsigned) servertime;
6198 ShipSend00 (workShip);
6199 }
6200 }
6201 }
6202
6203 // Process client connections
6204
6205 for (ch=0;ch<serverNumConnections;ch++)
6206 {
6207 connectNum = serverConnectionList[ch];
6208 workConnect = connections[connectNum];
6209
6210 if (workConnect->plySockfd >= 0)
6211 {
6212 if (FD_ISSET(workConnect->plySockfd, &ReadFDs))
6213 {
6214 // Read shit.
6215 if ( ( pkt_len = recv (workConnect->plySockfd, &tmprcv[0], TCP_BUFFER_SIZE - 1, 0) ) <= 0 )
6216 {
6217 /*
6218 wserror = WSAGetLastError();
6219 printf ("Could not read data from client...\n");
6220 printf ("Socket Error %u.\n", wserror );
6221 */
6222 initialize_connection (workConnect);
6223 }
6224 else
6225 {
6226 workConnect->fromBytesSec += (unsigned) pkt_len;
6227 // Work with it.
6228 for (pkt_c=0;pkt_c<pkt_len;pkt_c++)
6229 {
6230 workConnect->rcvbuf[workConnect->rcvread++] = tmprcv[pkt_c];
6231
6232 if (workConnect->rcvread == 8)
6233 {
6234 /* Decrypt the packet header after receiving 8 bytes. */
6235
6236 cipher_ptr = &workConnect->client_cipher;
6237
6238 decryptcopy ( &workConnect->peekbuf[0], &workConnect->rcvbuf[0], 8 );
6239
6240 /* Make sure we're expecting a multiple of 8 bytes. */
6241
6242 workConnect->expect = *(unsigned short*) &workConnect->peekbuf[0];
6243
6244 if ( workConnect->expect % 8 )
6245 workConnect->expect += ( 8 - ( workConnect->expect % 8 ) );
6246
6247 if ( workConnect->expect > TCP_BUFFER_SIZE )
6248 {
6249 initialize_connection ( workConnect );
6250 break;
6251 }
6252 }
6253
6254 if ( ( workConnect->rcvread == workConnect->expect ) && ( workConnect->expect != 0 ) )
6255 {
6256 if ( workConnect->packetdata + workConnect->expect > TCP_BUFFER_SIZE )
6257 {
6258 initialize_connection ( workConnect );
6259 break;
6260 }
6261 else
6262 {
6263 /* Decrypt the rest of the data if needed. */
6264
6265 cipher_ptr = &workConnect->client_cipher;
6266
6267 *(long long*) &workConnect->packet[workConnect->packetdata] = *(long long*) &workConnect->peekbuf[0];
6268
6269 if ( workConnect->rcvread > 8 )
6270 decryptcopy ( &workConnect->packet[workConnect->packetdata + 8], &workConnect->rcvbuf[8], workConnect->expect - 8 );
6271
6272 this_packet = *(unsigned short*) &workConnect->peekbuf[0];
6273 workConnect->packetdata += this_packet;
6274
6275 workConnect->packetsSec ++;
6276
6277 if ((workConnect->packetsSec > 40) ||
6278 (workConnect->fromBytesSec > 15000) ||
6279 (workConnect->toBytesSec > 500000))
6280 {
6281 printf ("%u disconnected for possible DDOS. (p/s: %u, tb/s: %u, fb/s: %u)\n", workConnect->guildcard, workConnect->packetsSec, workConnect->toBytesSec, workConnect->fromBytesSec);
6282 initialize_connection(workConnect);
6283 break;
6284 }
6285
6286 workConnect->rcvread = 0;
6287 }
6288 }
6289 }
6290 }
6291 }
6292
6293 if (FD_ISSET(workConnect->plySockfd, &WriteFDs))
6294 {
6295 // Write shit.
6296
6297 bytes_sent = send (workConnect->plySockfd, &workConnect->sndbuf[workConnect->sndwritten],
6298 workConnect->snddata - workConnect->sndwritten, 0);
6299 if (bytes_sent == SOCKET_ERROR)
6300 {
6301 /*
6302 wserror = WSAGetLastError();
6303 printf ("Could not send data to client...\n");
6304 printf ("Socket Error %u.\n", wserror );
6305 */
6306 initialize_connection (workConnect);
6307 }
6308 else
6309 {
6310 workConnect->sndwritten += bytes_sent;
6311 workConnect->toBytesSec += (unsigned) bytes_sent;
6312 }
6313
6314 if (workConnect->sndwritten == workConnect->snddata)
6315 workConnect->sndwritten = workConnect->snddata = 0;
6316 }
6317
6318 if (workConnect->todc)
6319 {
6320 if ( workConnect->snddata - workConnect->sndwritten )
6321 send (workConnect->plySockfd, &workConnect->sndbuf[workConnect->sndwritten],
6322 workConnect->snddata - workConnect->sndwritten, 0);
6323 initialize_connection (workConnect);
6324 }
6325
6326 if (FD_ISSET(workConnect->plySockfd, &ExceptFDs)) // Exception?
6327 initialize_connection (workConnect);
6328 }
6329 }
6330
6331 // Process ship connections
6332
6333 for (ch=0;ch<serverNumShips;ch++)
6334 {
6335 shipNum = serverShipList[ch];
6336 workShip = ships[shipNum];
6337
6338 if (workShip->shipSockfd >= 0)
6339 {
6340 if (FD_ISSET(workShip->shipSockfd, &ReadFDs))
6341 {
6342 // Read shit.
6343 if ( ( pkt_len = recv (workShip->shipSockfd, &tmprcv[0], PACKET_BUFFER_SIZE - 1, 0) ) <= 0 )
6344 {
6345 /*
6346 wserror = WSAGetLastError();
6347 printf ("Could not read data from client...\n");
6348 printf ("Socket Error %u.\n", wserror );
6349 */
6350 printf ("Lost connection with the %s ship...\n", workShip->name );
6351 initialize_ship (workShip);
6352 }
6353 else
6354 {
6355 // Work with it.
6356 for (pkt_c=0;pkt_c<pkt_len;pkt_c++)
6357 {
6358 workShip->rcvbuf[workShip->rcvread++] = tmprcv[pkt_c];
6359
6360 if (workShip->rcvread == 4)
6361 {
6362 /* Read out how much data we're expecting this packet. */
6363 workShip->expect = *(unsigned*) &workShip->rcvbuf[0];
6364
6365 if ( workShip->expect > TCP_BUFFER_SIZE )
6366 {
6367 printf ("Lost connection with the %s ship...\n", workShip->name );
6368 initialize_ship ( workShip ); /* This shouldn't happen, lol. */
6369 }
6370 }
6371
6372 if ( ( workShip->rcvread == workShip->expect ) && ( workShip->expect != 0 ) )
6373 {
6374 decompressShipPacket ( workShip, &workShip->decryptbuf[0], &workShip->rcvbuf[0] );
6375
6376 workShip->expect = *(unsigned *) &workShip->decryptbuf[0];
6377
6378 if ( workShip->packetdata + workShip->expect < PACKET_BUFFER_SIZE )
6379 {
6380 memcpy ( &workShip->packet[workShip->packetdata], &workShip->decryptbuf[0], workShip->expect );
6381 workShip->packetdata += workShip->expect;
6382 }
6383 else
6384 {
6385 initialize_ship ( workShip );
6386 break;
6387 }
6388 workShip->rcvread = 0;
6389 }
6390 }
6391 }
6392 }
6393
6394 if (FD_ISSET(workShip->shipSockfd, &WriteFDs))
6395 {
6396 // Write shit.
6397
6398 bytes_sent = send (workShip->shipSockfd, &workShip->sndbuf[workShip->sndwritten],
6399 workShip->snddata - workShip->sndwritten, 0);
6400 if (bytes_sent == SOCKET_ERROR)
6401 {
6402 /*
6403 wserror = WSAGetLastError();
6404 printf ("Could not send data to client...\n");
6405 printf ("Socket Error %u.\n", wserror );
6406 */
6407 printf ("Lost connection with the %s ship...\n", workShip->name );
6408 initialize_ship (workShip);
6409 }
6410 else
6411 workShip->sndwritten += bytes_sent;
6412
6413 if (workShip->sndwritten == workShip->snddata)
6414 workShip->sndwritten = workShip->snddata = 0;
6415
6416 }
6417
6418 if (workShip->todc)
6419 {
6420 if ( workShip->snddata - workShip->sndwritten )
6421 send (workShip->shipSockfd, &workShip->sndbuf[workShip->sndwritten],
6422 workShip->snddata - workShip->sndwritten, 0);
6423 printf ("Terminated connection with ship...\n" );
6424 initialize_ship (workShip);
6425 }
6426
6427 }
6428 }
6429 }
6430 }
6431#ifndef NO_SQL
6432 mysql_close( myData ) ;
6433#endif
6434 return 0;
6435}
6436
6437
6438void send_to_server(int sock, char* packet)
6439{
6440 int pktlen;
6441
6442 pktlen = strlen (packet);
6443
6444 if (send(sock, packet, pktlen, 0) != pktlen)
6445 {
6446 printf ("send_to_server(): failure");
6447 printf ("Hit [ENTER]");
6448 gets (&dp[0]);
6449 exit(1);
6450 }
6451
6452}
6453
6454int receive_from_server(int sock, char* packet)
6455{
6456 int pktlen;
6457
6458 if ((pktlen = recv(sock, packet, TCP_BUFFER_SIZE - 1, 0)) <= 0)
6459 {
6460 printf ("receive_from_server(): failure");
6461 printf ("Hit [ENTER]");
6462 gets (&dp[0]);
6463 exit(1);
6464 }
6465 packet[pktlen] = 0;
6466 return pktlen;
6467}
6468
6469void tcp_listen (int sockfd)
6470{
6471 if (listen(sockfd, 10) < 0)
6472 {
6473 debug_perror ("Could not listen for connection");
6474 printf ("Hit [ENTER]");
6475 gets (&dp[0]);
6476 exit(1);
6477 }
6478}
6479
6480int tcp_accept (int sockfd, struct sockaddr *client_addr, int *addr_len )
6481{
6482 int fd;
6483
6484 if ((fd = accept (sockfd, client_addr, addr_len)) < 0)
6485 debug_perror ("Could not accept connection");
6486
6487 return (fd);
6488}
6489
6490int tcp_sock_connect(char* dest_addr, int port)
6491{
6492 int fd;
6493 struct sockaddr_in sa;
6494
6495 /* Clear it out */
6496 memset((void *)&sa, 0, sizeof(sa));
6497
6498 fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
6499
6500 /* Error */
6501 if( fd < 0 )
6502 debug_perror("Could not create socket");
6503 else
6504 {
6505
6506 memset (&sa, 0, sizeof(sa));
6507 sa.sin_family = AF_INET;
6508 sa.sin_addr.s_addr = inet_addr (dest_addr);
6509 sa.sin_port = htons((unsigned short) port);
6510
6511 if (connect(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0)
6512 debug_perror("Could not make TCP connection");
6513 else
6514 debug ("tcp_sock_connect %s:%u", inet_ntoa (sa.sin_addr), sa.sin_port );
6515 }
6516 return(fd);
6517}
6518
6519/*****************************************************************************/
6520int tcp_sock_open(struct in_addr ip, int port)
6521{
6522 int fd, turn_on_option_flag = 1, rcSockopt;
6523
6524 struct sockaddr_in sa;
6525
6526 /* Clear it out */
6527 memset((void *)&sa, 0, sizeof(sa));
6528
6529 fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
6530
6531 /* Error */
6532 if( fd < 0 ){
6533 debug_perror("Could not create socket");
6534 printf ("Hit [ENTER]");
6535 gets (&dp[0]);
6536 exit(1);
6537 }
6538
6539 sa.sin_family = AF_INET;
6540 memcpy((void *)&sa.sin_addr, (void *)&ip, sizeof(struct in_addr));
6541 sa.sin_port = htons((unsigned short) port);
6542
6543 /* Reuse port */
6544
6545 rcSockopt = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &turn_on_option_flag, sizeof(turn_on_option_flag));
6546
6547 /* bind() the socket to the interface */
6548 if (bind(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr)) < 0){
6549 debug_perror("Could not bind to port");
6550 printf ("Hit [ENTER]");
6551 gets (&dp[0]);
6552 exit(1);
6553 }
6554
6555 return(fd);
6556}
6557
6558/*****************************************************************************
6559* same as debug_perror but writes to debug output.
6560*
6561*****************************************************************************/
6562void debug_perror( char * msg ) {
6563 debug( "%s : %s\n" , msg , strerror(errno) );
6564}
6565/*****************************************************************************/
6566void debug(char *fmt, ...)
6567{
6568#define MAX_MESG_LEN 1024
6569
6570 va_list args;
6571 char text[ MAX_MESG_LEN ];
6572
6573 va_start (args, fmt);
6574 strcpy (text + vsprintf( text,fmt,args), "\r\n");
6575 va_end (args);
6576
6577 fprintf( stderr, "%s", text);
6578}
6579
6580/* Blue Burst encryption routines */
6581
6582static void pso_crypt_init_key_bb(unsigned char *data)
6583{
6584 unsigned x;
6585 for (x = 0; x < 48; x += 3)
6586 {
6587 data[x] ^= 0x19;
6588 data[x + 1] ^= 0x16;
6589 data[x + 2] ^= 0x18;
6590 }
6591}
6592
6593
6594void pso_crypt_decrypt_bb(PSO_CRYPT *pcry, unsigned char *data, unsigned
6595 length)
6596{
6597 unsigned eax, ecx, edx, ebx, ebp, esi, edi;
6598
6599 edx = 0;
6600 ecx = 0;
6601 eax = 0;
6602 while (edx < length)
6603 {
6604 ebx = *(unsigned long *) &data[edx];
6605 ebx = ebx ^ pcry->tbl[5];
6606 ebp = ((pcry->tbl[(ebx >> 0x18) + 0x12]+pcry->tbl[((ebx >> 0x10)& 0xff) + 0x112])
6607 ^ pcry->tbl[((ebx >> 0x8)& 0xff) + 0x212]) + pcry->tbl[(ebx & 0xff) + 0x312];
6608 ebp = ebp ^ pcry->tbl[4];
6609 ebp ^= *(unsigned long *) &data[edx+4];
6610 edi = ((pcry->tbl[(ebp >> 0x18) + 0x12]+pcry->tbl[((ebp >> 0x10)& 0xff) + 0x112])
6611 ^ pcry->tbl[((ebp >> 0x8)& 0xff) + 0x212]) + pcry->tbl[(ebp & 0xff) + 0x312];
6612 edi = edi ^ pcry->tbl[3];
6613 ebx = ebx ^ edi;
6614 esi = ((pcry->tbl[(ebx >> 0x18) + 0x12]+pcry->tbl[((ebx >> 0x10)& 0xff) + 0x112])
6615 ^ pcry->tbl[((ebx >> 0x8)& 0xff) + 0x212]) + pcry->tbl[(ebx & 0xff) + 0x312];
6616 ebp = ebp ^ esi ^ pcry->tbl[2];
6617 edi = ((pcry->tbl[(ebp >> 0x18) + 0x12]+pcry->tbl[((ebp >> 0x10)& 0xff) + 0x112])
6618 ^ pcry->tbl[((ebp >> 0x8)& 0xff) + 0x212]) + pcry->tbl[(ebp & 0xff) + 0x312];
6619 edi = edi ^ pcry->tbl[1];
6620 ebp = ebp ^ pcry->tbl[0];
6621 ebx = ebx ^ edi;
6622 *(unsigned long *) &data[edx] = ebp;
6623 *(unsigned long *) &data[edx+4] = ebx;
6624 edx = edx+8;
6625 }
6626}
6627
6628
6629void pso_crypt_encrypt_bb(PSO_CRYPT *pcry, unsigned char *data, unsigned
6630 length)
6631{
6632 unsigned eax, ecx, edx, ebx, ebp, esi, edi;
6633
6634 edx = 0;
6635 ecx = 0;
6636 eax = 0;
6637 while (edx < length)
6638 {
6639 ebx = *(unsigned long *) &data[edx];
6640 ebx = ebx ^ pcry->tbl[0];
6641 ebp = ((pcry->tbl[(ebx >> 0x18) + 0x12]+pcry->tbl[((ebx >> 0x10)& 0xff) + 0x112])
6642 ^ pcry->tbl[((ebx >> 0x8)& 0xff) + 0x212]) + pcry->tbl[(ebx & 0xff) + 0x312];
6643 ebp = ebp ^ pcry->tbl[1];
6644 ebp ^= *(unsigned long *) &data[edx+4];
6645 edi = ((pcry->tbl[(ebp >> 0x18) + 0x12]+pcry->tbl[((ebp >> 0x10)& 0xff) + 0x112])
6646 ^ pcry->tbl[((ebp >> 0x8)& 0xff) + 0x212]) + pcry->tbl[(ebp & 0xff) + 0x312];
6647 edi = edi ^ pcry->tbl[2];
6648 ebx = ebx ^ edi;
6649 esi = ((pcry->tbl[(ebx >> 0x18) + 0x12]+pcry->tbl[((ebx >> 0x10)& 0xff) + 0x112])
6650 ^ pcry->tbl[((ebx >> 0x8)& 0xff) + 0x212]) + pcry->tbl[(ebx & 0xff) + 0x312];
6651 ebp = ebp ^ esi ^ pcry->tbl[3];
6652 edi = ((pcry->tbl[(ebp >> 0x18) + 0x12]+pcry->tbl[((ebp >> 0x10)& 0xff) + 0x112])
6653 ^ pcry->tbl[((ebp >> 0x8)& 0xff) + 0x212]) + pcry->tbl[(ebp & 0xff) + 0x312];
6654 edi = edi ^ pcry->tbl[4];
6655 ebp = ebp ^ pcry->tbl[5];
6656 ebx = ebx ^ edi;
6657 *(unsigned long *) &data[edx] = ebp;
6658 *(unsigned long *) &data[edx+4] = ebx;
6659 edx = edx+8;
6660 }
6661}
6662
6663void encryptcopy (BANANA* client, const unsigned char* src, unsigned size)
6664{
6665 unsigned char* dest;
6666
6667 if (TCP_BUFFER_SIZE - client->snddata < ( (int) size + 7 ) )
6668 client->todc = 1;
6669 else
6670 {
6671 dest = &client->sndbuf[client->snddata];
6672 memcpy (dest,src,size);
6673 while (size % 8)
6674 dest[size++] = 0x00;
6675 client->snddata += (int) size;
6676 pso_crypt_encrypt_bb(cipher_ptr,dest,size);
6677 }
6678}
6679
6680
6681void decryptcopy (unsigned char* dest, const unsigned char* src, unsigned size)
6682{
6683 memcpy (dest,src,size);
6684 pso_crypt_decrypt_bb(cipher_ptr,dest,size);
6685}
6686
6687
6688void pso_crypt_table_init_bb(PSO_CRYPT *pcry, const unsigned char *salt)
6689{
6690 unsigned long eax, ecx, edx, ebx, ebp, esi, edi, ou, x;
6691 unsigned char s[48];
6692 unsigned short* pcryp;
6693 unsigned short* bbtbl;
6694 unsigned short dx;
6695
6696 pcry->cur = 0;
6697 pcry->mangle = NULL;
6698 pcry->size = 1024 + 18;
6699
6700 memcpy(s, salt, sizeof(s));
6701 pso_crypt_init_key_bb(s);
6702
6703 bbtbl = (unsigned short*) &bbtable[0];
6704 pcryp = (unsigned short*) &pcry->tbl[0];
6705
6706 eax = 0;
6707 ebx = 0;
6708
6709 for(ecx=0;ecx<0x12;ecx++)
6710 {
6711 dx = bbtbl[eax++];
6712 dx = ( ( dx & 0xFF ) << 8 ) + ( dx >> 8 );
6713 pcryp[ebx] = dx;
6714 dx = bbtbl[eax++];
6715 dx ^= pcryp[ebx++];
6716 pcryp[ebx++] = dx;
6717 }
6718
6719 /*
6720
6721 pcry->tbl[0] = 0x243F6A88;
6722 pcry->tbl[1] = 0x85A308D3;
6723 pcry->tbl[2] = 0x13198A2E;
6724 pcry->tbl[3] = 0x03707344;
6725 pcry->tbl[4] = 0xA4093822;
6726 pcry->tbl[5] = 0x299F31D0;
6727 pcry->tbl[6] = 0x082EFA98;
6728 pcry->tbl[7] = 0xEC4E6C89;
6729 pcry->tbl[8] = 0x452821E6;
6730 pcry->tbl[9] = 0x38D01377;
6731 pcry->tbl[10] = 0xBE5466CF;
6732 pcry->tbl[11] = 0x34E90C6C;
6733 pcry->tbl[12] = 0xC0AC29B7;
6734 pcry->tbl[13] = 0xC97C50DD;
6735 pcry->tbl[14] = 0x3F84D5B5;
6736 pcry->tbl[15] = 0xB5470917;
6737 pcry->tbl[16] = 0x9216D5D9;
6738 pcry->tbl[17] = 0x8979FB1B;
6739
6740 */
6741
6742 memcpy(&pcry->tbl[18], &bbtable[18], 4096);
6743
6744 ecx=0;
6745 //total key[0] length is min 0x412
6746 ebx=0;
6747
6748 while (ebx < 0x12)
6749 {
6750 //in a loop
6751 ebp=((unsigned long) (s[ecx])) << 0x18;
6752 eax=ecx+1;
6753 edx=eax-((eax / 48)*48);
6754 eax=(((unsigned long) (s[edx])) << 0x10) & 0xFF0000;
6755 ebp=(ebp | eax) & 0xffff00ff;
6756 eax=ecx+2;
6757 edx=eax-((eax / 48)*48);
6758 eax=(((unsigned long) (s[edx])) << 0x8) & 0xFF00;
6759 ebp=(ebp | eax) & 0xffffff00;
6760 eax=ecx+3;
6761 ecx=ecx+4;
6762 edx=eax-((eax / 48)*48);
6763 eax=(unsigned long) (s[edx]);
6764 ebp=ebp | eax;
6765 eax=ecx;
6766 edx=eax-((eax / 48)*48);
6767 pcry->tbl[ebx]=pcry->tbl[ebx] ^ ebp;
6768 ecx=edx;
6769 ebx++;
6770 }
6771
6772 ebp=0;
6773 esi=0;
6774 ecx=0;
6775 edi=0;
6776 ebx=0;
6777 edx=0x48;
6778
6779 while (edi < edx)
6780 {
6781 esi=esi ^ pcry->tbl[0];
6782 eax=esi >> 0x18;
6783 ebx=(esi >> 0x10) & 0xff;
6784 eax=pcry->tbl[eax+0x12]+pcry->tbl[ebx+0x112];
6785 ebx=(esi >> 8) & 0xFF;
6786 eax=eax ^ pcry->tbl[ebx+0x212];
6787 ebx=esi & 0xff;
6788 eax=eax + pcry->tbl[ebx+0x312];
6789
6790 eax=eax ^ pcry->tbl[1];
6791 ecx= ecx ^ eax;
6792 ebx=ecx >> 0x18;
6793 eax=(ecx >> 0x10) & 0xFF;
6794 ebx=pcry->tbl[ebx+0x12]+pcry->tbl[eax+0x112];
6795 eax=(ecx >> 8) & 0xff;
6796 ebx=ebx ^ pcry->tbl[eax+0x212];
6797 eax=ecx & 0xff;
6798 ebx=ebx + pcry->tbl[eax+0x312];
6799
6800 for (x = 0; x <= 5; x++)
6801 {
6802 ebx=ebx ^ pcry->tbl[(x*2)+2];
6803 esi= esi ^ ebx;
6804 ebx=esi >> 0x18;
6805 eax=(esi >> 0x10) & 0xFF;
6806 ebx=pcry->tbl[ebx+0x12]+pcry->tbl[eax+0x112];
6807 eax=(esi >> 8) & 0xff;
6808 ebx=ebx ^ pcry->tbl[eax+0x212];
6809 eax=esi & 0xff;
6810 ebx=ebx + pcry->tbl[eax+0x312];
6811
6812 ebx=ebx ^ pcry->tbl[(x*2)+3];
6813 ecx= ecx ^ ebx;
6814 ebx=ecx >> 0x18;
6815 eax=(ecx >> 0x10) & 0xFF;
6816 ebx=pcry->tbl[ebx+0x12]+pcry->tbl[eax+0x112];
6817 eax=(ecx >> 8) & 0xff;
6818 ebx=ebx ^ pcry->tbl[eax+0x212];
6819 eax=ecx & 0xff;
6820 ebx=ebx + pcry->tbl[eax+0x312];
6821 }
6822
6823 ebx=ebx ^ pcry->tbl[14];
6824 esi= esi ^ ebx;
6825 eax=esi >> 0x18;
6826 ebx=(esi >> 0x10) & 0xFF;
6827 eax=pcry->tbl[eax+0x12]+pcry->tbl[ebx+0x112];
6828 ebx=(esi >> 8) & 0xff;
6829 eax=eax ^ pcry->tbl[ebx+0x212];
6830 ebx=esi & 0xff;
6831 eax=eax + pcry->tbl[ebx+0x312];
6832
6833 eax=eax ^ pcry->tbl[15];
6834 eax= ecx ^ eax;
6835 ecx=eax >> 0x18;
6836 ebx=(eax >> 0x10) & 0xFF;
6837 ecx=pcry->tbl[ecx+0x12]+pcry->tbl[ebx+0x112];
6838 ebx=(eax >> 8) & 0xff;
6839 ecx=ecx ^ pcry->tbl[ebx+0x212];
6840 ebx=eax & 0xff;
6841 ecx=ecx + pcry->tbl[ebx+0x312];
6842
6843 ecx=ecx ^ pcry->tbl[16];
6844 ecx=ecx ^ esi;
6845 esi= pcry->tbl[17];
6846 esi=esi ^ eax;
6847 pcry->tbl[(edi / 4)]=esi;
6848 pcry->tbl[(edi / 4)+1]=ecx;
6849 edi=edi+8;
6850 }
6851
6852
6853 eax=0;
6854 edx=0;
6855 ou=0;
6856 while (ou < 0x1000)
6857 {
6858 edi=0x48;
6859 edx=0x448;
6860
6861 while (edi < edx)
6862 {
6863 esi=esi ^ pcry->tbl[0];
6864 eax=esi >> 0x18;
6865 ebx=(esi >> 0x10) & 0xff;
6866 eax=pcry->tbl[eax+0x12]+pcry->tbl[ebx+0x112];
6867 ebx=(esi >> 8) & 0xFF;
6868 eax=eax ^ pcry->tbl[ebx+0x212];
6869 ebx=esi & 0xff;
6870 eax=eax + pcry->tbl[ebx+0x312];
6871
6872 eax=eax ^ pcry->tbl[1];
6873 ecx= ecx ^ eax;
6874 ebx=ecx >> 0x18;
6875 eax=(ecx >> 0x10) & 0xFF;
6876 ebx=pcry->tbl[ebx+0x12]+pcry->tbl[eax+0x112];
6877 eax=(ecx >> 8) & 0xff;
6878 ebx=ebx ^ pcry->tbl[eax+0x212];
6879 eax=ecx & 0xff;
6880 ebx=ebx + pcry->tbl[eax+0x312];
6881
6882 for (x = 0; x <= 5; x++)
6883 {
6884 ebx=ebx ^ pcry->tbl[(x*2)+2];
6885 esi= esi ^ ebx;
6886 ebx=esi >> 0x18;
6887 eax=(esi >> 0x10) & 0xFF;
6888 ebx=pcry->tbl[ebx+0x12]+pcry->tbl[eax+0x112];
6889 eax=(esi >> 8) & 0xff;
6890 ebx=ebx ^ pcry->tbl[eax+0x212];
6891 eax=esi & 0xff;
6892 ebx=ebx + pcry->tbl[eax+0x312];
6893
6894 ebx=ebx ^ pcry->tbl[(x*2)+3];
6895 ecx= ecx ^ ebx;
6896 ebx=ecx >> 0x18;
6897 eax=(ecx >> 0x10) & 0xFF;
6898 ebx=pcry->tbl[ebx+0x12]+pcry->tbl[eax+0x112];
6899 eax=(ecx >> 8) & 0xff;
6900 ebx=ebx ^ pcry->tbl[eax+0x212];
6901 eax=ecx & 0xff;
6902 ebx=ebx + pcry->tbl[eax+0x312];
6903 }
6904
6905 ebx=ebx ^ pcry->tbl[14];
6906 esi= esi ^ ebx;
6907 eax=esi >> 0x18;
6908 ebx=(esi >> 0x10) & 0xFF;
6909 eax=pcry->tbl[eax+0x12]+pcry->tbl[ebx+0x112];
6910 ebx=(esi >> 8) & 0xff;
6911 eax=eax ^ pcry->tbl[ebx+0x212];
6912 ebx=esi & 0xff;
6913 eax=eax + pcry->tbl[ebx+0x312];
6914
6915 eax=eax ^ pcry->tbl[15];
6916 eax= ecx ^ eax;
6917 ecx=eax >> 0x18;
6918 ebx=(eax >> 0x10) & 0xFF;
6919 ecx=pcry->tbl[ecx+0x12]+pcry->tbl[ebx+0x112];
6920 ebx=(eax >> 8) & 0xff;
6921 ecx=ecx ^ pcry->tbl[ebx+0x212];
6922 ebx=eax & 0xff;
6923 ecx=ecx + pcry->tbl[ebx+0x312];
6924
6925 ecx=ecx ^ pcry->tbl[16];
6926 ecx=ecx ^ esi;
6927 esi= pcry->tbl[17];
6928 esi=esi ^ eax;
6929 pcry->tbl[(ou / 4)+(edi / 4)]=esi;
6930 pcry->tbl[(ou / 4)+(edi / 4)+1]=ecx;
6931 edi=edi+8;
6932 }
6933 ou=ou+0x400;
6934 }
6935}
6936
6937unsigned RleEncode(unsigned char *src, unsigned char *dest, unsigned src_size)
6938{
6939 unsigned char currChar, prevChar; /* current and previous characters */
6940 unsigned short count; /* number of characters in a run */
6941 unsigned src_end, dest_start;
6942
6943 dest_start = (unsigned)dest;
6944 src_end = (unsigned)src + src_size;
6945
6946 prevChar = 0xFF - *src;
6947
6948 while ((unsigned) src < src_end)
6949 {
6950 currChar = *(dest++) = *(src++);
6951
6952 if ( currChar == prevChar )
6953 {
6954 if ( (unsigned) src == src_end )
6955 {
6956 *(dest++) = 0;
6957 *(dest++) = 0;
6958 }
6959 else
6960 {
6961 count = 0;
6962 while (((unsigned)src < src_end) && (count < 0xFFF0))
6963 {
6964 if (*src == prevChar)
6965 {
6966 count++;
6967 src++;
6968 if ( (unsigned) src == src_end )
6969 {
6970 *(unsigned short*) dest = count;
6971 dest += 2;
6972 }
6973 }
6974 else
6975 {
6976 *(unsigned short*) dest = count;
6977 dest += 2;
6978 prevChar = 0xFF - *src;
6979 break;
6980 }
6981 }
6982 }
6983 }
6984 else
6985 prevChar = currChar;
6986 }
6987 return (unsigned)dest - dest_start;
6988}
6989
6990void RleDecode(unsigned char *src, unsigned char *dest, unsigned src_size)
6991{
6992 unsigned char currChar, prevChar; /* current and previous characters */
6993 unsigned short count; /* number of characters in a run */
6994 unsigned src_end;
6995
6996 src_end = (unsigned) src + src_size;
6997
6998 /* decode */
6999
7000 prevChar = 0xFF - *src; /* force next char to be different */
7001
7002 /* read input until there's nothing left */
7003
7004 while ((unsigned) src < src_end)
7005 {
7006 currChar = *(src++);
7007
7008 *(dest++) = currChar;
7009
7010 /* check for run */
7011 if (currChar == prevChar)
7012 {
7013 /* we have a run. write it out. */
7014 count = *(unsigned short*) src;
7015 src += 2;
7016 while (count > 0)
7017 {
7018 *(dest++) = currChar;
7019 count--;
7020 }
7021
7022 prevChar = 0xFF - *src; /* force next char to be different */
7023 }
7024 else
7025 {
7026 /* no run */
7027 prevChar = currChar;
7028 }
7029 }
7030}
7031
7032
7033/* expand a key (makes a rc4_key) */
7034
7035void prepare_key(unsigned char *keydata, unsigned len, struct rc4_key *key)
7036{
7037 unsigned index1, index2, counter;
7038 unsigned char *state;
7039
7040 state = key->state;
7041
7042 for (counter = 0; counter < 256; counter++)
7043 state[counter] = counter;
7044
7045 key->x = key->y = index1 = index2 = 0;
7046
7047 for (counter = 0; counter < 256; counter++) {
7048 index2 = (keydata[index1] + state[counter] + index2) & 255;
7049
7050 /* swap */
7051 state[counter] ^= state[index2];
7052 state[index2] ^= state[counter];
7053 state[counter] ^= state[index2];
7054
7055 index1 = (index1 + 1) % len;
7056 }
7057}
7058
7059/* reversible encryption, will encode a buffer updating the key */
7060
7061void rc4(unsigned char *buffer, unsigned len, struct rc4_key *key)
7062{
7063 unsigned x, y, xorIndex, counter;
7064 unsigned char *state;
7065
7066 /* get local copies */
7067 x = key->x; y = key->y;
7068 state = key->state;
7069
7070 for (counter = 0; counter < len; counter++) {
7071 x = (x + 1) & 255;
7072 y = (state[x] + y) & 255;
7073
7074 /* swap */
7075 state[x] ^= state[y];
7076 state[y] ^= state[x];
7077 state[x] ^= state[y];
7078
7079 xorIndex = (state[y] + state[x]) & 255;
7080
7081 buffer[counter] ^= state[xorIndex];
7082 }
7083
7084 key->x = x; key->y = y;
7085}
7086
7087void compressShipPacket ( ORANGE* ship, unsigned char* src, unsigned long src_size )
7088{
7089 unsigned char* dest;
7090 unsigned long result;
7091
7092 if (ship->shipSockfd >= 0)
7093 {
7094 if (PACKET_BUFFER_SIZE - ship->snddata < (int) ( src_size + 100 ) )
7095 initialize_ship(ship);
7096 else
7097 {
7098 if ( ship->crypt_on )
7099 {
7100 dest = &ship->sndbuf[ship->snddata];
7101 // Store the original packet size before RLE compression at offset 0x04 of the new packet.
7102 dest += 4;
7103 *(unsigned *) dest = src_size;
7104 // Compress packet using RLE, storing at offset 0x08 of new packet.
7105 //
7106 // result = size of RLE compressed data + a DWORD for the original packet size.
7107 result = RleEncode (src, dest+4, src_size) + 4;
7108 // Encrypt with RC4
7109 rc4 (dest, result, &ship->sc_key);
7110 // Increase result by the size of a DWORD for the final ship packet size.
7111 result += 4;
7112 // Copy it to the front of the packet.
7113 *(unsigned *) &ship->sndbuf[ship->snddata] = result;
7114 ship->snddata += (int) result;
7115 }
7116 else
7117 {
7118 memcpy ( &ship->sndbuf[ship->snddata+4], src, src_size );
7119 src_size += 4;
7120 *(unsigned *) &ship->sndbuf[ship->snddata] = src_size;
7121 ship->snddata += src_size;
7122 }
7123 }
7124 }
7125}
7126
7127void decompressShipPacket ( ORANGE* ship, unsigned char* dest, unsigned char* src )
7128{
7129 unsigned src_size, dest_size;
7130 unsigned char *srccpy;
7131
7132 if (ship->crypt_on)
7133 {
7134 src_size = *(unsigned *) src;
7135 src_size -= 8;
7136 src += 4;
7137 srccpy = src;
7138 // Decrypt RC4
7139 rc4 (src, src_size+4, &ship->cs_key);
7140 // The first four bytes of the src should now contain the expected uncompressed data size.
7141 dest_size = *(unsigned *) srccpy;
7142 // Increase expected size by 4 before inserting into the destination buffer. (To take account for the packet
7143 // size DWORD...)
7144 dest_size += 4;
7145 *(unsigned *) dest = dest_size;
7146 // Decompress the data...
7147 RleDecode (srccpy+4, dest+4, src_size);
7148 }
7149 else
7150 {
7151 src_size = *(unsigned *) src;
7152 memcpy (dest + 4, src + 4, src_size);
7153 src_size += 4;
7154 *(unsigned *) dest = src_size;
7155 }
7156}