viewing paste ra_charlogin_explode | Diff

Posted on the
  1. Index: src/common/mmo.h
  2. ===================================================================
  3. --- src/common/mmo.h	(revision 17373)
  4. +++ src/common/mmo.h	(working copy)
  5. @@ -8,52 +8,15 @@
  6.  #include "../common/db.h"
  7.  #include <time.h>
  8.  
  9. -// server->client protocol version
  10. -//        0 - pre-?
  11. -//        1 - ?                    - 0x196
  12. -//        2 - ?                    - 0x78, 0x79
  13. -//        3 - ?                    - 0x1c8, 0x1c9, 0x1de
  14. -//        4 - ?                    - 0x1d7, 0x1d8, 0x1d9, 0x1da
  15. -//        5 - 2003-12-18aSakexe+   - 0x1ee, 0x1ef, 0x1f0, ?0x1c4, 0x1c5?
  16. -//        6 - 2004-03-02aSakexe+   - 0x1f4, 0x1f5
  17. -//        7 - 2005-04-11aSakexe+   - 0x229, 0x22a, 0x22b, 0x22c
  18. -// 20061023 - 2006-10-23aSakexe+   - 0x6b, 0x6d
  19. -// 20070521 - 2007-05-21aSakexe+   - 0x283
  20. -// 20070821 - 2007-08-21aSakexe+   - 0x2c5
  21. -// 20070918 - 2007-09-18aSakexe+   - 0x2d7, 0x2d9, 0x2da
  22. -// 20071106 - 2007-11-06aSakexe+   - 0x78, 0x7c, 0x22c
  23. -// 20080102 - 2008-01-02aSakexe+   - 0x2ec, 0x2ed , 0x2ee
  24. -// 20081126 - 2008-11-26aSakexe+   - 0x1a2
  25. -// 20090408 - 2009-04-08aSakexe+   - 0x44a (dont use as it overlaps with RE client packets)
  26. -// 20080827 - 2008-08-27aRagexeRE+ - First RE Client
  27. -// 20081217 - 2008-12-17aRagexeRE+ - 0x6d (Note: This one still use old Char Info Packet Structure)
  28. -// 20081218 - 2008-12-17bRagexeRE+ - 0x6d (Note: From this one client use new Char Info Packet Structure)
  29. -// 20090603 - 2009-06-03aRagexeRE+ - 0x7d7, 0x7d8, 0x7d9, 0x7da
  30. -// 20090617 - 2009-06-17aRagexeRE+ - 0x7d9
  31. -// 20090922 - 2009-09-22aRagexeRE+ - 0x7e5, 0x7e7, 0x7e8, 0x7e9
  32. -// 20091103 - 2009-11-03aRagexeRE+ - 0x7f7, 0x7f8, 0x7f9
  33. -// 20100105 - 2010-01-05aRagexeRE+ - 0x133, 0x800, 0x801
  34. -// 20100126 - 2010-01-26aRagexeRE+ - 0x80e
  35. -// 20100223 - 2010-02-23aRagexeRE+ - 0x80f
  36. -// 20100413 - 2010-04-13aRagexeRE+ - 0x6b
  37. -// 20100629 - 2010-06-29aRagexeRE+ - 0x2d0, 0xaa, 0x2d1, 0x2d2
  38. -// 20100721 - 2010-07-21aRagexeRE+ - 0x6b, 0x6d
  39. -// 20100727 - 2010-07-27aRagexeRE+ - 0x6b, 0x6d
  40. -// 20100803 - 2010-08-03aRagexeRE+ - 0x6b, 0x6d, 0x827, 0x828, 0x829, 0x82a, 0x82b, 0x82c, 0x842, 0x843
  41. -// 20101124 - 2010-11-24aRagexeRE+ - 0x856, 0x857, 0x858
  42. -// 20110111 - 2011-01-11aRagexeRE+ - 0x6b, 0x6d
  43. -// 20110928 - 2011-09-28aRagexeRE+ - 0x6b, 0x6d
  44. -// 20111025 - 2011-10-25aRagexeRE+ - 0x6b, 0x6d
  45. -// 20120307 - 2012-03-07aRagexeRE+ - 0x970
  46. -
  47.  #ifndef PACKETVER
  48. -	#define PACKETVER 20120410
  49. -	//#define PACKETVER 20130320
  50. +	//#define PACKETVER 20120410
  51. +	#define PACKETVER 20130320
  52.  	//#define PACKETVER 20111116
  53.  #endif
  54.  
  55.  //Remove/Comment this line to disable sc_data saving. [Skotlex]
  56.  #define ENABLE_SC_SAVING
  57. +
  58.  //Remove/Comment this line to disable server-side hot-key saving support [Skotlex]
  59.  //Note that newer clients no longer save hotkeys in the registry!
  60.  #define HOTKEY_SAVING
  61. Index: src/common/cli.c
  62. ===================================================================
  63. --- src/common/cli.c	(revision 17373)
  64. +++ src/common/cli.c	(working copy)
  65. @@ -53,12 +53,12 @@
  66.   */
  67.  void display_versionscreen(bool do_exit)
  68.  {
  69. -    ShowInfo(CL_WHITE"rAthena SVN version: %s" CL_RESET"\n", get_svn_revision());
  70. -    ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://rathena.org/\n");
  71. -    ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rizon.net/#rathena\n");
  72. -    ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n");
  73. -    if (do_exit)
  74. -	exit(EXIT_SUCCESS);
  75. +	ShowInfo(CL_WHITE"rAthena SVN version: %s" CL_RESET"\n", get_svn_revision());
  76. +	ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://rathena.org/\n");
  77. +	ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rizon.net/#rathena\n");
  78. +	ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n");
  79. +	if (do_exit)
  80. +		exit(EXIT_SUCCESS);
  81.  }
  82.  
  83.  /*
  84. Index: src/common/cli.h
  85. ===================================================================
  86. --- src/common/cli.h	(revision 17373)
  87. +++ src/common/cli.h	(working copy)
  88. @@ -32,6 +32,8 @@
  89.   extern char* MSG_CONF_NAME_EN; //all
  90.  
  91.  extern void display_helpscreen(bool exit);
  92. +void display_versionscreen(bool do_exit);
  93. +bool opt_has_next_value(const char* option, int i, int argc);
  94.  int cli_get_options(int argc, char ** argv);
  95.  int parse_console_timer(int tid, unsigned int tick, int id, intptr_t data);
  96.  extern int parse_console(const char* buf); //particular for each serv
  97. Index: src/common/timer.c
  98. ===================================================================
  99. --- src/common/timer.c	(revision 17373)
  100. +++ src/common/timer.c	(working copy)
  101. @@ -109,28 +109,28 @@
  102.  	} t;
  103.  
  104.  	asm volatile("rdtsc":"=a"(t.dw[0]), "=d"(t.dw[1]) );
  105. -	
  106. +
  107.  	return t.qw;
  108.  }
  109.  
  110.  static void rdtsc_calibrate(){
  111.  	uint64 t1, t2;
  112.  	int32 i;
  113. -	
  114. +
  115.  	ShowStatus("Calibrating Timer Source, please wait... ");
  116. -	
  117. +
  118.  	RDTSC_CLOCK = 0;
  119. -	
  120. +
  121.  	for(i = 0; i < 5; i++){
  122.  		t1 = _rdtsc();
  123.  		usleep(1000000); //1000 MS
  124.  		t2 = _rdtsc();
  125. -		RDTSC_CLOCK += (t2 - t1) / 1000; 
  126. +		RDTSC_CLOCK += (t2 - t1) / 1000;
  127.  	}
  128.  	RDTSC_CLOCK /= 5;
  129. -	
  130. +
  131.  	RDTSC_BEGINTICK = _rdtsc();
  132. -	
  133. +
  134.  	ShowMessage(" done. (Frequency: %u Mhz)\n", (uint32)(RDTSC_CLOCK/1000) );
  135.  }
  136.  
  137. @@ -243,7 +243,7 @@
  138.  int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data)
  139.  {
  140.  	int tid;
  141. -	
  142. +
  143.  	tid = acquire_timer();
  144.  	timer_data[tid].tick     = tick;
  145.  	timer_data[tid].func     = func;
  146. @@ -267,7 +267,7 @@
  147.  		ShowError("add_timer_interval: invalid interval (tick=%u %p[%s] id=%d data=%d diff_tick=%d)\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, gettick()));
  148.  		return INVALID_TIMER;
  149.  	}
  150. -	
  151. +
  152.  	tid = acquire_timer();
  153.  	timer_data[tid].tick     = tick;
  154.  	timer_data[tid].func     = func;
  155. @@ -320,7 +320,7 @@
  156.  int settick_timer(int tid, unsigned int tick)
  157.  {
  158.  	size_t i;
  159. -	
  160. +
  161.  	// search timer position
  162.  	ARR_FIND(0, BHEAP_LENGTH(timer_heap), i, BHEAP_DATA(timer_heap)[i] == tid);
  163.  	if( i == BHEAP_LENGTH(timer_heap) )
  164. @@ -406,6 +406,16 @@
  165.  	return (unsigned long)difftime(time(NULL), start_time);
  166.  }
  167.  
  168. +//-----------------------------------------------------
  169. +// custom timestamp formatting (from eApp)
  170. +//-----------------------------------------------------
  171. +const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format)
  172. +{
  173. +	size_t len = strftime(str, size, format, localtime(&timestamp));
  174. +	memset(str + len, '\0', size - len);
  175. +	return str;
  176. +}
  177. +
  178.  void timer_init(void)
  179.  {
  180.  #if defined(ENABLE_RDTSC)
  181. Index: src/common/timer.h
  182. ===================================================================
  183. --- src/common/timer.h	(revision 17373)
  184. +++ src/common/timer.h	(working copy)
  185. @@ -5,6 +5,7 @@
  186.  #define	_TIMER_H_
  187.  
  188.  #include "../common/cbasetypes.h"
  189. +#include <time.h>
  190.  
  191.  #define DIFF_TICK(a,b) ((int)((a)-(b)))
  192.  
  193. @@ -51,6 +52,9 @@
  194.  
  195.  unsigned long get_uptime(void);
  196.  
  197. +//transform a timestamp to string
  198. +const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format);
  199. +
  200.  int do_timer(unsigned int tick);
  201.  void timer_init(void);
  202.  void timer_final(void);
  203. Index: src/config/const.h
  204. ===================================================================
  205. --- src/config/const.h	(revision 17373)
  206. +++ src/config/const.h	(working copy)
  207. @@ -87,6 +87,9 @@
  208.  /* Feb 1st 2012 */
  209.  #if PACKETVER >= 20120201
  210.  	#define NEW_CARTS
  211. +	#ifndef ENABLE_SC_SAVING
  212. +	 #warning "Cart won't be able to be saved for relog"
  213. +	#endif
  214.  	#define MAX_CARTS 9
  215.  #else
  216.  	#define MAX_CARTS 5
  217. Index: src/login/account_sql.c
  218. ===================================================================
  219. --- src/login/account_sql.c	(revision 17373)
  220. +++ src/login/account_sql.c	(working copy)
  221. @@ -1,689 +0,0 @@
  222. -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  223. -// For more information, see LICENCE in the main folder
  224. -
  225. -#include "../common/malloc.h"
  226. -#include "../common/mmo.h"
  227. -#include "../common/showmsg.h"
  228. -#include "../common/sql.h"
  229. -#include "../common/strlib.h"
  230. -#include "../common/timer.h"
  231. -#include "account.h"
  232. -#include <stdlib.h>
  233. -#include <string.h>
  234. -
  235. -/// global defines
  236. -#define ACCOUNT_SQL_DB_VERSION 20110114
  237. -
  238. -/// internal structure
  239. -typedef struct AccountDB_SQL
  240. -{
  241. -	AccountDB vtable;    // public interface
  242. -
  243. -	Sql* accounts;       // SQL accounts storage
  244. -
  245. -	// global sql settings
  246. -	char   global_db_hostname[32];
  247. -	uint16 global_db_port;
  248. -	char   global_db_username[32];
  249. -	char   global_db_password[32];
  250. -	char   global_db_database[32];
  251. -	char   global_codepage[32];
  252. -	// local sql settings
  253. -	char   db_hostname[32];
  254. -	uint16 db_port;
  255. -	char   db_username[32];
  256. -	char   db_password[32];
  257. -	char   db_database[32];
  258. -	char   codepage[32];
  259. -	// other settings
  260. -	bool case_sensitive;
  261. -	char account_db[32];
  262. -	char accreg_db[32];
  263. -
  264. -} AccountDB_SQL;
  265. -
  266. -/// internal structure
  267. -typedef struct AccountDBIterator_SQL
  268. -{
  269. -	AccountDBIterator vtable;    // public interface
  270. -
  271. -	AccountDB_SQL* db;
  272. -	int last_account_id;
  273. -} AccountDBIterator_SQL;
  274. -
  275. -/// internal functions
  276. -static bool account_db_sql_init(AccountDB* self);
  277. -static void account_db_sql_destroy(AccountDB* self);
  278. -static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen);
  279. -static bool account_db_sql_set_property(AccountDB* self, const char* option, const char* value);
  280. -static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc);
  281. -static bool account_db_sql_remove(AccountDB* self, const int account_id);
  282. -static bool account_db_sql_save(AccountDB* self, const struct mmo_account* acc);
  283. -static bool account_db_sql_load_num(AccountDB* self, struct mmo_account* acc, const int account_id);
  284. -static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, const char* userid);
  285. -static AccountDBIterator* account_db_sql_iterator(AccountDB* self);
  286. -static void account_db_sql_iter_destroy(AccountDBIterator* self);
  287. -static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account* acc);
  288. -
  289. -static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int account_id);
  290. -static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new);
  291. -
  292. -/// public constructor
  293. -AccountDB* account_db_sql(void)
  294. -{
  295. -	AccountDB_SQL* db = (AccountDB_SQL*)aCalloc(1, sizeof(AccountDB_SQL));
  296. -
  297. -	// set up the vtable
  298. -	db->vtable.init         = &account_db_sql_init;
  299. -	db->vtable.destroy      = &account_db_sql_destroy;
  300. -	db->vtable.get_property = &account_db_sql_get_property;
  301. -	db->vtable.set_property = &account_db_sql_set_property;
  302. -	db->vtable.save         = &account_db_sql_save;
  303. -	db->vtable.create       = &account_db_sql_create;
  304. -	db->vtable.remove       = &account_db_sql_remove;
  305. -	db->vtable.load_num     = &account_db_sql_load_num;
  306. -	db->vtable.load_str     = &account_db_sql_load_str;
  307. -	db->vtable.iterator     = &account_db_sql_iterator;
  308. -
  309. -	// initialize to default values
  310. -	db->accounts = NULL;
  311. -	// global sql settings
  312. -	safestrncpy(db->global_db_hostname, "127.0.0.1", sizeof(db->global_db_hostname));
  313. -	db->global_db_port = 3306;
  314. -	safestrncpy(db->global_db_username, "ragnarok", sizeof(db->global_db_username));
  315. -	safestrncpy(db->global_db_password, "ragnarok", sizeof(db->global_db_password));
  316. -	safestrncpy(db->global_db_database, "ragnarok", sizeof(db->global_db_database));
  317. -	safestrncpy(db->global_codepage, "", sizeof(db->global_codepage));
  318. -	// local sql settings
  319. -	safestrncpy(db->db_hostname, "", sizeof(db->db_hostname));
  320. -	db->db_port = 3306;
  321. -	safestrncpy(db->db_username, "", sizeof(db->db_username));
  322. -	safestrncpy(db->db_password, "", sizeof(db->db_password));
  323. -	safestrncpy(db->db_database, "", sizeof(db->db_database));
  324. -	safestrncpy(db->codepage, "", sizeof(db->codepage));
  325. -	// other settings
  326. -	db->case_sensitive = false;
  327. -	safestrncpy(db->account_db, "login", sizeof(db->account_db));
  328. -	safestrncpy(db->accreg_db, "global_reg_value", sizeof(db->accreg_db));
  329. -
  330. -	return &db->vtable;
  331. -}
  332. -
  333. -
  334. -/* ------------------------------------------------------------------------- */
  335. -
  336. -
  337. -/// establishes database connection
  338. -static bool account_db_sql_init(AccountDB* self)
  339. -{
  340. -	AccountDB_SQL* db = (AccountDB_SQL*)self;
  341. -	Sql* sql_handle;
  342. -	const char* username;
  343. -	const char* password;
  344. -	const char* hostname;
  345. -	uint16      port;
  346. -	const char* database;
  347. -	const char* codepage;
  348. -
  349. -	db->accounts = Sql_Malloc();
  350. -	sql_handle = db->accounts;
  351. -
  352. -	if( db->db_hostname[0] != '\0' )
  353. -	{// local settings
  354. -		username = db->db_username;
  355. -		password = db->db_password;
  356. -		hostname = db->db_hostname;
  357. -		port     = db->db_port;
  358. -		database = db->db_database;
  359. -		codepage = db->codepage;
  360. -	}
  361. -	else
  362. -	{// global settings
  363. -		username = db->global_db_username;
  364. -		password = db->global_db_password;
  365. -		hostname = db->global_db_hostname;
  366. -		port     = db->global_db_port;
  367. -		database = db->global_db_database;
  368. -		codepage = db->global_codepage;
  369. -	}
  370. -
  371. -	if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) )
  372. -	{
  373. -		Sql_ShowDebug(sql_handle);
  374. -		Sql_Free(db->accounts);
  375. -		db->accounts = NULL;
  376. -		return false;
  377. -	}
  378. -
  379. -	if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) )
  380. -		Sql_ShowDebug(sql_handle);
  381. -
  382. -	return true;
  383. -}
  384. -
  385. -/// disconnects from database
  386. -static void account_db_sql_destroy(AccountDB* self)
  387. -{
  388. -	AccountDB_SQL* db = (AccountDB_SQL*)self;
  389. -
  390. -	Sql_Free(db->accounts);
  391. -	db->accounts = NULL;
  392. -	aFree(db);
  393. -}
  394. -
  395. -/// Gets a property from this database.
  396. -static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen)
  397. -{
  398. -	AccountDB_SQL* db = (AccountDB_SQL*)self;
  399. -	const char* signature;
  400. -
  401. -	signature = "engine.";
  402. -	if( strncmpi(key, signature, strlen(signature)) == 0 )
  403. -	{
  404. -		key += strlen(signature);
  405. -		if( strcmpi(key, "name") == 0 )
  406. -			safesnprintf(buf, buflen, "sql");
  407. -		else
  408. -		if( strcmpi(key, "version") == 0 )
  409. -			safesnprintf(buf, buflen, "%d", ACCOUNT_SQL_DB_VERSION);
  410. -		else
  411. -		if( strcmpi(key, "comment") == 0 )
  412. -			safesnprintf(buf, buflen, "SQL Account Database");
  413. -		else
  414. -			return false;// not found
  415. -		return true;
  416. -	}
  417. -
  418. -	signature = "sql.";
  419. -	if( strncmpi(key, signature, strlen(signature)) == 0 )
  420. -	{
  421. -		key += strlen(signature);
  422. -		if( strcmpi(key, "db_hostname") == 0 )
  423. -			safesnprintf(buf, buflen, "%s", db->global_db_hostname);
  424. -		else
  425. -		if( strcmpi(key, "db_port") == 0 )
  426. -			safesnprintf(buf, buflen, "%d", db->global_db_port);
  427. -		else
  428. -		if( strcmpi(key, "db_username") == 0 )
  429. -			safesnprintf(buf, buflen, "%s", db->global_db_username);
  430. -		else
  431. -		if(	strcmpi(key, "db_password") == 0 )
  432. -			safesnprintf(buf, buflen, "%s", db->global_db_password);
  433. -		else
  434. -		if( strcmpi(key, "db_database") == 0 )
  435. -			safesnprintf(buf, buflen, "%s", db->global_db_database);
  436. -		else
  437. -		if( strcmpi(key, "codepage") == 0 )
  438. -			safesnprintf(buf, buflen, "%s", db->global_codepage);
  439. -		else
  440. -			return false;// not found
  441. -		return true;
  442. -	}
  443. -
  444. -	signature = "account.sql.";
  445. -	if( strncmpi(key, signature, strlen(signature)) == 0 )
  446. -	{
  447. -		key += strlen(signature);
  448. -		if( strcmpi(key, "db_hostname") == 0 )
  449. -			safesnprintf(buf, buflen, "%s", db->db_hostname);
  450. -		else
  451. -		if( strcmpi(key, "db_port") == 0 )
  452. -			safesnprintf(buf, buflen, "%d", db->db_port);
  453. -		else
  454. -		if( strcmpi(key, "db_username") == 0 )
  455. -			safesnprintf(buf, buflen, "%s", db->db_username);
  456. -		else
  457. -		if(	strcmpi(key, "db_password") == 0 )
  458. -			safesnprintf(buf, buflen, "%s", db->db_password);
  459. -		else
  460. -		if( strcmpi(key, "db_database") == 0 )
  461. -			safesnprintf(buf, buflen, "%s", db->db_database);
  462. -		else
  463. -		if( strcmpi(key, "codepage") == 0 )
  464. -			safesnprintf(buf, buflen, "%s", db->codepage);
  465. -		else
  466. -		if( strcmpi(key, "case_sensitive") == 0 )
  467. -			safesnprintf(buf, buflen, "%d", (db->case_sensitive ? 1 : 0));
  468. -		else
  469. -		if( strcmpi(key, "account_db") == 0 )
  470. -			safesnprintf(buf, buflen, "%s", db->account_db);
  471. -		else
  472. -		if( strcmpi(key, "accreg_db") == 0 )
  473. -			safesnprintf(buf, buflen, "%s", db->accreg_db);
  474. -		else
  475. -			return false;// not found
  476. -		return true;
  477. -	}
  478. -
  479. -	return false;// not found
  480. -}
  481. -
  482. -/// if the option is supported, adjusts the internal state
  483. -static bool account_db_sql_set_property(AccountDB* self, const char* key, const char* value)
  484. -{
  485. -	AccountDB_SQL* db = (AccountDB_SQL*)self;
  486. -	const char* signature;
  487. -
  488. -
  489. -	signature = "sql.";
  490. -	if( strncmp(key, signature, strlen(signature)) == 0 )
  491. -	{
  492. -		key += strlen(signature);
  493. -		if( strcmpi(key, "db_hostname") == 0 )
  494. -			safestrncpy(db->global_db_hostname, value, sizeof(db->global_db_hostname));
  495. -		else
  496. -		if( strcmpi(key, "db_port") == 0 )
  497. -			db->global_db_port = (uint16)strtoul(value, NULL, 10);
  498. -		else
  499. -		if( strcmpi(key, "db_username") == 0 )
  500. -			safestrncpy(db->global_db_username, value, sizeof(db->global_db_username));
  501. -		else
  502. -		if( strcmpi(key, "db_password") == 0 )
  503. -			safestrncpy(db->global_db_password, value, sizeof(db->global_db_password));
  504. -		else
  505. -		if( strcmpi(key, "db_database") == 0 )
  506. -			safestrncpy(db->global_db_database, value, sizeof(db->global_db_database));
  507. -		else
  508. -		if( strcmpi(key, "codepage") == 0 )
  509. -			safestrncpy(db->global_codepage, value, sizeof(db->global_codepage));
  510. -		else
  511. -			return false;// not found
  512. -		return true;
  513. -	}
  514. -
  515. -	signature = "account.sql.";
  516. -	if( strncmp(key, signature, strlen(signature)) == 0 )
  517. -	{
  518. -		key += strlen(signature);
  519. -		if( strcmpi(key, "db_hostname") == 0 )
  520. -			safestrncpy(db->db_hostname, value, sizeof(db->db_hostname));
  521. -		else
  522. -		if( strcmpi(key, "db_port") == 0 )
  523. -			db->db_port = (uint16)strtoul(value, NULL, 10);
  524. -		else
  525. -		if( strcmpi(key, "db_username") == 0 )
  526. -			safestrncpy(db->db_username, value, sizeof(db->db_username));
  527. -		else
  528. -		if( strcmpi(key, "db_password") == 0 )
  529. -			safestrncpy(db->db_password, value, sizeof(db->db_password));
  530. -		else
  531. -		if( strcmpi(key, "db_database") == 0 )
  532. -			safestrncpy(db->db_database, value, sizeof(db->db_database));
  533. -		else
  534. -		if( strcmpi(key, "codepage") == 0 )
  535. -			safestrncpy(db->codepage, value, sizeof(db->codepage));
  536. -		else
  537. -		if( strcmpi(key, "case_sensitive") == 0 )
  538. -			db->case_sensitive = config_switch(value);
  539. -		else
  540. -		if( strcmpi(key, "account_db") == 0 )
  541. -			safestrncpy(db->account_db, value, sizeof(db->account_db));
  542. -		else
  543. -		if( strcmpi(key, "accreg_db") == 0 )
  544. -			safestrncpy(db->accreg_db, value, sizeof(db->accreg_db));
  545. -		else
  546. -			return false;// not found
  547. -		return true;
  548. -	}
  549. -
  550. -	return false;// not found
  551. -}
  552. -
  553. -/// create a new account entry
  554. -/// If acc->account_id is -1, the account id will be auto-generated,
  555. -/// and its value will be written to acc->account_id if everything succeeds.
  556. -static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc)
  557. -{
  558. -	AccountDB_SQL* db = (AccountDB_SQL*)self;
  559. -	Sql* sql_handle = db->accounts;
  560. -
  561. -	// decide on the account id to assign
  562. -	int account_id;
  563. -	if( acc->account_id != -1 )
  564. -	{// caller specifies it manually
  565. -		account_id = acc->account_id;
  566. -	}
  567. -	else
  568. -	{// ask the database
  569. -		char* data;
  570. -		size_t len;
  571. -
  572. -		if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT MAX(`account_id`)+1 FROM `%s`", db->account_db) )
  573. -		{
  574. -			Sql_ShowDebug(sql_handle);
  575. -			return false;
  576. -		}
  577. -		if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  578. -		{
  579. -			Sql_ShowDebug(sql_handle);
  580. -			Sql_FreeResult(sql_handle);
  581. -			return false;
  582. -		}
  583. -
  584. -		Sql_GetData(sql_handle, 0, &data, &len);
  585. -		account_id = ( data != NULL ) ? atoi(data) : 0;
  586. -		Sql_FreeResult(sql_handle);
  587. -
  588. -		if( account_id < START_ACCOUNT_NUM )
  589. -			account_id = START_ACCOUNT_NUM;
  590. -
  591. -	}
  592. -
  593. -	// zero value is prohibited
  594. -	if( account_id == 0 )
  595. -		return false;
  596. -
  597. -	// absolute maximum
  598. -	if( account_id > END_ACCOUNT_NUM )
  599. -		return false;
  600. -
  601. -	// insert the data into the database
  602. -	acc->account_id = account_id;
  603. -	return mmo_auth_tosql(db, acc, true);
  604. -}
  605. -
  606. -/// delete an existing account entry + its regs
  607. -static bool account_db_sql_remove(AccountDB* self, const int account_id)
  608. -{
  609. -	AccountDB_SQL* db = (AccountDB_SQL*)self;
  610. -	Sql* sql_handle = db->accounts;
  611. -	bool result = false;
  612. -
  613. -	if( SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION")
  614. -	||  SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->account_db, account_id)
  615. -	||  SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->accreg_db, account_id) )
  616. -		Sql_ShowDebug(sql_handle);
  617. -	else
  618. -		result = true;
  619. -
  620. -	result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") );
  621. -
  622. -	return result;
  623. -}
  624. -
  625. -/// update an existing account with the provided new data (both account and regs)
  626. -static bool account_db_sql_save(AccountDB* self, const struct mmo_account* acc)
  627. -{
  628. -	AccountDB_SQL* db = (AccountDB_SQL*)self;
  629. -	return mmo_auth_tosql(db, acc, false);
  630. -}
  631. -
  632. -/// retrieve data from db and store it in the provided data structure
  633. -static bool account_db_sql_load_num(AccountDB* self, struct mmo_account* acc, const int account_id)
  634. -{
  635. -	AccountDB_SQL* db = (AccountDB_SQL*)self;
  636. -	return mmo_auth_fromsql(db, acc, account_id);
  637. -}
  638. -
  639. -/// retrieve data from db and store it in the provided data structure
  640. -static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, const char* userid)
  641. -{
  642. -	AccountDB_SQL* db = (AccountDB_SQL*)self;
  643. -	Sql* sql_handle = db->accounts;
  644. -	char esc_userid[2*NAME_LENGTH+1];
  645. -	int account_id;
  646. -	char* data;
  647. -
  648. -	Sql_EscapeString(sql_handle, esc_userid, userid);
  649. -
  650. -	// get the list of account IDs for this user ID
  651. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `userid`= %s '%s'",
  652. -		db->account_db, (db->case_sensitive ? "BINARY" : ""), esc_userid) )
  653. -	{
  654. -		Sql_ShowDebug(sql_handle);
  655. -		return false;
  656. -	}
  657. -
  658. -	if( Sql_NumRows(sql_handle) > 1 )
  659. -	{// serious problem - duplicit account
  660. -		ShowError("account_db_sql_load_str: multiple accounts found when retrieving data for account '%s'!\n", userid);
  661. -		Sql_FreeResult(sql_handle);
  662. -		return false;
  663. -	}
  664. -
  665. -	if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  666. -	{// no such entry
  667. -		Sql_FreeResult(sql_handle);
  668. -		return false;
  669. -	}
  670. -
  671. -	Sql_GetData(sql_handle, 0, &data, NULL);
  672. -	account_id = atoi(data);
  673. -
  674. -	return account_db_sql_load_num(self, acc, account_id);
  675. -}
  676. -
  677. -
  678. -/// Returns a new forward iterator.
  679. -static AccountDBIterator* account_db_sql_iterator(AccountDB* self)
  680. -{
  681. -	AccountDB_SQL* db = (AccountDB_SQL*)self;
  682. -	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)aCalloc(1, sizeof(AccountDBIterator_SQL));
  683. -
  684. -	// set up the vtable
  685. -	iter->vtable.destroy = &account_db_sql_iter_destroy;
  686. -	iter->vtable.next    = &account_db_sql_iter_next;
  687. -
  688. -	// fill data
  689. -	iter->db = db;
  690. -	iter->last_account_id = -1;
  691. -
  692. -	return &iter->vtable;
  693. -}
  694. -
  695. -
  696. -/// Destroys this iterator, releasing all allocated memory (including itself).
  697. -static void account_db_sql_iter_destroy(AccountDBIterator* self)
  698. -{
  699. -	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
  700. -	aFree(iter);
  701. -}
  702. -
  703. -
  704. -/// Fetches the next account in the database.
  705. -static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account* acc)
  706. -{
  707. -	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
  708. -	AccountDB_SQL* db = (AccountDB_SQL*)iter->db;
  709. -	Sql* sql_handle = db->accounts;
  710. -	char* data;
  711. -
  712. -	// get next account ID
  713. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `account_id` > '%d' ORDER BY `account_id` ASC LIMIT 1",
  714. -		db->account_db, iter->last_account_id) )
  715. -	{
  716. -		Sql_ShowDebug(sql_handle);
  717. -		return false;
  718. -	}
  719. -
  720. -	if( SQL_SUCCESS == Sql_NextRow(sql_handle) &&
  721. -		SQL_SUCCESS == Sql_GetData(sql_handle, 0, &data, NULL) &&
  722. -		data != NULL )
  723. -	{// get account data
  724. -		int account_id;
  725. -		account_id = atoi(data);
  726. -		if( mmo_auth_fromsql(db, acc, account_id) )
  727. -		{
  728. -			iter->last_account_id = account_id;
  729. -			Sql_FreeResult(sql_handle);
  730. -			return true;
  731. -		}
  732. -	}
  733. -	Sql_FreeResult(sql_handle);
  734. -	return false;
  735. -}
  736. -
  737. -
  738. -static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int account_id)
  739. -{
  740. -	Sql* sql_handle = db->accounts;
  741. -	char* data;
  742. -	int i = 0;
  743. -
  744. -	// retrieve login entry for the specified account
  745. -	if( SQL_ERROR == Sql_Query(sql_handle,
  746. -	    "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate`,`character_slots`,`pincode`, `pincode_change` FROM `%s` WHERE `account_id` = %d",
  747. -		db->account_db, account_id )
  748. -	) {
  749. -		Sql_ShowDebug(sql_handle);
  750. -		return false;
  751. -	}
  752. -
  753. -	if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  754. -	{// no such entry
  755. -		Sql_FreeResult(sql_handle);
  756. -		return false;
  757. -	}
  758. -
  759. -	Sql_GetData(sql_handle,  0, &data, NULL); acc->account_id = atoi(data);
  760. -	Sql_GetData(sql_handle,  1, &data, NULL); safestrncpy(acc->userid, data, sizeof(acc->userid));
  761. -	Sql_GetData(sql_handle,  2, &data, NULL); safestrncpy(acc->pass, data, sizeof(acc->pass));
  762. -	Sql_GetData(sql_handle,  3, &data, NULL); acc->sex = data[0];
  763. -	Sql_GetData(sql_handle,  4, &data, NULL); safestrncpy(acc->email, data, sizeof(acc->email));
  764. -	Sql_GetData(sql_handle,  5, &data, NULL); acc->group_id = atoi(data);
  765. -	Sql_GetData(sql_handle,  6, &data, NULL); acc->state = strtoul(data, NULL, 10);
  766. -	Sql_GetData(sql_handle,  7, &data, NULL); acc->unban_time = atol(data);
  767. -	Sql_GetData(sql_handle,  8, &data, NULL); acc->expiration_time = atol(data);
  768. -	Sql_GetData(sql_handle,  9, &data, NULL); acc->logincount = strtoul(data, NULL, 10);
  769. -	Sql_GetData(sql_handle, 10, &data, NULL); safestrncpy(acc->lastlogin, data, sizeof(acc->lastlogin));
  770. -	Sql_GetData(sql_handle, 11, &data, NULL); safestrncpy(acc->last_ip, data, sizeof(acc->last_ip));
  771. -	Sql_GetData(sql_handle, 12, &data, NULL); safestrncpy(acc->birthdate, data, sizeof(acc->birthdate));
  772. -	Sql_GetData(sql_handle, 13, &data, NULL); acc->char_slots = atoi(data);
  773. -	Sql_GetData(sql_handle, 14, &data, NULL); safestrncpy(acc->pincode, data, sizeof(acc->pincode));
  774. -	Sql_GetData(sql_handle, 15, &data, NULL); acc->pincode_change = atol(data);
  775. -
  776. -	Sql_FreeResult(sql_handle);
  777. -
  778. -
  779. -	// retrieve account regs for the specified user
  780. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) )
  781. -	{
  782. -		Sql_ShowDebug(sql_handle);
  783. -		return false;
  784. -	}
  785. -
  786. -	acc->account_reg2_num = (int)Sql_NumRows(sql_handle);
  787. -
  788. -	while( SQL_SUCCESS == Sql_NextRow(sql_handle) )
  789. -	{
  790. -		char* data;
  791. -		Sql_GetData(sql_handle, 0, &data, NULL); safestrncpy(acc->account_reg2[i].str, data, sizeof(acc->account_reg2[i].str));
  792. -		Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->account_reg2[i].value, data, sizeof(acc->account_reg2[i].value));
  793. -		++i;
  794. -	}
  795. -	Sql_FreeResult(sql_handle);
  796. -
  797. -	if( i != acc->account_reg2_num )
  798. -		return false;
  799. -
  800. -	return true;
  801. -}
  802. -
  803. -static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new)
  804. -{
  805. -	Sql* sql_handle = db->accounts;
  806. -	SqlStmt* stmt = SqlStmt_Malloc(sql_handle);
  807. -	bool result = false;
  808. -	int i;
  809. -
  810. -	// try
  811. -	do
  812. -	{
  813. -
  814. -	if( SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION") )
  815. -	{
  816. -		Sql_ShowDebug(sql_handle);
  817. -		break;
  818. -	}
  819. -
  820. -	if( is_new )
  821. -	{// insert into account table
  822. -		if( SQL_SUCCESS != SqlStmt_Prepare(stmt,
  823. -			"INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`, `character_slots`, `pincode`, `pincode_change`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
  824. -			db->account_db)
  825. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  0, SQLDT_INT,    (void*)&acc->account_id,      sizeof(acc->account_id))
  826. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  1, SQLDT_STRING, (void*)acc->userid,           strlen(acc->userid))
  827. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  2, SQLDT_STRING, (void*)acc->pass,             strlen(acc->pass))
  828. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  3, SQLDT_ENUM,   (void*)&acc->sex,             sizeof(acc->sex))
  829. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  4, SQLDT_STRING, (void*)&acc->email,           strlen(acc->email))
  830. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  5, SQLDT_INT,    (void*)&acc->group_id,        sizeof(acc->group_id))
  831. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  6, SQLDT_UINT,   (void*)&acc->state,           sizeof(acc->state))
  832. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  7, SQLDT_LONG,   (void*)&acc->unban_time,      sizeof(acc->unban_time))
  833. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  8, SQLDT_INT,    (void*)&acc->expiration_time, sizeof(acc->expiration_time))
  834. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  9, SQLDT_UINT,   (void*)&acc->logincount,      sizeof(acc->logincount))
  835. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->lastlogin,       strlen(acc->lastlogin))
  836. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->last_ip,         strlen(acc->last_ip))
  837. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_STRING, (void*)&acc->birthdate,       strlen(acc->birthdate))
  838. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 13, SQLDT_UCHAR,  (void*)&acc->char_slots,      sizeof(acc->char_slots))
  839. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 14, SQLDT_STRING, (void*)&acc->pincode,         strlen(acc->pincode))
  840. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 15, SQLDT_LONG,   (void*)&acc->pincode_change,  sizeof(acc->pincode_change))
  841. -		||  SQL_SUCCESS != SqlStmt_Execute(stmt)
  842. -		) {
  843. -			SqlStmt_ShowDebug(stmt);
  844. -			break;
  845. -		}
  846. -	}
  847. -	else
  848. -	{// update account table
  849. -		if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=?,`character_slots`=?,`pincode`=?, `pincode_change`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id)
  850. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  0, SQLDT_STRING, (void*)acc->userid,           strlen(acc->userid))
  851. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  1, SQLDT_STRING, (void*)acc->pass,             strlen(acc->pass))
  852. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  2, SQLDT_ENUM,   (void*)&acc->sex,             sizeof(acc->sex))
  853. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  3, SQLDT_STRING, (void*)acc->email,            strlen(acc->email))
  854. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  4, SQLDT_INT,    (void*)&acc->group_id,        sizeof(acc->group_id))
  855. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  5, SQLDT_UINT,   (void*)&acc->state,           sizeof(acc->state))
  856. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  6, SQLDT_LONG,   (void*)&acc->unban_time,      sizeof(acc->unban_time))
  857. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  7, SQLDT_LONG,   (void*)&acc->expiration_time, sizeof(acc->expiration_time))
  858. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  8, SQLDT_UINT,   (void*)&acc->logincount,      sizeof(acc->logincount))
  859. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  9, SQLDT_STRING, (void*)&acc->lastlogin,       strlen(acc->lastlogin))
  860. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->last_ip,         strlen(acc->last_ip))
  861. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->birthdate,       strlen(acc->birthdate))
  862. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_UCHAR,  (void*)&acc->char_slots,      sizeof(acc->char_slots))
  863. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 13, SQLDT_STRING, (void*)&acc->pincode,         strlen(acc->pincode))
  864. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 14, SQLDT_LONG,   (void*)&acc->pincode_change,  sizeof(acc->pincode_change))
  865. -		||  SQL_SUCCESS != SqlStmt_Execute(stmt)
  866. -		) {
  867. -			SqlStmt_ShowDebug(stmt);
  868. -			break;
  869. -		}
  870. -	}
  871. -
  872. -	// remove old account regs
  873. -	if( SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) )
  874. -	{
  875. -		Sql_ShowDebug(sql_handle);
  876. -		break;
  877. -	}
  878. -	// insert new account regs
  879. -	if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , ? , ? );",  db->accreg_db, acc->account_id) )
  880. -	{
  881. -		SqlStmt_ShowDebug(stmt);
  882. -		break;
  883. -	}
  884. -	for( i = 0; i < acc->account_reg2_num; ++i )
  885. -	{
  886. -		if( SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->account_reg2[i].str, strlen(acc->account_reg2[i].str))
  887. -		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->account_reg2[i].value, strlen(acc->account_reg2[i].value))
  888. -		||  SQL_SUCCESS != SqlStmt_Execute(stmt)
  889. -		) {
  890. -			SqlStmt_ShowDebug(stmt);
  891. -			break;
  892. -		}
  893. -	}
  894. -	if( i < acc->account_reg2_num )
  895. -	{
  896. -		result = false;
  897. -		break;
  898. -	}
  899. -
  900. -	// if we got this far, everything was successful
  901. -	result = true;
  902. -
  903. -	} while(0);
  904. -	// finally
  905. -
  906. -	result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") );
  907. -	SqlStmt_Free(stmt);
  908. -
  909. -	return result;
  910. -}
  911. Index: src/login/login.h
  912. ===================================================================
  913. --- src/login/login.h	(revision 17373)
  914. +++ src/login/login.h	(working copy)
  915. @@ -6,6 +6,7 @@
  916.  
  917.  #include "../common/mmo.h" // NAME_LENGTH,SEX_*
  918.  #include "../common/core.h" // CORE_ST_LAST
  919. +#include "account.h"
  920.  
  921.  enum E_LOGINSERVER_ST
  922.  {
  923. @@ -40,8 +41,8 @@
  924.  	int fd;
  925.  };
  926.  
  927. +#define MAX_SERVERS 30
  928.  struct mmo_char_server {
  929. -
  930.  	char name[20];
  931.  	int fd;
  932.  	uint32 ip;
  933. @@ -49,7 +50,7 @@
  934.  	uint16 users;       // user count on this server
  935.  	uint16 type;        // 0=normal, 1=maintenance, 2=over 18, 3=paying, 4=P2P
  936.  	uint16 new_;        // should display as 'new'?
  937. -};
  938. +} server[MAX_SERVERS]; // char server data
  939.  
  940.  struct client_hash_node {
  941.  	int group_id;
  942. @@ -83,10 +84,15 @@
  943.  	char dnsbl_servs[1024];                         // comma-separated list of dnsbl servers
  944.  
  945.  	char account_engine[256];                       // name of the engine to use (defaults to auto, for the first available engine)
  946. +	int allowed_regs;				//max number of registration
  947. +	int time_allowed;				//registration intervall in seconds
  948.  
  949.  	int client_hash_check;							// flags for checking client md5
  950.  	struct client_hash_node *client_hash_nodes;		// linked list containg md5 hash for each gm group
  951. -};
  952. +	char *loginconf_name;
  953. +	char *msgconf_name;
  954. +	char *lanconf_name;
  955. +} login_config;
  956.  
  957.  #define sex_num2str(num) ( (num ==  SEX_FEMALE  ) ? 'F' : (num ==  SEX_MALE  ) ? 'M' : 'S' )
  958.  #define sex_str2num(str) ( (str == 'F' ) ?  SEX_FEMALE  : (str == 'M' ) ?  SEX_MALE  :  SEX_SERVER  )
  959. @@ -94,15 +100,51 @@
  960.  #define msg_config_read(cfgName) login_msg_config_read(cfgName)
  961.  #define msg_txt(msg_number) login_msg_txt(msg_number)
  962.  #define do_final_msg() login_do_final_msg()
  963. -
  964.  int login_msg_config_read(char *cfgName);
  965.  const char* login_msg_txt(int msg_number);
  966.  void login_do_final_msg(void);
  967.  
  968. +//-----------------------------------------------------
  969. +// Online User Database [Wizputer]
  970. +//-----------------------------------------------------
  971. +struct online_login_data {
  972. +	int account_id;
  973. +	int waiting_disconnect;
  974. +	int char_server;
  975. +};
  976. +DBMap* online_db; // int account_id -> struct online_login_data*
  977.  
  978. -#define MAX_SERVERS 30
  979. -extern struct mmo_char_server server[MAX_SERVERS];
  980. -extern struct Login_Config login_config;
  981. +//-----------------------------------------------------
  982. +// Auth database
  983. +//-----------------------------------------------------
  984. +#define AUTH_TIMEOUT 30000
  985. +struct auth_node {
  986. +	int account_id;
  987. +	uint32 login_id1;
  988. +	uint32 login_id2;
  989. +	uint32 ip;
  990. +	char sex;
  991. +	uint32 version;
  992. +	uint8 clienttype;
  993. +};
  994. +DBMap* auth_db; // int account_id -> struct auth_node*
  995.  
  996.  
  997. +AccountDB* login_get_accounts_db(void);
  998. +
  999. +
  1000. +bool check_encrypted(const char* str1, const char* str2, const char* passwd);
  1001. +bool check_password(const char* md5key, int passwdenc, const char* passwd, const char* refpass);
  1002. +
  1003. +int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data);
  1004. +void remove_online_user(int account_id);
  1005. +struct online_login_data* add_online_user(int char_server, int account_id);
  1006. +int lan_subnetcheck(uint32 ip);
  1007. +
  1008. +int online_db_setoffline(DBKey key, DBData *data, va_list ap);
  1009. +DBData create_online_user(DBKey key, va_list args);
  1010. +
  1011. +int mmo_auth_new(const char* userid, const char* pass, const char sex, const char* last_ip);
  1012. +int mmo_auth(struct login_session_data* sd, bool isServer);
  1013. +
  1014.  #endif /* _LOGIN_H_ */
  1015. Index: src/login/sql/CMakeLists.txt
  1016. ===================================================================
  1017. --- src/login/sql/CMakeLists.txt	(revision 17373)
  1018. +++ src/login/sql/CMakeLists.txt	(working copy)
  1019. @@ -8,13 +8,19 @@
  1020.  	"${SQL_LOGIN_SOURCE_DIR}/account.h"
  1021.  	"${SQL_LOGIN_SOURCE_DIR}/ipban.h"
  1022.  	"${SQL_LOGIN_SOURCE_DIR}/login.h"
  1023. +	"${SQL_LOGIN_SOURCE_DIR}/loginclif.h"
  1024. +	"${SQL_LOGIN_SOURCE_DIR}/loginchrif.h"
  1025. +	"${SQL_LOGIN_SOURCE_DIR}/logincnslif.h"
  1026.  	"${SQL_LOGIN_SOURCE_DIR}/loginlog.h"
  1027.  	)
  1028.  set( SQL_LOGIN_SOURCES
  1029. -	"${SQL_LOGIN_SOURCE_DIR}/account_sql.c"
  1030. -	"${SQL_LOGIN_SOURCE_DIR}/ipban_sql.c"
  1031. +	"${SQL_LOGIN_SOURCE_DIR}/account.c"
  1032. +	"${SQL_LOGIN_SOURCE_DIR}/ipban.c"
  1033.  	"${SQL_LOGIN_SOURCE_DIR}/login.c"
  1034. -	"${SQL_LOGIN_SOURCE_DIR}/loginlog_sql.c"
  1035. +	"${SQL_LOGIN_SOURCE_DIR}/loginclif.c"
  1036. +	"${SQL_LOGIN_SOURCE_DIR}/loginchrif.c"
  1037. +	"${SQL_LOGIN_SOURCE_DIR}/logincnslif.c"
  1038. +	"${SQL_LOGIN_SOURCE_DIR}/loginlog.c"
  1039.  	)
  1040.  set( DEPENDENCIES common_sql )
  1041.  set( LIBRARIES ${GLOBAL_LIBRARIES} )
  1042. Index: src/login/loginlog_sql.c
  1043. ===================================================================
  1044. --- src/login/loginlog_sql.c	(revision 17373)
  1045. +++ src/login/loginlog_sql.c	(working copy)
  1046. @@ -1,184 +0,0 @@
  1047. -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  1048. -// For more information, see LICENCE in the main folder
  1049. -
  1050. -#include "../common/cbasetypes.h"
  1051. -#include "../common/mmo.h"
  1052. -#include "../common/socket.h"
  1053. -#include "../common/sql.h"
  1054. -#include "../common/strlib.h"
  1055. -#include <string.h>
  1056. -#include <stdlib.h> // exit
  1057. -
  1058. -// global sql settings (in ipban_sql.c)
  1059. -static char   global_db_hostname[32] = "127.0.0.1";
  1060. -static uint16 global_db_port = 3306;
  1061. -static char   global_db_username[32] = "ragnarok";
  1062. -static char   global_db_password[32] = "ragnarok";
  1063. -static char   global_db_database[32] = "ragnarok";
  1064. -static char   global_codepage[32] = "";
  1065. -// local sql settings
  1066. -static char   log_db_hostname[32] = "";
  1067. -static uint16 log_db_port = 0;
  1068. -static char   log_db_username[32] = "";
  1069. -static char   log_db_password[32] = "";
  1070. -static char   log_db_database[32] = "";
  1071. -static char   log_codepage[32] = "";
  1072. -static char   log_login_db[256] = "loginlog";
  1073. -
  1074. -static Sql* sql_handle = NULL;
  1075. -static bool enabled = false;
  1076. -
  1077. -
  1078. -// Returns the number of failed login attemps by the ip in the last minutes.
  1079. -unsigned long loginlog_failedattempts(uint32 ip, unsigned int minutes)
  1080. -{
  1081. -	unsigned long failures = 0;
  1082. -
  1083. -	if( !enabled )
  1084. -		return 0;
  1085. -
  1086. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `ip` = '%s' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE",
  1087. -		log_login_db, ip2str(ip,NULL), minutes) )// how many times failed account? in one ip.
  1088. -		Sql_ShowDebug(sql_handle);
  1089. -
  1090. -	if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
  1091. -	{
  1092. -		char* data;
  1093. -		Sql_GetData(sql_handle, 0, &data, NULL);
  1094. -		failures = strtoul(data, NULL, 10);
  1095. -		Sql_FreeResult(sql_handle);
  1096. -	}
  1097. -	return failures;
  1098. -}
  1099. -
  1100. -
  1101. -/*=============================================
  1102. - * Records an event in the login log
  1103. - *---------------------------------------------*/
  1104. -void login_log(uint32 ip, const char* username, int rcode, const char* message)
  1105. -{
  1106. -	char esc_username[NAME_LENGTH*2+1];
  1107. -	char esc_message[255*2+1];
  1108. -	int retcode;
  1109. -
  1110. -	if( !enabled )
  1111. -		return;
  1112. -
  1113. -	Sql_EscapeStringLen(sql_handle, esc_username, username, strnlen(username, NAME_LENGTH));
  1114. -	Sql_EscapeStringLen(sql_handle, esc_message, message, strnlen(message, 255));
  1115. -
  1116. -	retcode = Sql_Query(sql_handle,
  1117. -		"INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%s', '%s', '%d', '%s')",
  1118. -		log_login_db, ip2str(ip,NULL), esc_username, rcode, esc_message);
  1119. -
  1120. -	if( retcode != SQL_SUCCESS )
  1121. -		Sql_ShowDebug(sql_handle);
  1122. -}
  1123. -
  1124. -bool loginlog_init(void)
  1125. -{
  1126. -	const char* username;
  1127. -	const char* password;
  1128. -	const char* hostname;
  1129. -	uint16      port;
  1130. -	const char* database;
  1131. -	const char* codepage;
  1132. -
  1133. -	if( log_db_hostname[0] != '\0' )
  1134. -	{// local settings
  1135. -		username = log_db_username;
  1136. -		password = log_db_password;
  1137. -		hostname = log_db_hostname;
  1138. -		port     = log_db_port;
  1139. -		database = log_db_database;
  1140. -		codepage = log_codepage;
  1141. -	}
  1142. -	else
  1143. -	{// global settings
  1144. -		username = global_db_username;
  1145. -		password = global_db_password;
  1146. -		hostname = global_db_hostname;
  1147. -		port     = global_db_port;
  1148. -		database = global_db_database;
  1149. -		codepage = global_codepage;
  1150. -	}
  1151. -
  1152. -	sql_handle = Sql_Malloc();
  1153. -
  1154. -	if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) )
  1155. -	{
  1156. -		Sql_ShowDebug(sql_handle);
  1157. -		Sql_Free(sql_handle);
  1158. -		exit(EXIT_FAILURE);
  1159. -	}
  1160. -
  1161. -	if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) )
  1162. -		Sql_ShowDebug(sql_handle);
  1163. -
  1164. -	enabled = true;
  1165. -
  1166. -	return true;
  1167. -}
  1168. -
  1169. -bool loginlog_final(void)
  1170. -{
  1171. -	Sql_Free(sql_handle);
  1172. -	sql_handle = NULL;
  1173. -	return true;
  1174. -}
  1175. -
  1176. -bool loginlog_config_read(const char* key, const char* value)
  1177. -{
  1178. -	const char* signature;
  1179. -
  1180. -	signature = "sql.";
  1181. -	if( strncmpi(key, signature, strlen(signature)) == 0 )
  1182. -	{
  1183. -		key += strlen(signature);
  1184. -		if( strcmpi(key, "db_hostname") == 0 )
  1185. -			safestrncpy(global_db_hostname, value, sizeof(global_db_hostname));
  1186. -		else
  1187. -		if( strcmpi(key, "db_port") == 0 )
  1188. -			global_db_port = (uint16)strtoul(value, NULL, 10);
  1189. -		else
  1190. -		if( strcmpi(key, "db_username") == 0 )
  1191. -			safestrncpy(global_db_username, value, sizeof(global_db_username));
  1192. -		else
  1193. -		if( strcmpi(key, "db_password") == 0 )
  1194. -			safestrncpy(global_db_password, value, sizeof(global_db_password));
  1195. -		else
  1196. -		if( strcmpi(key, "db_database") == 0 )
  1197. -			safestrncpy(global_db_database, value, sizeof(global_db_database));
  1198. -		else
  1199. -		if( strcmpi(key, "codepage") == 0 )
  1200. -			safestrncpy(global_codepage, value, sizeof(global_codepage));
  1201. -		else
  1202. -			return false;// not found
  1203. -		return true;
  1204. -	}
  1205. -
  1206. -	if( strcmpi(key, "log_db_ip") == 0 )
  1207. -		safestrncpy(log_db_hostname, value, sizeof(log_db_hostname));
  1208. -	else
  1209. -	if( strcmpi(key, "log_db_port") == 0 )
  1210. -		log_db_port = (uint16)strtoul(value, NULL, 10);
  1211. -	else
  1212. -	if( strcmpi(key, "log_db_id") == 0 )
  1213. -		safestrncpy(log_db_username, value, sizeof(log_db_username));
  1214. -	else
  1215. -	if( strcmpi(key, "log_db_pw") == 0 )
  1216. -		safestrncpy(log_db_password, value, sizeof(log_db_password));
  1217. -	else
  1218. -	if( strcmpi(key, "log_db_db") == 0 )
  1219. -		safestrncpy(log_db_database, value, sizeof(log_db_database));
  1220. -	else
  1221. -	if( strcmpi(key, "log_codepage") == 0 )
  1222. -		safestrncpy(log_codepage, value, sizeof(log_codepage));
  1223. -	else
  1224. -	if( strcmpi(key, "log_login_db") == 0 )
  1225. -		safestrncpy(log_login_db, value, sizeof(log_login_db));
  1226. -	else
  1227. -		return false;
  1228. -
  1229. -	return true;
  1230. -}
  1231. Index: src/login/ipban.c
  1232. ===================================================================
  1233. --- src/login/ipban.c	(working copy)
  1234. +++ src/login/ipban.c	(working copy)
  1235. @@ -100,7 +100,7 @@
  1236.  	if( login_config.ipban_cleanup_interval > 0 )
  1237.  		// release data
  1238.  		delete_timer(cleanup_timer_id, ipban_cleanup);
  1239. -	
  1240. +
  1241.  	ipban_cleanup(0,0,0,0); // always clean up on login-server stop
  1242.  
  1243.  	// close connections
  1244. Index: src/login/Makefile.in
  1245. ===================================================================
  1246. --- src/login/Makefile.in	(revision 17373)
  1247. +++ src/login/Makefile.in	(working copy)
  1248. @@ -12,10 +12,9 @@
  1249.  	../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h
  1250.  LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig
  1251.  
  1252. -LOGIN_OBJ = login.o
  1253. -LOGIN_SQL_OBJ = $(LOGIN_OBJ:%=obj_sql/%) \
  1254. -	obj_sql/account_sql.o obj_sql/ipban_sql.o obj_sql/loginlog_sql.o
  1255. -LOGIN_H = login.h account.h ipban.h loginlog.h
  1256. +LOGIN_OBJ = login.o loginclif.o loginchrif.o logincnslif.o account.o ipban.o loginlog.o
  1257. +LOGIN_H = login.h loginclif.h loginchrif.h logincnslif.h account.h ipban.h loginlog.h
  1258. +LOGIN_SQL_OBJ = $(LOGIN_OBJ:%=obj_sql/%)
  1259.  
  1260.  HAVE_MYSQL=@HAVE_MYSQL@
  1261.  ifeq ($(HAVE_MYSQL),yes)
  1262. @@ -62,8 +61,8 @@
  1263.  login-server_sql: obj_sql $(LOGIN_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a  $(MT19937AR_OBJ)
  1264.  	@echo "	LD	$@"
  1265.  	@@CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ $(LOGIN_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
  1266. -	    
  1267.  
  1268. +
  1269.  # login object files
  1270.  
  1271.  obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H)
  1272. Index: src/login/ipban_sql.c
  1273. ===================================================================
  1274. --- src/login/ipban_sql.c	(revision 17373)
  1275. +++ src/login/ipban_sql.c	(working copy)
  1276. @@ -1,258 +0,0 @@
  1277. -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  1278. -// For more information, see LICENCE in the main folder
  1279. -
  1280. -#include "../common/cbasetypes.h"
  1281. -#include "../common/db.h"
  1282. -#include "../common/malloc.h"
  1283. -#include "../common/sql.h"
  1284. -#include "../common/socket.h"
  1285. -#include "../common/strlib.h"
  1286. -#include "../common/timer.h"
  1287. -#include "login.h"
  1288. -#include "ipban.h"
  1289. -#include "loginlog.h"
  1290. -#include <stdlib.h>
  1291. -#include <string.h>
  1292. -
  1293. -// global sql settings
  1294. -static char   global_db_hostname[32] = "127.0.0.1";
  1295. -static uint16 global_db_port = 3306;
  1296. -static char   global_db_username[32] = "ragnarok";
  1297. -static char   global_db_password[32] = "ragnarok";
  1298. -static char   global_db_database[32] = "ragnarok";
  1299. -static char   global_codepage[32] = "";
  1300. -// local sql settings
  1301. -static char   ipban_db_hostname[32] = "";
  1302. -static uint16 ipban_db_port = 0;
  1303. -static char   ipban_db_username[32] = "";
  1304. -static char   ipban_db_password[32] = "";
  1305. -static char   ipban_db_database[32] = "";
  1306. -static char   ipban_codepage[32] = "";
  1307. -static char   ipban_table[32] = "ipbanlist";
  1308. -
  1309. -// globals
  1310. -static Sql* sql_handle = NULL;
  1311. -static int cleanup_timer_id = INVALID_TIMER;
  1312. -static bool ipban_inited = false;
  1313. -
  1314. -int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data);
  1315. -
  1316. -
  1317. -// initialize
  1318. -void ipban_init(void)
  1319. -{
  1320. -	const char* username;
  1321. -	const char* password;
  1322. -	const char* hostname;
  1323. -	uint16      port;
  1324. -	const char* database;
  1325. -	const char* codepage;
  1326. -
  1327. -	ipban_inited = true;
  1328. -
  1329. -	if( !login_config.ipban )
  1330. -		return;// ipban disabled
  1331. -
  1332. -	if( ipban_db_hostname[0] != '\0' )
  1333. -	{// local settings
  1334. -		username = ipban_db_username;
  1335. -		password = ipban_db_password;
  1336. -		hostname = ipban_db_hostname;
  1337. -		port     = ipban_db_port;
  1338. -		database = ipban_db_database;
  1339. -		codepage = ipban_codepage;
  1340. -	}
  1341. -	else
  1342. -	{// global settings
  1343. -		username = global_db_username;
  1344. -		password = global_db_password;
  1345. -		hostname = global_db_hostname;
  1346. -		port     = global_db_port;
  1347. -		database = global_db_database;
  1348. -		codepage = global_codepage;
  1349. -	}
  1350. -
  1351. -	// establish connections
  1352. -	sql_handle = Sql_Malloc();
  1353. -	if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) )
  1354. -	{
  1355. -		Sql_ShowDebug(sql_handle);
  1356. -		Sql_Free(sql_handle);
  1357. -		exit(EXIT_FAILURE);
  1358. -	}
  1359. -	if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) )
  1360. -		Sql_ShowDebug(sql_handle);
  1361. -
  1362. -	if( login_config.ipban_cleanup_interval > 0 )
  1363. -	{ // set up periodic cleanup of connection history and active bans
  1364. -		add_timer_func_list(ipban_cleanup, "ipban_cleanup");
  1365. -		cleanup_timer_id = add_timer_interval(gettick()+10, ipban_cleanup, 0, 0, login_config.ipban_cleanup_interval*1000);
  1366. -	} else // make sure it gets cleaned up on login-server start regardless of interval-based cleanups
  1367. -		ipban_cleanup(0,0,0,0);
  1368. -}
  1369. -
  1370. -// finalize
  1371. -void ipban_final(void)
  1372. -{
  1373. -	if( !login_config.ipban )
  1374. -		return;// ipban disabled
  1375. -
  1376. -	if( login_config.ipban_cleanup_interval > 0 )
  1377. -		// release data
  1378. -		delete_timer(cleanup_timer_id, ipban_cleanup);
  1379. -	
  1380. -	ipban_cleanup(0,0,0,0); // always clean up on login-server stop
  1381. -
  1382. -	// close connections
  1383. -	Sql_Free(sql_handle);
  1384. -	sql_handle = NULL;
  1385. -}
  1386. -
  1387. -// load configuration options
  1388. -bool ipban_config_read(const char* key, const char* value)
  1389. -{
  1390. -	const char* signature;
  1391. -
  1392. -	if( ipban_inited )
  1393. -		return false;// settings can only be changed before init
  1394. -
  1395. -	signature = "sql.";
  1396. -	if( strncmpi(key, signature, strlen(signature)) == 0 )
  1397. -	{
  1398. -		key += strlen(signature);
  1399. -		if( strcmpi(key, "db_hostname") == 0 )
  1400. -			safestrncpy(global_db_hostname, value, sizeof(global_db_hostname));
  1401. -		else
  1402. -		if( strcmpi(key, "db_port") == 0 )
  1403. -			global_db_port = (uint16)strtoul(value, NULL, 10);
  1404. -		else
  1405. -		if( strcmpi(key, "db_username") == 0 )
  1406. -			safestrncpy(global_db_username, value, sizeof(global_db_username));
  1407. -		else
  1408. -		if( strcmpi(key, "db_password") == 0 )
  1409. -			safestrncpy(global_db_password, value, sizeof(global_db_password));
  1410. -		else
  1411. -		if( strcmpi(key, "db_database") == 0 )
  1412. -			safestrncpy(global_db_database, value, sizeof(global_db_database));
  1413. -		else
  1414. -		if( strcmpi(key, "codepage") == 0 )
  1415. -			safestrncpy(global_codepage, value, sizeof(global_codepage));
  1416. -		else
  1417. -			return false;// not found
  1418. -		return true;
  1419. -	}
  1420. -
  1421. -	signature = "ipban.sql.";
  1422. -	if( strncmpi(key, signature, strlen(signature)) == 0 )
  1423. -	{
  1424. -		key += strlen(signature);
  1425. -		if( strcmpi(key, "db_hostname") == 0 )
  1426. -			safestrncpy(ipban_db_hostname, value, sizeof(ipban_db_hostname));
  1427. -		else
  1428. -		if( strcmpi(key, "db_port") == 0 )
  1429. -			ipban_db_port = (uint16)strtoul(value, NULL, 10);
  1430. -		else
  1431. -		if( strcmpi(key, "db_username") == 0 )
  1432. -			safestrncpy(ipban_db_username, value, sizeof(ipban_db_username));
  1433. -		else
  1434. -		if( strcmpi(key, "db_password") == 0 )
  1435. -			safestrncpy(ipban_db_password, value, sizeof(ipban_db_password));
  1436. -		else
  1437. -		if( strcmpi(key, "db_database") == 0 )
  1438. -			safestrncpy(ipban_db_database, value, sizeof(ipban_db_database));
  1439. -		else
  1440. -		if( strcmpi(key, "codepage") == 0 )
  1441. -			safestrncpy(ipban_codepage, value, sizeof(ipban_codepage));
  1442. -		else
  1443. -		if( strcmpi(key, "ipban_table") == 0 )
  1444. -			safestrncpy(ipban_table, value, sizeof(ipban_table));
  1445. -		else
  1446. -			return false;// not found
  1447. -		return true;
  1448. -	}
  1449. -
  1450. -	signature = "ipban.";
  1451. -	if( strncmpi(key, signature, strlen(signature)) == 0 )
  1452. -	{
  1453. -		key += strlen(signature);
  1454. -		if( strcmpi(key, "enable") == 0 )
  1455. -			login_config.ipban = (bool)config_switch(value);
  1456. -		else
  1457. -		if( strcmpi(key, "dynamic_pass_failure_ban") == 0 )
  1458. -			login_config.dynamic_pass_failure_ban = (bool)config_switch(value);
  1459. -		else
  1460. -		if( strcmpi(key, "dynamic_pass_failure_ban_interval") == 0 )
  1461. -			login_config.dynamic_pass_failure_ban_interval = atoi(value);
  1462. -		else
  1463. -		if( strcmpi(key, "dynamic_pass_failure_ban_limit") == 0 )
  1464. -			login_config.dynamic_pass_failure_ban_limit = atoi(value);
  1465. -		else
  1466. -		if( strcmpi(key, "dynamic_pass_failure_ban_duration") == 0 )
  1467. -			login_config.dynamic_pass_failure_ban_duration = atoi(value);
  1468. -		else
  1469. -			return false;// not found
  1470. -		return true;
  1471. -	}
  1472. -
  1473. -	return false;// not found
  1474. -}
  1475. -
  1476. -// check ip against active bans list
  1477. -bool ipban_check(uint32 ip)
  1478. -{
  1479. -	uint8* p = (uint8*)&ip;
  1480. -	char* data = NULL;
  1481. -	int matches;
  1482. -
  1483. -	if( !login_config.ipban )
  1484. -		return false;// ipban disabled
  1485. -
  1486. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `rtime` > NOW() AND (`list` = '%u.*.*.*' OR `list` = '%u.%u.*.*' OR `list` = '%u.%u.%u.*' OR `list` = '%u.%u.%u.%u')",
  1487. -		ipban_table, p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]) )
  1488. -	{
  1489. -		Sql_ShowDebug(sql_handle);
  1490. -		// close connection because we can't verify their connectivity.
  1491. -		return true;
  1492. -	}
  1493. -
  1494. -	if( SQL_ERROR == Sql_NextRow(sql_handle) )
  1495. -		return true;// Shouldn't happen, but just in case...
  1496. -
  1497. -	Sql_GetData(sql_handle, 0, &data, NULL);
  1498. -	matches = atoi(data);
  1499. -	Sql_FreeResult(sql_handle);
  1500. -
  1501. -	return( matches > 0 );
  1502. -}
  1503. -
  1504. -// log failed attempt
  1505. -void ipban_log(uint32 ip)
  1506. -{
  1507. -	unsigned long failures;
  1508. -
  1509. -	if( !login_config.ipban )
  1510. -		return;// ipban disabled
  1511. -
  1512. -	failures = loginlog_failedattempts(ip, login_config.dynamic_pass_failure_ban_interval);// how many times failed account? in one ip.
  1513. -
  1514. -	// if over the limit, add a temporary ban entry
  1515. -	if( failures >= login_config.dynamic_pass_failure_ban_limit )
  1516. -	{
  1517. -		uint8* p = (uint8*)&ip;
  1518. -		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`list`,`btime`,`rtime`,`reason`) VALUES ('%u.%u.%u.*', NOW() , NOW() +  INTERVAL %d MINUTE ,'Password error ban')",
  1519. -			ipban_table, p[3], p[2], p[1], login_config.dynamic_pass_failure_ban_duration) )
  1520. -			Sql_ShowDebug(sql_handle);
  1521. -	}
  1522. -}
  1523. -
  1524. -// remove expired bans
  1525. -int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data)
  1526. -{
  1527. -	if( !login_config.ipban )
  1528. -		return 0;// ipban disabled
  1529. -
  1530. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()") )
  1531. -		Sql_ShowDebug(sql_handle);
  1532. -
  1533. -	return 0;
  1534. -}
  1535. Index: src/login/login.c
  1536. ===================================================================
  1537. --- src/login/login.c	(revision 17373)
  1538. +++ src/login/login.c	(working copy)
  1539. @@ -7,16 +7,18 @@
  1540.  #include "../common/md5calc.h"
  1541.  #include "../common/random.h"
  1542.  #include "../common/showmsg.h"
  1543. -#include "../common/socket.h"
  1544. +#include "../common/socket.h" //ip2str
  1545.  #include "../common/strlib.h"
  1546.  #include "../common/timer.h"
  1547.  #include "../common/msg_conf.h"
  1548. -#include "../common/cli.h"
  1549. -#include "../common/ers.h"
  1550. +#include "../common/utils.h"
  1551.  #include "account.h"
  1552.  #include "ipban.h"
  1553.  #include "login.h"
  1554.  #include "loginlog.h"
  1555. +#include "loginclif.h"
  1556. +#include "loginchrif.h"
  1557. +#include "logincnslif.h"
  1558.  
  1559.  #include <stdio.h>
  1560.  #include <stdlib.h>
  1561. @@ -24,11 +26,6 @@
  1562.  
  1563.  #define LOGIN_MAX_MSG 30
  1564.  static char* msg_table[LOGIN_MAX_MSG]; // Login Server messages_conf
  1565. -struct Login_Config login_config;
  1566. -
  1567. -int login_fd; // login server socket
  1568. -struct mmo_char_server server[MAX_SERVERS]; // char server data
  1569. -
  1570.  // Account engines available
  1571.  static struct{
  1572.  	AccountDB* (*constructor)(void);
  1573. @@ -53,60 +50,25 @@
  1574.  	// end of structure
  1575.  	{NULL, NULL}
  1576.  };
  1577. -// account database
  1578. -AccountDB* accounts = NULL;
  1579. -
  1580. -//Account registration flood protection [Kevin]
  1581. -int allowed_regs = 1;
  1582. -int time_allowed = 10; //in seconds
  1583. -
  1584. +AccountDB* accounts = NULL; // account database«
  1585.  // Advanced subnet check [LuzZza]
  1586.  struct s_subnet {
  1587.  	uint32 mask;
  1588.  	uint32 char_ip;
  1589.  	uint32 map_ip;
  1590.  } subnet[16];
  1591. -
  1592.  int subnet_count = 0;
  1593.  
  1594. -int mmo_auth_new(const char* userid, const char* pass, const char sex, const char* last_ip);
  1595. +int login_fd; // login server socket
  1596.  
  1597. -//-----------------------------------------------------
  1598. -// Auth database
  1599. -//-----------------------------------------------------
  1600. -#define AUTH_TIMEOUT 30000
  1601. +AccountDB* login_get_accounts_db(void){
  1602. +	return accounts;
  1603. +}
  1604.  
  1605. -struct auth_node {
  1606. -
  1607. -	int account_id;
  1608. -	uint32 login_id1;
  1609. -	uint32 login_id2;
  1610. -	uint32 ip;
  1611. -	char sex;
  1612. -	uint32 version;
  1613. -	uint8 clienttype;
  1614. -};
  1615. -
  1616. -static DBMap* auth_db; // int account_id -> struct auth_node*
  1617. -
  1618. -
  1619. -//-----------------------------------------------------
  1620. -// Online User Database [Wizputer]
  1621. -//-----------------------------------------------------
  1622. -struct online_login_data {
  1623. -
  1624. -	int account_id;
  1625. -	int waiting_disconnect;
  1626. -	int char_server;
  1627. -};
  1628. -
  1629. -static DBMap* online_db; // int account_id -> struct online_login_data*
  1630. -static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data);
  1631. -
  1632.  /**
  1633.   * @see DBCreateData
  1634.   */
  1635. -static DBData create_online_user(DBKey key, va_list args)
  1636. +DBData create_online_user(DBKey key, va_list args)
  1637.  {
  1638.  	struct online_login_data* p;
  1639.  	CREATE(p, struct online_login_data, 1);
  1640. @@ -141,7 +103,7 @@
  1641.  	idb_remove(online_db, account_id);
  1642.  }
  1643.  
  1644. -static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data)
  1645. +int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data)
  1646.  {
  1647.  	struct online_login_data* p = (struct online_login_data*)idb_get(online_db, id);
  1648.  	if( p != NULL && p->waiting_disconnect == tid && p->account_id == id )
  1649. @@ -154,9 +116,9 @@
  1650.  }
  1651.  
  1652.  /**
  1653. - * @see DBApply
  1654. + * Mark a char offline
  1655.   */
  1656. -static int online_db_setoffline(DBKey key, DBData *data, va_list ap)
  1657. +int online_db_setoffline(DBKey key, DBData *data, va_list ap)
  1658.  {
  1659.  	struct online_login_data* p = db_data2ptr(data);
  1660.  	int server = va_arg(ap, int);
  1661. @@ -192,766 +154,7 @@
  1662.  }
  1663.  
  1664.  
  1665. -//--------------------------------------------------------------------
  1666. -// Packet send to all char-servers, except one (wos: without our self)
  1667. -//--------------------------------------------------------------------
  1668. -int charif_sendallwos(int sfd, uint8* buf, size_t len)
  1669. -{
  1670. -	int i, c;
  1671.  
  1672. -	for( i = 0, c = 0; i < ARRAYLENGTH(server); ++i )
  1673. -	{
  1674. -		int fd = server[i].fd;
  1675. -		if( session_isValid(fd) && fd != sfd )
  1676. -		{
  1677. -			WFIFOHEAD(fd,len);
  1678. -			memcpy(WFIFOP(fd,0), buf, len);
  1679. -			WFIFOSET(fd,len);
  1680. -			++c;
  1681. -		}
  1682. -	}
  1683. -
  1684. -	return c;
  1685. -}
  1686. -
  1687. -
  1688. -/// Initializes a server structure.
  1689. -void chrif_server_init(int id)
  1690. -{
  1691. -	memset(&server[id], 0, sizeof(server[id]));
  1692. -	server[id].fd = -1;
  1693. -}
  1694. -
  1695. -
  1696. -/// Destroys a server structure.
  1697. -void chrif_server_destroy(int id)
  1698. -{
  1699. -	if( server[id].fd != -1 )
  1700. -	{
  1701. -		do_close(server[id].fd);
  1702. -		server[id].fd = -1;
  1703. -	}
  1704. -}
  1705. -
  1706. -
  1707. -/// Resets all the data related to a server.
  1708. -void chrif_server_reset(int id)
  1709. -{
  1710. -	online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char server to offline.
  1711. -	chrif_server_destroy(id);
  1712. -	chrif_server_init(id);
  1713. -}
  1714. -
  1715. -
  1716. -/// Called when the connection to Char Server is disconnected.
  1717. -void chrif_on_disconnect(int id)
  1718. -{
  1719. -	ShowStatus("Char-server '%s' has disconnected.\n", server[id].name);
  1720. -	chrif_server_reset(id);
  1721. -}
  1722. -
  1723. -
  1724. -//-----------------------------------------------------
  1725. -// periodic ip address synchronization
  1726. -//-----------------------------------------------------
  1727. -static int sync_ip_addresses(int tid, unsigned int tick, int id, intptr_t data)
  1728. -{
  1729. -	uint8 buf[2];
  1730. -	ShowInfo("IP Sync in progress...\n");
  1731. -	WBUFW(buf,0) = 0x2735;
  1732. -	charif_sendallwos(-1, buf, 2);
  1733. -	return 0;
  1734. -}
  1735. -
  1736. -
  1737. -//-----------------------------------------------------
  1738. -// encrypted/unencrypted password check (from eApp)
  1739. -//-----------------------------------------------------
  1740. -bool check_encrypted(const char* str1, const char* str2, const char* passwd)
  1741. -{
  1742. -	char tmpstr[64+1], md5str[32+1];
  1743. -
  1744. -	safesnprintf(tmpstr, sizeof(tmpstr), "%s%s", str1, str2);
  1745. -	MD5_String(tmpstr, md5str);
  1746. -
  1747. -	return (0==strcmp(passwd, md5str));
  1748. -}
  1749. -
  1750. -bool check_password(const char* md5key, int passwdenc, const char* passwd, const char* refpass)
  1751. -{
  1752. -	if(passwdenc == 0)
  1753. -	{
  1754. -		return (0==strcmp(passwd, refpass));
  1755. -	}
  1756. -	else
  1757. -	{
  1758. -		// password mode set to 1 -> md5(md5key, refpass) enable with <passwordencrypt></passwordencrypt>
  1759. -		// password mode set to 2 -> md5(refpass, md5key) enable with <passwordencrypt2></passwordencrypt2>
  1760. -
  1761. -		return ((passwdenc&0x01) && check_encrypted(md5key, refpass, passwd)) ||
  1762. -		       ((passwdenc&0x02) && check_encrypted(refpass, md5key, passwd));
  1763. -	}
  1764. -}
  1765. -
  1766. -
  1767. -//-----------------------------------------------------
  1768. -// custom timestamp formatting (from eApp)
  1769. -//-----------------------------------------------------
  1770. -const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format)
  1771. -{
  1772. -	size_t len = strftime(str, size, format, localtime(&timestamp));
  1773. -	memset(str + len, '\0', size - len);
  1774. -	return str;
  1775. -}
  1776. -
  1777. -
  1778. -//--------------------------------------------
  1779. -// Test to know if an IP come from LAN or WAN.
  1780. -//--------------------------------------------
  1781. -int lan_subnetcheck(uint32 ip)
  1782. -{
  1783. -	int i;
  1784. -	ARR_FIND( 0, subnet_count, i, (subnet[i].char_ip & subnet[i].mask) == (ip & subnet[i].mask) );
  1785. -	return ( i < subnet_count ) ? subnet[i].char_ip : 0;
  1786. -}
  1787. -
  1788. -//----------------------------------
  1789. -// Reading Lan Support configuration
  1790. -//----------------------------------
  1791. -int login_lan_config_read(const char *lancfgName)
  1792. -{
  1793. -	FILE *fp;
  1794. -	int line_num = 0;
  1795. -	char line[1024], w1[64], w2[64], w3[64], w4[64];
  1796. -
  1797. -	if((fp = fopen(lancfgName, "r")) == NULL) {
  1798. -		ShowWarning("LAN Support configuration file is not found: %s\n", lancfgName);
  1799. -		return 1;
  1800. -	}
  1801. -
  1802. -	while(fgets(line, sizeof(line), fp))
  1803. -	{
  1804. -		line_num++;
  1805. -		if ((line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[1] == '\n')
  1806. -			continue;
  1807. -
  1808. -		if(sscanf(line,"%[^:]: %[^:]:%[^:]:%[^\r\n]", w1, w2, w3, w4) != 4)
  1809. -		{
  1810. -			ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num);
  1811. -			continue;
  1812. -		}
  1813. -
  1814. -		if( strcmpi(w1, "subnet") == 0 )
  1815. -		{
  1816. -			subnet[subnet_count].mask = str2ip(w2);
  1817. -			subnet[subnet_count].char_ip = str2ip(w3);
  1818. -			subnet[subnet_count].map_ip = str2ip(w4);
  1819. -
  1820. -			if( (subnet[subnet_count].char_ip & subnet[subnet_count].mask) != (subnet[subnet_count].map_ip & subnet[subnet_count].mask) )
  1821. -			{
  1822. -				ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4);
  1823. -				continue;
  1824. -			}
  1825. -
  1826. -			subnet_count++;
  1827. -		}
  1828. -	}
  1829. -
  1830. -	if( subnet_count > 1 ) /* only useful if there is more than 1 available */
  1831. -		ShowStatus("Read information about %d subnetworks.\n", subnet_count);
  1832. -
  1833. -	fclose(fp);
  1834. -	return 0;
  1835. -}
  1836. -
  1837. -//-----------------------
  1838. -// Console Command Parser [Wizputer]
  1839. -//-----------------------
  1840. -int parse_console(const char* buf){
  1841. -	char type[64];
  1842. -	char command[64];
  1843. -	int n=0;
  1844. -
  1845. -	if( ( n = sscanf(buf, "%127[^:]:%255[^\n\r]", type, command) ) < 2 ){
  1846. -		if((n = sscanf(buf, "%63[^\n]", type))<1) return -1; //nothing to do no arg
  1847. -	}
  1848. -	if( n != 2 ){ //end string
  1849. -		ShowNotice("Type: '%s'\n",type);
  1850. -		command[0] = '\0';
  1851. -	}
  1852. -	else
  1853. -		ShowNotice("Type of command: '%s' || Command: '%s'\n",type,command);
  1854. -
  1855. -	if( n == 2 ){
  1856. -		if(strcmpi("server", type) == 0 ){
  1857. -			if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){
  1858. -				runflag = 0;
  1859. -			}
  1860. -			else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 )
  1861. -				ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
  1862. -		}
  1863. -		if( strcmpi("create",type) == 0 )
  1864. -		{
  1865. -			char username[NAME_LENGTH], password[NAME_LENGTH], md5password[32+1], sex; //23+1 plaintext 32+1 md5
  1866. -			bool md5 = 0;
  1867. -			if( sscanf(command, "%23s %23s %c", username, password, &sex) < 3 || strnlen(username, sizeof(username)) < 4 || strnlen(password, sizeof(password)) < 1 ){
  1868. -				ShowWarning("Console: Invalid parameters for '%s'. Usage: %s <username> <password> <sex:F/M>\n", type, type);
  1869. -				return 0;
  1870. -			}
  1871. -			if( login_config.use_md5_passwds ){
  1872. -				MD5_String(password,md5password);
  1873. -				md5 = 1;
  1874. -			}
  1875. -			if( mmo_auth_new(username,(md5?md5password:password), TOUPPER(sex), "0.0.0.0") != -1 ){
  1876. -				ShowError("Console: Account creation failed.\n");
  1877. -				return 0;
  1878. -			}
  1879. -			ShowStatus("Console: Account '%s' created successfully.\n", username);
  1880. -		}
  1881. -	}
  1882. -	else if( strcmpi("ers_report", type) == 0 ){
  1883. -		ers_report();
  1884. -	}
  1885. -	else if( strcmpi("help", type) == 0 ){
  1886. -		ShowInfo("Available commands:\n");
  1887. -		ShowInfo("\t server:shutdown => Stops the server.\n");
  1888. -		ShowInfo("\t server:alive => Checks if the server is running.\n");
  1889. -		ShowInfo("\t ers_report => Displays database usage.\n");
  1890. -		ShowInfo("\t create:<username> <password> <sex:M|F> => Creates a new account.\n");
  1891. -	}
  1892. -	else{ // commands with parameters
  1893. -
  1894. -
  1895. -
  1896. -	}
  1897. -
  1898. -	return 0;
  1899. -}
  1900. -
  1901. -
  1902. -//--------------------------------
  1903. -// Packet parsing for char-servers
  1904. -//--------------------------------
  1905. -int parse_fromchar(int fd){
  1906. -	int j, id;
  1907. -	uint32 ipl;
  1908. -	char ip[16];
  1909. -
  1910. -	ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd );
  1911. -	if( id == ARRAYLENGTH(server) ){// not a char server
  1912. -		ShowDebug("parse_fromchar: Disconnecting invalid session #%d (is not a char-server)\n", fd);
  1913. -		set_eof(fd);
  1914. -		do_close(fd);
  1915. -		return 0;
  1916. -	}
  1917. -
  1918. -	if( session[fd]->flag.eof ){
  1919. -		do_close(fd);
  1920. -		server[id].fd = -1;
  1921. -		chrif_on_disconnect(id);
  1922. -		return 0;
  1923. -	}
  1924. -
  1925. -	ipl = server[id].ip;
  1926. -	ip2str(ipl, ip);
  1927. -
  1928. -	while( RFIFOREST(fd) >= 2 ){
  1929. -		uint16 command = RFIFOW(fd,0);
  1930. -
  1931. -		switch( command ){
  1932. -
  1933. -		case 0x2712: // request from char-server to authenticate an account
  1934. -			if( RFIFOREST(fd) < 23 )
  1935. -				return 0;
  1936. -			else{
  1937. -				struct auth_node* node;
  1938. -				int account_id = RFIFOL(fd,2);
  1939. -				uint32 login_id1 = RFIFOL(fd,6);
  1940. -				uint32 login_id2 = RFIFOL(fd,10);
  1941. -				uint8 sex = RFIFOB(fd,14);
  1942. -				//uint32 ip_ = ntohl(RFIFOL(fd,15));
  1943. -				int request_id = RFIFOL(fd,19);
  1944. -				RFIFOSKIP(fd,23);
  1945. -
  1946. -				node = (struct auth_node*)idb_get(auth_db, account_id);
  1947. -				if( runflag == LOGINSERVER_ST_RUNNING &&
  1948. -					node != NULL &&
  1949. -					node->account_id == account_id &&
  1950. -					node->login_id1  == login_id1 &&
  1951. -					node->login_id2  == login_id2 &&
  1952. -					node->sex        == sex_num2str(sex) /*&&
  1953. -					node->ip         == ip_*/ ){// found
  1954. -					//ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip);
  1955. -
  1956. -					// send ack
  1957. -					WFIFOHEAD(fd,25);
  1958. -					WFIFOW(fd,0) = 0x2713;
  1959. -					WFIFOL(fd,2) = account_id;
  1960. -					WFIFOL(fd,6) = login_id1;
  1961. -					WFIFOL(fd,10) = login_id2;
  1962. -					WFIFOB(fd,14) = sex;
  1963. -					WFIFOB(fd,15) = 0;// ok
  1964. -					WFIFOL(fd,16) = request_id;
  1965. -					WFIFOL(fd,20) = node->version;
  1966. -					WFIFOB(fd,24) = node->clienttype;
  1967. -					WFIFOSET(fd,25);
  1968. -
  1969. -					// each auth entry can only be used once
  1970. -					idb_remove(auth_db, account_id);
  1971. -				}else{// authentication not found
  1972. -					ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip);
  1973. -					WFIFOHEAD(fd,25);
  1974. -					WFIFOW(fd,0) = 0x2713;
  1975. -					WFIFOL(fd,2) = account_id;
  1976. -					WFIFOL(fd,6) = login_id1;
  1977. -					WFIFOL(fd,10) = login_id2;
  1978. -					WFIFOB(fd,14) = sex;
  1979. -					WFIFOB(fd,15) = 1;// auth failed
  1980. -					WFIFOL(fd,16) = request_id;
  1981. -					WFIFOL(fd,20) = 0;
  1982. -					WFIFOB(fd,24) = 0;
  1983. -					WFIFOSET(fd,25);
  1984. -				}
  1985. -			}
  1986. -		break;
  1987. -
  1988. -		case 0x2714:
  1989. -			if( RFIFOREST(fd) < 6 )
  1990. -				return 0;
  1991. -			else{
  1992. -				int users = RFIFOL(fd,2);
  1993. -				RFIFOSKIP(fd,6);
  1994. -
  1995. -				// how many users on world? (update)
  1996. -				if( server[id].users != users ){
  1997. -					ShowStatus("set users %s : %d\n", server[id].name, users);
  1998. -
  1999. -					server[id].users = users;
  2000. -				}
  2001. -			}
  2002. -		break;
  2003. -
  2004. -		case 0x2715: // request from char server to change e-email from default "[email protected]"
  2005. -			if (RFIFOREST(fd) < 46)
  2006. -				return 0;
  2007. -			else{
  2008. -				struct mmo_account acc;
  2009. -				char email[40];
  2010. -
  2011. -				int account_id = RFIFOL(fd,2);
  2012. -				safestrncpy(email, (char*)RFIFOP(fd,6), 40); remove_control_chars(email);
  2013. -				RFIFOSKIP(fd,46);
  2014. -
  2015. -				if( e_mail_check(email) == 0 )
  2016. -					ShowNotice("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - e-mail is invalid (account: %d, ip: %s)\n", server[id].name, account_id, ip);
  2017. -				else if( !accounts->load_num(accounts, &acc, account_id) || strcmp(acc.email, "[email protected]") == 0 || acc.email[0] == '\0' )
  2018. -					ShowNotice("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - account doesn't exist or e-mail of account isn't default e-mail (account: %d, ip: %s).\n", server[id].name, account_id, ip);
  2019. -				else{
  2020. -					memcpy(acc.email, email, 40);
  2021. -					ShowNotice("Char-server '%s': Create an e-mail on an account with a default e-mail (account: %d, new e-mail: %s, ip: %s).\n", server[id].name, account_id, email, ip);
  2022. -					// Save
  2023. -					accounts->save(accounts, &acc);
  2024. -				}
  2025. -			}
  2026. -		break;
  2027. -
  2028. -		case 0x2716: // request account data
  2029. -			if( RFIFOREST(fd) < 6 )
  2030. -				return 0;
  2031. -			else{
  2032. -				struct mmo_account acc;
  2033. -				time_t expiration_time = 0;
  2034. -				char email[40] = "";
  2035. -				uint8 char_slots = 0;
  2036. -				int group_id = 0;
  2037. -				char birthdate[10+1] = "";
  2038. -				char pincode[PINCODE_LENGTH+1];
  2039. -				int account_id = RFIFOL(fd,2);
  2040. -
  2041. -				memset(pincode,0,PINCODE_LENGTH+1);
  2042. -
  2043. -				RFIFOSKIP(fd,6);
  2044. -
  2045. -				if( !accounts->load_num(accounts, &acc, account_id) )
  2046. -					ShowNotice("Char-server '%s': account %d NOT found (ip: %s).\n", server[id].name, account_id, ip);
  2047. -				else{
  2048. -					safestrncpy(email, acc.email, sizeof(email));
  2049. -					expiration_time = acc.expiration_time;
  2050. -					group_id = acc.group_id;
  2051. -					char_slots = acc.char_slots;
  2052. -					safestrncpy(birthdate, acc.birthdate, sizeof(birthdate));
  2053. -					safestrncpy(pincode, acc.pincode, sizeof(pincode));
  2054. -				}
  2055. -
  2056. -				WFIFOHEAD(fd,72);
  2057. -				WFIFOW(fd,0) = 0x2717;
  2058. -				WFIFOL(fd,2) = account_id;
  2059. -				safestrncpy((char*)WFIFOP(fd,6), email, 40);
  2060. -				WFIFOL(fd,46) = (uint32)expiration_time;
  2061. -				WFIFOB(fd,50) = (unsigned char)group_id;
  2062. -				WFIFOB(fd,51) = char_slots;
  2063. -				safestrncpy((char*)WFIFOP(fd,52), birthdate, 10+1);
  2064. -				safestrncpy((char*)WFIFOP(fd,63), pincode, 4+1 );
  2065. -				WFIFOL(fd,68) = (uint32)acc.pincode_change;
  2066. -				WFIFOSET(fd,72);
  2067. -			}
  2068. -		break;
  2069. -
  2070. -		case 0x2719: // ping request from charserver
  2071. -			RFIFOSKIP(fd,2);
  2072. -
  2073. -			WFIFOHEAD(fd,2);
  2074. -			WFIFOW(fd,0) = 0x2718;
  2075. -			WFIFOSET(fd,2);
  2076. -		break;
  2077. -
  2078. -		// Map server send information to change an email of an account via char-server
  2079. -		case 0x2722:	// 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
  2080. -			if (RFIFOREST(fd) < 86)
  2081. -				return 0;
  2082. -			else{
  2083. -				struct mmo_account acc;
  2084. -				char actual_email[40];
  2085. -				char new_email[40];
  2086. -
  2087. -				int account_id = RFIFOL(fd,2);
  2088. -				safestrncpy(actual_email, (char*)RFIFOP(fd,6), 40);
  2089. -				safestrncpy(new_email, (char*)RFIFOP(fd,46), 40);
  2090. -				RFIFOSKIP(fd, 86);
  2091. -
  2092. -				if( e_mail_check(actual_email) == 0 )
  2093. -					ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n", server[id].name, account_id, ip);
  2094. -				else if( e_mail_check(new_email) == 0 )
  2095. -					ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n", server[id].name, account_id, ip);
  2096. -				else if( strcmpi(new_email, "[email protected]") == 0 )
  2097. -					ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n", server[id].name, account_id, ip);
  2098. -				else if( !accounts->load_num(accounts, &acc, account_id) )
  2099. -					ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", server[id].name, account_id, ip);
  2100. -				else if( strcmpi(acc.email, actual_email) != 0 )
  2101. -					ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", server[id].name, account_id, acc.userid, acc.email, actual_email, ip);
  2102. -				else{
  2103. -					safestrncpy(acc.email, new_email, 40);
  2104. -					ShowNotice("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n", server[id].name, account_id, acc.userid, new_email, ip);
  2105. -					// Save
  2106. -					accounts->save(accounts, &acc);
  2107. -				}
  2108. -			}
  2109. -		break;
  2110. -
  2111. -		case 0x2724: // Receiving an account state update request from a map-server (relayed via char-server)
  2112. -			if (RFIFOREST(fd) < 10)
  2113. -				return 0;
  2114. -			else{
  2115. -				struct mmo_account acc;
  2116. -
  2117. -				int account_id = RFIFOL(fd,2);
  2118. -				unsigned int state = RFIFOL(fd,6);
  2119. -				RFIFOSKIP(fd,10);
  2120. -
  2121. -				if( !accounts->load_num(accounts, &acc, account_id) )
  2122. -					ShowNotice("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s).\n", server[id].name, account_id, state, ip);
  2123. -				else if( acc.state == state )
  2124. -					ShowNotice("Char-server '%s':  Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s).\n", server[id].name, account_id, state, ip);
  2125. -				else{
  2126. -					ShowNotice("Char-server '%s': Status change (account: %d, new status %d, ip: %s).\n", server[id].name, account_id, state, ip);
  2127. -
  2128. -					acc.state = state;
  2129. -					// Save
  2130. -					accounts->save(accounts, &acc);
  2131. -
  2132. -					// notify other servers
  2133. -					if (state != 0){
  2134. -						uint8 buf[11];
  2135. -						WBUFW(buf,0) = 0x2731;
  2136. -						WBUFL(buf,2) = account_id;
  2137. -						WBUFB(buf,6) = 0; // 0: change of state, 1: ban
  2138. -						WBUFL(buf,7) = state; // status or final date of a banishment
  2139. -						charif_sendallwos(-1, buf, 11);
  2140. -					}
  2141. -				}
  2142. -			}
  2143. -		break;
  2144. -
  2145. -		case 0x2725: // Receiving of map-server via char-server a ban request
  2146. -			if (RFIFOREST(fd) < 18)
  2147. -				return 0;
  2148. -			else{
  2149. -				struct mmo_account acc;
  2150. -
  2151. -				int account_id = RFIFOL(fd,2);
  2152. -				int year = (short)RFIFOW(fd,6);
  2153. -				int month = (short)RFIFOW(fd,8);
  2154. -				int mday = (short)RFIFOW(fd,10);
  2155. -				int hour = (short)RFIFOW(fd,12);
  2156. -				int min = (short)RFIFOW(fd,14);
  2157. -				int sec = (short)RFIFOW(fd,16);
  2158. -				RFIFOSKIP(fd,18);
  2159. -
  2160. -				if( !accounts->load_num(accounts, &acc, account_id) )
  2161. -					ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
  2162. -				else{
  2163. -					time_t timestamp;
  2164. -					struct tm *tmtime;
  2165. -					if (acc.unban_time == 0 || acc.unban_time < time(NULL))
  2166. -						timestamp = time(NULL); // new ban
  2167. -					else
  2168. -						timestamp = acc.unban_time; // add to existing ban
  2169. -					tmtime = localtime(&timestamp);
  2170. -					tmtime->tm_year = tmtime->tm_year + year;
  2171. -					tmtime->tm_mon  = tmtime->tm_mon + month;
  2172. -					tmtime->tm_mday = tmtime->tm_mday + mday;
  2173. -					tmtime->tm_hour = tmtime->tm_hour + hour;
  2174. -					tmtime->tm_min  = tmtime->tm_min + min;
  2175. -					tmtime->tm_sec  = tmtime->tm_sec + sec;
  2176. -					timestamp = mktime(tmtime);
  2177. -					if (timestamp == -1)
  2178. -						ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", server[id].name, account_id, ip);
  2179. -					else if( timestamp <= time(NULL) || timestamp == 0 )
  2180. -						ShowNotice("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", server[id].name, account_id, ip);
  2181. -					else{
  2182. -						uint8 buf[11];
  2183. -						char tmpstr[24];
  2184. -						timestamp2string(tmpstr, sizeof(tmpstr), timestamp, login_config.date_format);
  2185. -						ShowNotice("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s).\n", server[id].name, account_id, timestamp, tmpstr, ip);
  2186. -
  2187. -						acc.unban_time = timestamp;
  2188. -
  2189. -						// Save
  2190. -						accounts->save(accounts, &acc);
  2191. -
  2192. -						WBUFW(buf,0) = 0x2731;
  2193. -						WBUFL(buf,2) = account_id;
  2194. -						WBUFB(buf,6) = 1; // 0: change of status, 1: ban
  2195. -						WBUFL(buf,7) = (uint32)timestamp; // status or final date of a banishment
  2196. -						charif_sendallwos(-1, buf, 11);
  2197. -					}
  2198. -				}
  2199. -			}
  2200. -		break;
  2201. -
  2202. -		case 0x2727: // Change of sex (sex is reversed)
  2203. -			if( RFIFOREST(fd) < 6 )
  2204. -				return 0;
  2205. -			else{
  2206. -				struct mmo_account acc;
  2207. -
  2208. -				int account_id = RFIFOL(fd,2);
  2209. -				RFIFOSKIP(fd,6);
  2210. -
  2211. -				if( !accounts->load_num(accounts, &acc, account_id) )
  2212. -					ShowNotice("Char-server '%s': Error of sex change (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
  2213. -				else if( acc.sex == 'S' )
  2214. -					ShowNotice("Char-server '%s': Error of sex change - account to change is a Server account (account: %d, ip: %s).\n", server[id].name, account_id, ip);
  2215. -				else{
  2216. -					unsigned char buf[7];
  2217. -					char sex = ( acc.sex == 'M' ) ? 'F' : 'M'; //Change gender
  2218. -
  2219. -					ShowNotice("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", server[id].name, account_id, sex, ip);
  2220. -
  2221. -					acc.sex = sex;
  2222. -					// Save
  2223. -					accounts->save(accounts, &acc);
  2224. -
  2225. -					// announce to other servers
  2226. -					WBUFW(buf,0) = 0x2723;
  2227. -					WBUFL(buf,2) = account_id;
  2228. -					WBUFB(buf,6) = sex_str2num(sex);
  2229. -					charif_sendallwos(-1, buf, 7);
  2230. -				}
  2231. -			}
  2232. -		break;
  2233. -
  2234. -		case 0x2728:	// We receive account_reg2 from a char-server, and we send them to other map-servers.
  2235. -			if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
  2236. -				return 0;
  2237. -			else{
  2238. -				struct mmo_account acc;
  2239. -
  2240. -				int account_id = RFIFOL(fd,4);
  2241. -
  2242. -				if( !accounts->load_num(accounts, &acc, account_id) )
  2243. -					ShowStatus("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
  2244. -				else{
  2245. -					int len;
  2246. -					int p;
  2247. -					ShowNotice("char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", server[id].name, account_id, ip);
  2248. -					for( j = 0, p = 13; j < ACCOUNT_REG2_NUM && p < RFIFOW(fd,2); ++j ){
  2249. -						sscanf((char*)RFIFOP(fd,p), "%31c%n", acc.account_reg2[j].str, &len);
  2250. -						acc.account_reg2[j].str[len]='\0';
  2251. -						p +=len+1; //+1 to skip the '\0' between strings.
  2252. -						sscanf((char*)RFIFOP(fd,p), "%255c%n", acc.account_reg2[j].value, &len);
  2253. -						acc.account_reg2[j].value[len]='\0';
  2254. -						p +=len+1;
  2255. -						remove_control_chars(acc.account_reg2[j].str);
  2256. -						remove_control_chars(acc.account_reg2[j].value);
  2257. -					}
  2258. -					acc.account_reg2_num = j;
  2259. -
  2260. -					// Save
  2261. -					accounts->save(accounts, &acc);
  2262. -
  2263. -					// Sending information towards the other char-servers.
  2264. -					RFIFOW(fd,0) = 0x2729;// reusing read buffer
  2265. -					charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2));
  2266. -				}
  2267. -				RFIFOSKIP(fd,RFIFOW(fd,2));
  2268. -			}
  2269. -		break;
  2270. -
  2271. -		case 0x272a:	// Receiving of map-server via char-server an unban request
  2272. -			if( RFIFOREST(fd) < 6 )
  2273. -				return 0;
  2274. -			else{
  2275. -				struct mmo_account acc;
  2276. -
  2277. -				int account_id = RFIFOL(fd,2);
  2278. -				RFIFOSKIP(fd,6);
  2279. -
  2280. -				if( !accounts->load_num(accounts, &acc, account_id) )
  2281. -					ShowNotice("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
  2282. -				else if( acc.unban_time == 0 )
  2283. -					ShowNotice("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n", server[id].name, account_id, ip);
  2284. -				else{
  2285. -					ShowNotice("Char-server '%s': UnBan request (account: %d, ip: %s).\n", server[id].name, account_id, ip);
  2286. -					acc.unban_time = 0;
  2287. -					accounts->save(accounts, &acc);
  2288. -				}
  2289. -			}
  2290. -		break;
  2291. -
  2292. -		case 0x272b:    // Set account_id to online [Wizputer]
  2293. -			if( RFIFOREST(fd) < 6 )
  2294. -				return 0;
  2295. -			add_online_user(id, RFIFOL(fd,2));
  2296. -			RFIFOSKIP(fd,6);
  2297. -		break;
  2298. -
  2299. -		case 0x272c:   // Set account_id to offline [Wizputer]
  2300. -			if( RFIFOREST(fd) < 6 )
  2301. -				return 0;
  2302. -			remove_online_user(RFIFOL(fd,2));
  2303. -			RFIFOSKIP(fd,6);
  2304. -		break;
  2305. -
  2306. -		case 0x272d:	// Receive list of all online accounts. [Skotlex]
  2307. -			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  2308. -				return 0;
  2309. -			else{
  2310. -				struct online_login_data *p;
  2311. -				int aid;
  2312. -				uint32 i, users;
  2313. -				online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char-server offline first
  2314. -				users = RFIFOW(fd,4);
  2315. -				for (i = 0; i < users; i++) {
  2316. -					aid = RFIFOL(fd,6+i*4);
  2317. -					p = idb_ensure(online_db, aid, create_online_user);
  2318. -					p->char_server = id;
  2319. -					if (p->waiting_disconnect != INVALID_TIMER){
  2320. -						delete_timer(p->waiting_disconnect, waiting_disconnect_timer);
  2321. -						p->waiting_disconnect = INVALID_TIMER;
  2322. -					}
  2323. -				}
  2324. -
  2325. -				RFIFOSKIP(fd,RFIFOW(fd,2));
  2326. -			}
  2327. -		break;
  2328. -
  2329. -		case 0x272e: //Request account_reg2 for a character.
  2330. -			if (RFIFOREST(fd) < 10)
  2331. -				return 0;
  2332. -			else{
  2333. -				struct mmo_account acc;
  2334. -				size_t off;
  2335. -
  2336. -				int account_id = RFIFOL(fd,2);
  2337. -				int char_id = RFIFOL(fd,6);
  2338. -				RFIFOSKIP(fd,10);
  2339. -
  2340. -				WFIFOHEAD(fd,ACCOUNT_REG2_NUM*sizeof(struct global_reg));
  2341. -				WFIFOW(fd,0) = 0x2729;
  2342. -				WFIFOL(fd,4) = account_id;
  2343. -				WFIFOL(fd,8) = char_id;
  2344. -				WFIFOB(fd,12) = 1; //Type 1 for Account2 registry
  2345. -
  2346. -				off = 13;
  2347. -				if( accounts->load_num(accounts, &acc, account_id) ){
  2348. -					for( j = 0; j < acc.account_reg2_num; j++ ){
  2349. -						if( acc.account_reg2[j].str[0] != '\0' ){
  2350. -							off += sprintf((char*)WFIFOP(fd,off), "%s", acc.account_reg2[j].str)+1; //We add 1 to consider the '\0' in place.
  2351. -							off += sprintf((char*)WFIFOP(fd,off), "%s", acc.account_reg2[j].value)+1;
  2352. -						}
  2353. -					}
  2354. -				}
  2355. -
  2356. -				WFIFOW(fd,2) = (uint16)off;
  2357. -				WFIFOSET(fd,WFIFOW(fd,2));
  2358. -			}
  2359. -		break;
  2360. -
  2361. -		case 0x2736: // WAN IP update from char-server
  2362. -			if( RFIFOREST(fd) < 6 )
  2363. -				return 0;
  2364. -			server[id].ip = ntohl(RFIFOL(fd,2));
  2365. -			ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(server[id].ip));
  2366. -			RFIFOSKIP(fd,6);
  2367. -		break;
  2368. -
  2369. -		case 0x2737: //Request to set all offline.
  2370. -			ShowInfo("Setting accounts from char-server %d offline.\n", id);
  2371. -			online_db->foreach(online_db, online_db_setoffline, id);
  2372. -			RFIFOSKIP(fd,2);
  2373. -		break;
  2374. -
  2375. -		case 0x2738: //Change PIN Code for a account
  2376. -			if( RFIFOREST(fd) < 11 )
  2377. -				return 0;
  2378. -			else{
  2379. -				struct mmo_account acc;
  2380. -
  2381. -				if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ){
  2382. -					strncpy( acc.pincode, (char*)RFIFOP(fd,6), 5 );
  2383. -					acc.pincode_change = time( NULL );
  2384. -					accounts->save(accounts, &acc);
  2385. -				}
  2386. -
  2387. -				RFIFOSKIP(fd,11);
  2388. -			}
  2389. -		break;
  2390. -
  2391. -		case 0x2739: // PIN Code was entered wrong too often
  2392. -			if( RFIFOREST(fd) < 6 )
  2393. -				return 0;
  2394. -			else{
  2395. -				struct mmo_account acc;
  2396. -
  2397. -				if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ){
  2398. -					struct online_login_data* ld;
  2399. -
  2400. -					ld = (struct online_login_data*)idb_get(online_db,acc.account_id);
  2401. -
  2402. -					if( ld == NULL )
  2403. -						return 0;
  2404. -
  2405. -					login_log( host2ip(acc.last_ip), acc.userid, 100, "PIN Code check failed" );
  2406. -				}
  2407. -
  2408. -				remove_online_user(acc.account_id);
  2409. -
  2410. -				RFIFOSKIP(fd,6);
  2411. -			}
  2412. -		break;
  2413. -
  2414. -		default:
  2415. -			ShowError("parse_fromchar: Unknown packet 0x%x from a char-server! Disconnecting!\n", command);
  2416. -			set_eof(fd);
  2417. -			return 0;
  2418. -		} // switch
  2419. -	} // while
  2420. -
  2421. -	return 0;
  2422. -}
  2423. -
  2424. -
  2425.  //-------------------------------------
  2426.  // Make new account
  2427.  //-------------------------------------
  2428. @@ -964,7 +167,7 @@
  2429.  	//Account Registration Flood Protection by [Kevin]
  2430.  	if( new_reg_tick == 0 )
  2431.  		new_reg_tick = gettick();
  2432. -	if( DIFF_TICK(tick, new_reg_tick) < 0 && num_regs >= allowed_regs ) {
  2433. +	if( DIFF_TICK(tick, new_reg_tick) < 0 && num_regs >= login_config.allowed_regs ) {
  2434.  		ShowNotice("Account registration denied (registration limit exceeded)\n");
  2435.  		return 3;
  2436.  	}
  2437. @@ -1004,7 +207,7 @@
  2438.  
  2439.  	if( DIFF_TICK(tick, new_reg_tick) > 0 ) {// Update the registration check.
  2440.  		num_regs = 0;
  2441. -		new_reg_tick = tick + time_allowed*1000;
  2442. +		new_reg_tick = tick + login_config.time_allowed*1000;
  2443.  	}
  2444.  	++num_regs;
  2445.  
  2446. @@ -1041,8 +244,11 @@
  2447.  	}
  2448.  
  2449.  	//Client Version check
  2450. -	if( login_config.check_client_version && sd->version != login_config.client_version_to_connect )
  2451. +	if( login_config.check_client_version && sd->version != login_config.client_version_to_connect ){
  2452. +		ShowNotice("Invalid version (account: '%s', auth_vers: '%d', received version: '%d', ip: %s)\n",
  2453. +			sd->userid, login_config.client_version_to_connect, sd->version, ip);
  2454.  		return 5;
  2455. +	}
  2456.  
  2457.  	len = strnlen(sd->userid, NAME_LENGTH);
  2458.  
  2459. @@ -1093,15 +299,16 @@
  2460.  
  2461.  	if( login_config.client_hash_check && !isServer ) {
  2462.  		struct client_hash_node *node = login_config.client_hash_nodes;
  2463. +		uint8 anyhash[16];
  2464.  		bool match = false;
  2465.  
  2466.  		if( !sd->has_client_hash ) {
  2467.  			ShowNotice("Client doesn't sent client hash (account: %s, pass: %s, ip: %s)\n", sd->userid, sd->passwd, acc.state, ip);
  2468.  			return 5;
  2469.  		}
  2470. -
  2471. +		memset(anyhash,1,sizeof(anyhash));
  2472.  		while( node ) {
  2473. -			if( node->group_id <= acc.group_id && memcmp(node->hash, sd->client_hash, 16) == 0 ) {
  2474. +			if( node->group_id <= acc.group_id && (memcmp(node->hash,anyhash,16)==0 || memcmp(node->hash, sd->client_hash, 16) == 0 ) ){
  2475.  				match = true;
  2476.  				break;
  2477.  			}
  2478. @@ -1145,466 +352,97 @@
  2479.  	return -1; // account OK
  2480.  }
  2481.  
  2482. -void login_auth_ok(struct login_session_data* sd)
  2483. +//-----------------------------------------------------
  2484. +// encrypted/unencrypted password check (from eApp)
  2485. +//-----------------------------------------------------
  2486. +bool check_encrypted(const char* str1, const char* str2, const char* passwd)
  2487.  {
  2488. -	int fd = sd->fd;
  2489. -	uint32 ip = session[fd]->client_addr;
  2490. +	char tmpstr[64+1], md5str[32+1];
  2491.  
  2492. -	uint8 server_num, n;
  2493. -	uint32 subnet_char_ip;
  2494. -	struct auth_node* node;
  2495. -	int i;
  2496. +	safesnprintf(tmpstr, sizeof(tmpstr), "%s%s", str1, str2);
  2497. +	MD5_String(tmpstr, md5str);
  2498.  
  2499. -	if( runflag != LOGINSERVER_ST_RUNNING )
  2500. -	{
  2501. -		// players can only login while running
  2502. -		WFIFOHEAD(fd,3);
  2503. -		WFIFOW(fd,0) = 0x81;
  2504. -		WFIFOB(fd,2) = 1;// server closed
  2505. -		WFIFOSET(fd,3);
  2506. -		return;
  2507. -	}
  2508. +	return (0==strcmp(passwd, md5str));
  2509. +}
  2510.  
  2511. -	if( login_config.group_id_to_connect >= 0 && sd->group_id != login_config.group_id_to_connect ) {
  2512. -		ShowStatus("Connection refused: the required group id for connection is %d (account: %s, group: %d).\n", login_config.group_id_to_connect, sd->userid, sd->group_id);
  2513. -		WFIFOHEAD(fd,3);
  2514. -		WFIFOW(fd,0) = 0x81;
  2515. -		WFIFOB(fd,2) = 1; // 01 = Server closed
  2516. -		WFIFOSET(fd,3);
  2517. -		return;
  2518. -	} else if( login_config.min_group_id_to_connect >= 0 && login_config.group_id_to_connect == -1 && sd->group_id < login_config.min_group_id_to_connect ) {
  2519. -		ShowStatus("Connection refused: the minium group id required for connection is %d (account: %s, group: %d).\n", login_config.min_group_id_to_connect, sd->userid, sd->group_id);
  2520. -		WFIFOHEAD(fd,3);
  2521. -		WFIFOW(fd,0) = 0x81;
  2522. -		WFIFOB(fd,2) = 1; // 01 = Server closed
  2523. -		WFIFOSET(fd,3);
  2524. -		return;
  2525. -	}
  2526. -
  2527. -	server_num = 0;
  2528. -	for( i = 0; i < ARRAYLENGTH(server); ++i )
  2529. -		if( session_isActive(server[i].fd) )
  2530. -			server_num++;
  2531. -
  2532. -	if( server_num == 0 )
  2533. -	{// if no char-server, don't send void list of servers, just disconnect the player with proper message
  2534. -		ShowStatus("Connection refused: there is no char-server online (account: %s).\n", sd->userid);
  2535. -		WFIFOHEAD(fd,3);
  2536. -		WFIFOW(fd,0) = 0x81;
  2537. -		WFIFOB(fd,2) = 1; // 01 = Server closed
  2538. -		WFIFOSET(fd,3);
  2539. -		return;
  2540. -	}
  2541. -
  2542. +bool check_password(const char* md5key, int passwdenc, const char* passwd, const char* refpass)
  2543. +{
  2544. +	if(passwdenc == 0)
  2545.  	{
  2546. -		struct online_login_data* data = (struct online_login_data*)idb_get(online_db, sd->account_id);
  2547. -		if( data )
  2548. -		{// account is already marked as online!
  2549. -			if( data->char_server > -1 )
  2550. -			{// Request char servers to kick this account out. [Skotlex]
  2551. -				uint8 buf[6];
  2552. -				ShowNotice("User '%s' is already online - Rejected.\n", sd->userid);
  2553. -				WBUFW(buf,0) = 0x2734;
  2554. -				WBUFL(buf,2) = sd->account_id;
  2555. -				charif_sendallwos(-1, buf, 6);
  2556. -				if( data->waiting_disconnect == INVALID_TIMER )
  2557. -					data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0);
  2558. -
  2559. -				WFIFOHEAD(fd,3);
  2560. -				WFIFOW(fd,0) = 0x81;
  2561. -				WFIFOB(fd,2) = 8; // 08 = Server still recognizes your last login
  2562. -				WFIFOSET(fd,3);
  2563. -				return;
  2564. -			}
  2565. -			else
  2566. -			if( data->char_server == -1 )
  2567. -			{// client has authed but did not access char-server yet
  2568. -				// wipe previous session
  2569. -				idb_remove(auth_db, sd->account_id);
  2570. -				remove_online_user(sd->account_id);
  2571. -				data = NULL;
  2572. -			}
  2573. -		}
  2574. +		return (0==strcmp(passwd, refpass));
  2575.  	}
  2576. -
  2577. -	login_log(ip, sd->userid, 100, "login ok");
  2578. -	ShowStatus("Connection of the account '%s' accepted.\n", sd->userid);
  2579. -
  2580. -	WFIFOHEAD(fd,47+32*server_num);
  2581. -	WFIFOW(fd,0) = 0x69;
  2582. -	WFIFOW(fd,2) = 47+32*server_num;
  2583. -	WFIFOL(fd,4) = sd->login_id1;
  2584. -	WFIFOL(fd,8) = sd->account_id;
  2585. -	WFIFOL(fd,12) = sd->login_id2;
  2586. -	WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used)
  2587. -	//memcpy(WFIFOP(fd,20), sd->lastlogin, 24); // in old version, that was for name (not more used)
  2588. -	memset(WFIFOP(fd,20), 0, 24);
  2589. -	WFIFOW(fd,44) = 0; // unknown
  2590. -	WFIFOB(fd,46) = sex_str2num(sd->sex);
  2591. -	for( i = 0, n = 0; i < ARRAYLENGTH(server); ++i )
  2592. +	else
  2593.  	{
  2594. -		if( !session_isValid(server[i].fd) )
  2595. -			continue;
  2596. +		// password mode set to 1 -> md5(md5key, refpass) enable with <passwordencrypt></passwordencrypt>
  2597. +		// password mode set to 2 -> md5(refpass, md5key) enable with <passwordencrypt2></passwordencrypt2>
  2598.  
  2599. -		subnet_char_ip = lan_subnetcheck(ip); // Advanced subnet check [LuzZza]
  2600. -		WFIFOL(fd,47+n*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip);
  2601. -		WFIFOW(fd,47+n*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
  2602. -		memcpy(WFIFOP(fd,47+n*32+6), server[i].name, 20);
  2603. -		WFIFOW(fd,47+n*32+26) = server[i].users;
  2604. -		WFIFOW(fd,47+n*32+28) = server[i].type;
  2605. -		WFIFOW(fd,47+n*32+30) = server[i].new_;
  2606. -		n++;
  2607. +		return ((passwdenc&0x01) && check_encrypted(md5key, refpass, passwd)) ||
  2608. +		       ((passwdenc&0x02) && check_encrypted(refpass, md5key, passwd));
  2609.  	}
  2610. -	WFIFOSET(fd,47+32*server_num);
  2611. -
  2612. -	// create temporary auth entry
  2613. -	CREATE(node, struct auth_node, 1);
  2614. -	node->account_id = sd->account_id;
  2615. -	node->login_id1 = sd->login_id1;
  2616. -	node->login_id2 = sd->login_id2;
  2617. -	node->sex = sd->sex;
  2618. -	node->ip = ip;
  2619. -	node->version = sd->version;
  2620. -	node->clienttype = sd->clienttype;
  2621. -	idb_put(auth_db, sd->account_id, node);
  2622. -
  2623. -	{
  2624. -		struct online_login_data* data;
  2625. -
  2626. -		// mark client as 'online'
  2627. -		data = add_online_user(-1, sd->account_id);
  2628. -
  2629. -		// schedule deletion of this node
  2630. -		data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0);
  2631. -	}
  2632.  }
  2633.  
  2634. -/* Log the result of a failed connection attempt by sd
  2635. - * result: nb (msg define in conf)
  2636. -    0 = Unregistered ID
  2637. -    1 = Incorrect Password
  2638. -    2 = This ID is expired
  2639. -    3 = Rejected from Server
  2640. -    4 = You have been blocked by the GM Team
  2641. -    5 = Your Game's EXE file is not the latest version
  2642. -    6 = Your are Prohibited to log in until %s
  2643. -    7 = Server is jammed due to over populated
  2644. -    8 = No more accounts may be connected from this company
  2645. -    9 = MSI_REFUSE_BAN_BY_DBA
  2646. -    10 = MSI_REFUSE_EMAIL_NOT_CONFIRMED
  2647. -    11 = MSI_REFUSE_BAN_BY_GM
  2648. -    12 = MSI_REFUSE_TEMP_BAN_FOR_DBWORK
  2649. -    13 = MSI_REFUSE_SELF_LOCK
  2650. -    14 = MSI_REFUSE_NOT_PERMITTED_GROUP
  2651. -    15 = MSI_REFUSE_NOT_PERMITTED_GROUP
  2652. -    99 = This ID has been totally erased
  2653. -    100 = Login information remains at %s
  2654. -    101 = Account has been locked for a hacking investigation. Please contact the GM Team for more information
  2655. -    102 = This account has been temporarily prohibited from login due to a bug-related investigation
  2656. -    103 = This character is being deleted. Login is temporarily unavailable for the time being
  2657. -    104 = This character is being deleted. Login is temporarily unavailable for the time being
  2658. -     default = Unknown Error.
  2659. - */
  2660. -void login_auth_failed(struct login_session_data* sd, int result)
  2661. +//--------------------------------------------
  2662. +// Test to know if an IP come from LAN or WAN.
  2663. +//--------------------------------------------
  2664. +int lan_subnetcheck(uint32 ip)
  2665.  {
  2666. -	int fd = sd->fd;
  2667. -	uint32 ip = session[fd]->client_addr;
  2668. -
  2669. -	if (login_config.log_login)
  2670. -	{
  2671. -		if(result >= 0 && result <= 15)
  2672. -		    login_log(ip, sd->userid, result, msg_txt(result));
  2673. -		else if(result >= 99 && result <= 104)
  2674. -		    login_log(ip, sd->userid, result, msg_txt(result-83)); //-83 offset
  2675. -		else
  2676. -		    login_log(ip, sd->userid, result, msg_txt(22)); //unknow error
  2677. -	}
  2678. -
  2679. -	if( result == 1 && login_config.dynamic_pass_failure_ban )
  2680. -		ipban_log(ip); // log failed password attempt
  2681. -
  2682. -#if PACKETVER >= 20120000 /* not sure when this started */
  2683. -	WFIFOHEAD(fd,26);
  2684. -	WFIFOW(fd,0) = 0x83e;
  2685. -	WFIFOL(fd,2) = result;
  2686. -	if( result != 6 )
  2687. -		memset(WFIFOP(fd,6), '\0', 20);
  2688. -	else { // 6 = Your are Prohibited to log in until %s
  2689. -		struct mmo_account acc;
  2690. -		time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
  2691. -		timestamp2string((char*)WFIFOP(fd,6), 20, unban_time, login_config.date_format);
  2692. -	}
  2693. -	WFIFOSET(fd,26);
  2694. -#else
  2695. -	WFIFOHEAD(fd,23);
  2696. -	WFIFOW(fd,0) = 0x6a;
  2697. -	WFIFOB(fd,2) = (uint8)result;
  2698. -	if( result != 6 )
  2699. -		memset(WFIFOP(fd,3), '\0', 20);
  2700. -	else { // 6 = Your are Prohibited to log in until %s
  2701. -		struct mmo_account acc;
  2702. -		time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
  2703. -		timestamp2string((char*)WFIFOP(fd,3), 20, unban_time, login_config.date_format);
  2704. -	}
  2705. -	WFIFOSET(fd,23);
  2706. -#endif
  2707. +	int i;
  2708. +	ARR_FIND( 0, subnet_count, i, (subnet[i].char_ip & subnet[i].mask) == (ip & subnet[i].mask) );
  2709. +	return ( i < subnet_count ) ? subnet[i].char_ip : 0;
  2710.  }
  2711.  
  2712. -
  2713. -//----------------------------------------------------------------------------------------
  2714. -// Default packet parsing (normal players or char-server connection requests)
  2715. -//----------------------------------------------------------------------------------------
  2716. -int parse_login(int fd)
  2717. +//----------------------------------
  2718. +// Reading Lan Support configuration
  2719. +//----------------------------------
  2720. +int login_lan_config_read(const char *lancfgName)
  2721.  {
  2722. -	struct login_session_data* sd = (struct login_session_data*)session[fd]->session_data;
  2723. -	int result;
  2724. +	FILE *fp;
  2725. +	int line_num = 0;
  2726. +	char line[1024], w1[64], w2[64], w3[64], w4[64];
  2727.  
  2728. -	char ip[16];
  2729. -	uint32 ipl = session[fd]->client_addr;
  2730. -	ip2str(ipl, ip);
  2731. -
  2732. -	if( session[fd]->flag.eof )
  2733. -	{
  2734. -		ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", ip);
  2735. -		do_close(fd);
  2736. -		return 0;
  2737. +	if((fp = fopen(lancfgName, "r")) == NULL) {
  2738. +		ShowWarning("LAN Support configuration file is not found: %s\n", lancfgName);
  2739. +		return 1;
  2740.  	}
  2741.  
  2742. -	if( sd == NULL )
  2743. +	while(fgets(line, sizeof(line), fp))
  2744.  	{
  2745. -		// Perform ip-ban check
  2746. -		if( login_config.ipban && ipban_check(ipl) )
  2747. -		{
  2748. -			ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip);
  2749. -			login_log(ipl, "unknown", -3, "ip banned");
  2750. -			WFIFOHEAD(fd,23);
  2751. -			WFIFOW(fd,0) = 0x6a;
  2752. -			WFIFOB(fd,2) = 3; // 3 = Rejected from Server
  2753. -			WFIFOSET(fd,23);
  2754. -			set_eof(fd);
  2755. -			return 0;
  2756. -		}
  2757. +		line_num++;
  2758. +		if ((line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[1] == '\n')
  2759. +			continue;
  2760.  
  2761. -		// create a session for this new connection
  2762. -		CREATE(session[fd]->session_data, struct login_session_data, 1);
  2763. -		sd = (struct login_session_data*)session[fd]->session_data;
  2764. -		sd->fd = fd;
  2765. -	}
  2766. -
  2767. -	while( RFIFOREST(fd) >= 2 )
  2768. -	{
  2769. -		uint16 command = RFIFOW(fd,0);
  2770. -
  2771. -		switch( command )
  2772. +		if(sscanf(line,"%[^:]: %[^:]:%[^:]:%[^\r\n]", w1, w2, w3, w4) != 4)
  2773.  		{
  2774. -
  2775. -		case 0x0200:		// New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
  2776. -			if (RFIFOREST(fd) < 26)
  2777. -				return 0;
  2778. -			RFIFOSKIP(fd,26);
  2779. -		break;
  2780. -
  2781. -		// client md5 hash (binary)
  2782. -		case 0x0204: // S 0204 <md5 hash>.16B (kRO 2004-05-31aSakexe langtype 0 and 6)
  2783. -			if (RFIFOREST(fd) < 18)
  2784. -				return 0;
  2785. -
  2786. -			sd->has_client_hash = 1;
  2787. -			memcpy(sd->client_hash, RFIFOP(fd, 2), 16);
  2788. -
  2789. -			RFIFOSKIP(fd,18);
  2790. -		break;
  2791. -
  2792. -		// request client login (raw password)
  2793. -		case 0x0064: // S 0064 <version>.L <username>.24B <password>.24B <clienttype>.B
  2794. -		case 0x0277: // S 0277 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B
  2795. -		case 0x02b0: // S 02b0 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B <g_isGravityID>.B
  2796. -		// request client login (md5-hashed password)
  2797. -		case 0x01dd: // S 01dd <version>.L <username>.24B <password hash>.16B <clienttype>.B
  2798. -		case 0x01fa: // S 01fa <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.B(index of the connection in the clientinfo file (+10 if the command-line contains "pc"))
  2799. -		case 0x027c: // S 027c <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.13B(junk)
  2800. -		case 0x0825: // S 0825 <packetsize>.W <version>.L <clienttype>.B <userid>.24B <password>.27B <mac>.17B <ip>.15B <token>.(packetsize - 0x5C)B
  2801. -		{
  2802. -			size_t packet_len = RFIFOREST(fd);
  2803. -
  2804. -			if( (command == 0x0064 && packet_len < 55)
  2805. -			||  (command == 0x0277 && packet_len < 84)
  2806. -			||  (command == 0x02b0 && packet_len < 85)
  2807. -			||  (command == 0x01dd && packet_len < 47)
  2808. -			||  (command == 0x01fa && packet_len < 48)
  2809. -			||  (command == 0x027c && packet_len < 60)
  2810. -			||  (command == 0x0825 && (packet_len < 4 || packet_len < RFIFOW(fd, 2))) )
  2811. -				return 0;
  2812. +			ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num);
  2813. +			continue;
  2814.  		}
  2815. -		{
  2816. -			uint32 version;
  2817. -			char username[NAME_LENGTH];
  2818. -			char password[NAME_LENGTH];
  2819. -			unsigned char passhash[16];
  2820. -			uint8 clienttype;
  2821. -			bool israwpass = (command==0x0064 || command==0x0277 || command==0x02b0 || command == 0x0825);
  2822.  
  2823. -			// Shinryo: For the time being, just use token as password.
  2824. -			if(command == 0x0825)
  2825. -			{
  2826. -				char *accname = (char *)RFIFOP(fd, 9);
  2827. -				char *token = (char *)RFIFOP(fd, 0x5C);
  2828. -				size_t uAccLen = strlen(accname);
  2829. -				size_t uTokenLen = RFIFOREST(fd) - 0x5C;
  2830. -
  2831. -				version = RFIFOL(fd,4);
  2832. -
  2833. -				if(uAccLen > NAME_LENGTH - 1 || uAccLen <= 0 || uTokenLen > NAME_LENGTH - 1  || uTokenLen <= 0)
  2834. -				{
  2835. -					login_auth_failed(sd, 3);
  2836. -					return 0;
  2837. -				}
  2838. -
  2839. -				safestrncpy(username, accname, uAccLen + 1);
  2840. -				safestrncpy(password, token, uTokenLen + 1);
  2841. -				clienttype = RFIFOB(fd, 8);
  2842. -			}
  2843. -			else
  2844. -			{
  2845. -				version = RFIFOL(fd,2);
  2846. -				safestrncpy(username, (const char*)RFIFOP(fd,6), NAME_LENGTH);
  2847. -				if( israwpass )
  2848. -				{
  2849. -					safestrncpy(password, (const char*)RFIFOP(fd,30), NAME_LENGTH);
  2850. -					clienttype = RFIFOB(fd,54);
  2851. -				}
  2852. -				else
  2853. -				{
  2854. -					memcpy(passhash, RFIFOP(fd,30), 16);
  2855. -					clienttype = RFIFOB(fd,46);
  2856. -				}
  2857. -			}
  2858. -			RFIFOSKIP(fd,RFIFOREST(fd)); // assume no other packet was sent
  2859. -
  2860. -			sd->clienttype = clienttype;
  2861. -			sd->version = version;
  2862. -			safestrncpy(sd->userid, username, NAME_LENGTH);
  2863. -			if( israwpass )
  2864. -			{
  2865. -				ShowStatus("Request for connection of %s (ip: %s) version=%d\n", sd->userid, ip,sd->version);
  2866. -				safestrncpy(sd->passwd, password, NAME_LENGTH);
  2867. -				if( login_config.use_md5_passwds )
  2868. -					MD5_String(sd->passwd, sd->passwd);
  2869. -				sd->passwdenc = 0;
  2870. -			}
  2871. -			else
  2872. -			{
  2873. -				ShowStatus("Request for connection (passwdenc mode) of %s (ip: %s) version=%d\n", sd->userid, ip,sd->version);
  2874. -				bin2hex(sd->passwd, passhash, 16); // raw binary data here!
  2875. -				sd->passwdenc = PASSWORDENC;
  2876. -			}
  2877. -
  2878. -			if( sd->passwdenc != 0 && login_config.use_md5_passwds )
  2879. -			{
  2880. -				login_auth_failed(sd, 3); // send "rejected from server"
  2881. -				return 0;
  2882. -			}
  2883. -
  2884. -			result = mmo_auth(sd, false);
  2885. -
  2886. -			if( result == -1 )
  2887. -				login_auth_ok(sd);
  2888. -			else
  2889. -				login_auth_failed(sd, result);
  2890. -		}
  2891. -		break;
  2892. -
  2893. -		case 0x01db:	// Sending request of the coding key
  2894. -			RFIFOSKIP(fd,2);
  2895. +		if( strcmpi(w1, "subnet") == 0 )
  2896.  		{
  2897. -			memset(sd->md5key, '\0', sizeof(sd->md5key));
  2898. -			sd->md5keylen = (uint16)(12 + rnd() % 4);
  2899. -			MD5_Salt(sd->md5keylen, sd->md5key);
  2900. +			subnet[subnet_count].mask = str2ip(w2);
  2901. +			subnet[subnet_count].char_ip = str2ip(w3);
  2902. +			subnet[subnet_count].map_ip = str2ip(w4);
  2903.  
  2904. -			WFIFOHEAD(fd,4 + sd->md5keylen);
  2905. -			WFIFOW(fd,0) = 0x01dc;
  2906. -			WFIFOW(fd,2) = 4 + sd->md5keylen;
  2907. -			memcpy(WFIFOP(fd,4), sd->md5key, sd->md5keylen);
  2908. -			WFIFOSET(fd,WFIFOW(fd,2));
  2909. -		}
  2910. -		break;
  2911. -
  2912. -		case 0x2710:	// Connection request of a char-server
  2913. -			if (RFIFOREST(fd) < 86)
  2914. -				return 0;
  2915. -		{
  2916. -			char server_name[20];
  2917. -			char message[256];
  2918. -			uint32 server_ip;
  2919. -			uint16 server_port;
  2920. -			uint16 type;
  2921. -			uint16 new_;
  2922. -
  2923. -			safestrncpy(sd->userid, (char*)RFIFOP(fd,2), NAME_LENGTH);
  2924. -			safestrncpy(sd->passwd, (char*)RFIFOP(fd,26), NAME_LENGTH);
  2925. -			if( login_config.use_md5_passwds )
  2926. -				MD5_String(sd->passwd, sd->passwd);
  2927. -			sd->passwdenc = 0;
  2928. -			sd->version = login_config.client_version_to_connect; // hack to skip version check
  2929. -			server_ip = ntohl(RFIFOL(fd,54));
  2930. -			server_port = ntohs(RFIFOW(fd,58));
  2931. -			safestrncpy(server_name, (char*)RFIFOP(fd,60), 20);
  2932. -			type = RFIFOW(fd,82);
  2933. -			new_ = RFIFOW(fd,84);
  2934. -			RFIFOSKIP(fd,86);
  2935. -
  2936. -			ShowInfo("Connection request of the char-server '%s' @ %u.%u.%u.%u:%u (account: '%s', pass: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, sd->userid, sd->passwd, ip);
  2937. -			sprintf(message, "charserver - %s@%u.%u.%u.%u:%u", server_name, CONVIP(server_ip), server_port);
  2938. -			login_log(session[fd]->client_addr, sd->userid, 100, message);
  2939. -
  2940. -			result = mmo_auth(sd, true);
  2941. -			if( runflag == LOGINSERVER_ST_RUNNING &&
  2942. -				result == -1 &&
  2943. -				sd->sex == 'S' &&
  2944. -				sd->account_id >= 0 && sd->account_id < ARRAYLENGTH(server) &&
  2945. -				!session_isValid(server[sd->account_id].fd) )
  2946. +			if( (subnet[subnet_count].char_ip & subnet[subnet_count].mask) != (subnet[subnet_count].map_ip & subnet[subnet_count].mask) )
  2947.  			{
  2948. -				ShowStatus("Connection of the char-server '%s' accepted.\n", server_name);
  2949. -				safestrncpy(server[sd->account_id].name, server_name, sizeof(server[sd->account_id].name));
  2950. -				server[sd->account_id].fd = fd;
  2951. -				server[sd->account_id].ip = server_ip;
  2952. -				server[sd->account_id].port = server_port;
  2953. -				server[sd->account_id].users = 0;
  2954. -				server[sd->account_id].type = type;
  2955. -				server[sd->account_id].new_ = new_;
  2956. -
  2957. -				session[fd]->func_parse = parse_fromchar;
  2958. -				session[fd]->flag.server = 1;
  2959. -				realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
  2960. -
  2961. -				// send connection success
  2962. -				WFIFOHEAD(fd,3);
  2963. -				WFIFOW(fd,0) = 0x2711;
  2964. -				WFIFOB(fd,2) = 0;
  2965. -				WFIFOSET(fd,3);
  2966. +				ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4);
  2967. +				continue;
  2968.  			}
  2969. -			else
  2970. -			{
  2971. -				ShowNotice("Connection of the char-server '%s' REFUSED.\n", server_name);
  2972. -				WFIFOHEAD(fd,3);
  2973. -				WFIFOW(fd,0) = 0x2711;
  2974. -				WFIFOB(fd,2) = 3;
  2975. -				WFIFOSET(fd,3);
  2976. -			}
  2977. -		}
  2978. -		return 0; // processing will continue elsewhere
  2979.  
  2980. -		default:
  2981. -			ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command);
  2982. -			set_eof(fd);
  2983. -			return 0;
  2984. +			subnet_count++;
  2985.  		}
  2986.  	}
  2987.  
  2988. +	if( subnet_count > 1 ) /* only useful if there is more than 1 available */
  2989. +		ShowStatus("Read information about %d subnetworks.\n", subnet_count);
  2990. +
  2991. +	fclose(fp);
  2992.  	return 0;
  2993.  }
  2994.  
  2995. -
  2996. +/*
  2997. + * Init default configuration
  2998. + */
  2999.  void login_set_defaults()
  3000.  {
  3001.  	login_config.login_ip = INADDR_ANY;
  3002. @@ -1620,7 +458,8 @@
  3003.  	login_config.group_id_to_connect = -1;
  3004.  	login_config.min_group_id_to_connect = -1;
  3005.  	login_config.check_client_version = false;
  3006. -	login_config.client_version_to_connect = 20;
  3007. +	login_config.client_version_to_connect = date2version(PACKETVER); //20120410 => 30
  3008. +	ShowInfo("loginconfig: client_version_to_connect = %d\n",login_config.client_version_to_connect);
  3009.  
  3010.  	login_config.ipban = true;
  3011.  	login_config.dynamic_pass_failure_ban = true;
  3012. @@ -1630,9 +469,16 @@
  3013.  	login_config.use_dnsbl = false;
  3014.  	safestrncpy(login_config.dnsbl_servs, "", sizeof(login_config.dnsbl_servs));
  3015.  	safestrncpy(login_config.account_engine, "auto", sizeof(login_config.account_engine));
  3016. +	login_config.allowed_regs = true;
  3017. +	login_config.time_allowed = 10; //in second
  3018.  
  3019.  	login_config.client_hash_check = 0;
  3020.  	login_config.client_hash_nodes = NULL;
  3021. +
  3022. +	//other default conf
  3023. +	login_config.loginconf_name = "conf/login_athena.conf";
  3024. +	login_config.lanconf_name = "conf/subnet_athena.conf";
  3025. +	login_config.msgconf_name = "conf/msg_conf/login_msg.conf";
  3026.  }
  3027.  
  3028.  //-----------------------------------
  3029. @@ -1696,9 +542,9 @@
  3030.  		else if(!strcmpi(w1, "console"))
  3031.  			login_config.console = (bool)config_switch(w2);
  3032.  		else if(!strcmpi(w1, "allowed_regs")) //account flood protection system
  3033. -			allowed_regs = atoi(w2);
  3034. +			login_config.allowed_regs = atoi(w2);
  3035.  		else if(!strcmpi(w1, "time_allowed"))
  3036. -			time_allowed = atoi(w2);
  3037. +			login_config.time_allowed = atoi(w2);
  3038.  		else if(!strcmpi(w1, "use_dnsbl"))
  3039.  			login_config.use_dnsbl = (bool)config_switch(w2);
  3040.  		else if(!strcmpi(w1, "dnsbl_servers"))
  3041. @@ -1718,15 +564,20 @@
  3042.  				int i;
  3043.  				CREATE(nnode, struct client_hash_node, 1);
  3044.  
  3045. -				for (i = 0; i < 32; i += 2) {
  3046. -					char buf[3];
  3047. -					unsigned int byte;
  3048. +				if(!strcmpi(md5,"any")){
  3049. +					memset(nnode->hash,1,sizeof(nnode->hash));
  3050. +				}
  3051. +				else {
  3052. +					for (i = 0; i < 32; i += 2) {
  3053. +						char buf[3];
  3054. +						unsigned int byte;
  3055.  
  3056. -					memcpy(buf, &md5[i], 2);
  3057. -					buf[2] = 0;
  3058. +						memcpy(buf, &md5[i], 2);
  3059. +						buf[2] = 0;
  3060.  
  3061. -					sscanf(buf, "%x", &byte);
  3062. -					nnode->hash[i / 2] = (uint8)(byte & 0xFF);
  3063. +						sscanf(buf, "%x", &byte);
  3064. +						nnode->hash[i / 2] = (uint8)(byte & 0xFF);
  3065. +					}
  3066.  				}
  3067.  
  3068.  				nnode->group_id = group;
  3069. @@ -1818,8 +669,7 @@
  3070.  	online_db->destroy(online_db, NULL);
  3071.  	auth_db->destroy(auth_db, NULL);
  3072.  
  3073. -	for( i = 0; i < ARRAYLENGTH(server); ++i )
  3074. -		chrif_server_destroy(i);
  3075. +	do_final_loginchrif();
  3076.  
  3077.  	if( login_fd != -1 )
  3078.  	{
  3079. @@ -1849,12 +699,10 @@
  3080.  {
  3081.  	if( runflag != LOGINSERVER_ST_SHUTDOWN )
  3082.  	{
  3083. -		int id;
  3084.  		runflag = LOGINSERVER_ST_SHUTDOWN;
  3085.  		ShowStatus("Shutting down...\n");
  3086.  		// TODO proper shutdown procedure; kick all characters, wait for acks, ...  [FlavioJS]
  3087. -		for( id = 0; id < ARRAYLENGTH(server); ++id )
  3088. -			chrif_server_reset(id);
  3089. +		do_shutdown_loginchrif();
  3090.  		flush_fifos();
  3091.  		runflag = CORE_ST_STOP;
  3092.  	}
  3093. @@ -1874,21 +722,16 @@
  3094.  
  3095.  	// read login-server configuration
  3096.  	login_set_defaults();
  3097. +	cnsl_get_options(argc,argv);
  3098.  
  3099. -	LOGIN_CONF_NAME = "conf/login_athena.conf";
  3100. -	LAN_CONF_NAME = "conf/subnet_athena.conf";
  3101. -	MSG_CONF_NAME_EN = "conf/msg_conf/login_msg.conf";
  3102. +	login_config_read(login_config.loginconf_name);
  3103. +	msg_config_read(login_config.msgconf_name);
  3104. +	login_lan_config_read(login_config.lanconf_name);
  3105. +	//end config
  3106.  
  3107. -	cli_get_options(argc,argv);
  3108. -
  3109. -	msg_config_read(MSG_CONF_NAME_EN);
  3110. -	login_config_read(LOGIN_CONF_NAME);
  3111. -	login_lan_config_read(LAN_CONF_NAME);
  3112. -
  3113.  	rnd_init();
  3114.  
  3115. -	for( i = 0; i < ARRAYLENGTH(server); ++i )
  3116. -		chrif_server_init(i);
  3117. +	do_init_loginchrif();
  3118.  
  3119.  	// initialize logging
  3120.  	if( login_config.log_login )
  3121. @@ -1911,12 +754,6 @@
  3122.  	add_timer_func_list(online_data_cleanup, "online_data_cleanup");
  3123.  	add_timer_interval(gettick() + 600*1000, online_data_cleanup, 0, 0, 600*1000);
  3124.  
  3125. -	// add timer to detect ip address change and perform update
  3126. -	if (login_config.ip_sync_interval) {
  3127. -		add_timer_func_list(sync_ip_addresses, "sync_ip_addresses");
  3128. -		add_timer_interval(gettick() + login_config.ip_sync_interval, sync_ip_addresses, 0, 0, login_config.ip_sync_interval);
  3129. -	}
  3130. -
  3131.  	// Account database init
  3132.  	accounts = get_account_engine();
  3133.  	if( accounts == NULL ) {
  3134. @@ -1941,14 +778,11 @@
  3135.  		runflag = LOGINSERVER_ST_RUNNING;
  3136.  	}
  3137.  
  3138. +	do_init_logincnslif();
  3139. +
  3140.  	ShowStatus("The login-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_port);
  3141.  	login_log(0, "login server", 100, "login server started");
  3142.  
  3143. -	if( login_config.console ) {
  3144. -		add_timer_func_list(parse_console_timer, "parse_console_timer");
  3145. -		add_timer_interval(gettick()+1000, parse_console_timer, 0, 0, 1000); //start in 1s each 1sec
  3146. -	}
  3147. -
  3148.  	return 0;
  3149.  }
  3150.  
  3151. @@ -1961,21 +795,3 @@
  3152.  void login_do_final_msg(void){
  3153.  	_do_final_msg(LOGIN_MAX_MSG,msg_table);
  3154.  }
  3155. -
  3156. -/*======================================================
  3157. - * Login-Server help option info
  3158. - *------------------------------------------------------*/
  3159. -void display_helpscreen(bool do_exit)
  3160. -{
  3161. -	ShowInfo("Usage: %s [options]\n", SERVER_NAME);
  3162. -	ShowInfo("\n");
  3163. -	ShowInfo("Options:\n");
  3164. -	ShowInfo("  -?, -h [--help]\t\tDisplays this help screen.\n");
  3165. -	ShowInfo("  -v [--version]\t\tDisplays the server's version.\n");
  3166. -	ShowInfo("  --run-once\t\t\tCloses server after loading (testing).\n");
  3167. -	ShowInfo("  --login-config <file>\t\tAlternative login-server configuration.\n");
  3168. -	ShowInfo("  --lan-config <file>\t\tAlternative lag configuration.\n");
  3169. -	ShowInfo("  --msg-config <file>\t\tAlternative message configuration.\n");
  3170. -	if( do_exit )
  3171. -		exit(EXIT_SUCCESS);
  3172. -}
  3173. Index: src/map/pc.h
  3174. ===================================================================
  3175. --- src/map/pc.h	(revision 17373)
  3176. +++ src/map/pc.h	(working copy)
  3177. @@ -185,6 +185,7 @@
  3178.  		unsigned int bonus_coma : 1;
  3179.  	} special_state;
  3180.  	int login_id1, login_id2;
  3181. +	int version;
  3182.  	unsigned short class_;	//This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex]
  3183.  	int group_id, group_pos, group_level;
  3184.  	unsigned int permissions;/* group permissions */
  3185. Index: src/map/chrif.c
  3186. ===================================================================
  3187. --- src/map/chrif.c	(revision 17373)
  3188. +++ src/map/chrif.c	(working copy)
  3189. @@ -722,13 +722,14 @@
  3190.  
  3191.  	chrif_check(-1);
  3192.  
  3193. -	WFIFOHEAD(char_fd,18);
  3194. +	WFIFOHEAD(char_fd,19);
  3195.  	WFIFOW(char_fd, 0) = 0x2b02;
  3196.  	WFIFOL(char_fd, 2) = sd->bl.id;
  3197.  	WFIFOL(char_fd, 6) = sd->login_id1;
  3198.  	WFIFOL(char_fd,10) = sd->login_id2;
  3199.  	WFIFOL(char_fd,14) = htonl(s_ip);
  3200. -	WFIFOSET(char_fd,18);
  3201. +	WFIFOB(char_fd,18) = sd->version;
  3202. +	WFIFOSET(char_fd,19);
  3203.  
  3204.  	return 0;
  3205.  }
  3206. Index: src/char/int_storage.c
  3207. ===================================================================
  3208. --- src/char/int_storage.c	(revision 17373)
  3209. +++ src/char/int_storage.c	(working copy)
  3210. @@ -41,7 +41,7 @@
  3211.  	StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`bound`,`unique_id`");
  3212.  	for( j = 0; j < MAX_SLOTS; ++j )
  3213.  		StringBuf_Printf(&buf, ",`card%d`", j);
  3214. -	StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", storage_db, account_id);
  3215. +	StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", schema_config.storage_db, account_id);
  3216.  
  3217.  	if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) )
  3218.  		Sql_ShowDebug(sql_handle);
  3219. @@ -99,7 +99,7 @@
  3220.  	StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`bound`,`unique_id`");
  3221.  	for( j = 0; j < MAX_SLOTS; ++j )
  3222.  		StringBuf_Printf(&buf, ",`card%d`", j);
  3223. -	StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", guild_storage_db, guild_id);
  3224. +	StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", schema_config.guild_storage_db, guild_id);
  3225.  
  3226.  	if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) )
  3227.  		Sql_ShowDebug(sql_handle);
  3228. @@ -146,13 +146,13 @@
  3229.  // Delete char storage
  3230.  int inter_storage_delete(int account_id)
  3231.  {
  3232. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", storage_db, account_id) )
  3233. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", schema_config.storage_db, account_id) )
  3234.  		Sql_ShowDebug(sql_handle);
  3235.  	return 0;
  3236.  }
  3237.  int inter_guild_storage_delete(int guild_id)
  3238.  {
  3239. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_storage_db, guild_id) )
  3240. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_storage_db, guild_id) )
  3241.  		Sql_ShowDebug(sql_handle);
  3242.  	return 0;
  3243.  }
  3244. @@ -162,7 +162,7 @@
  3245.  
  3246.  int mapif_load_guild_storage(int fd,int account_id,int guild_id, char flag)
  3247.  {
  3248. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) )
  3249. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_db, guild_id) )
  3250.  		Sql_ShowDebug(sql_handle);
  3251.  	else if( Sql_NumRows(sql_handle) > 0 )
  3252.  	{// guild exists
  3253. @@ -222,7 +222,7 @@
  3254.  	}
  3255.  	else
  3256.  	{
  3257. -		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) )
  3258. +		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_db, guild_id) )
  3259.  			Sql_ShowDebug(sql_handle);
  3260.  		else if( Sql_NumRows(sql_handle) > 0 )
  3261.  		{// guild exists
  3262. @@ -266,7 +266,7 @@
  3263.  	StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`");
  3264.  	for( j = 0; j < MAX_SLOTS; ++j )
  3265.  		StringBuf_Printf(&buf, ", `card%d`", j);
  3266. -	StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'",inventory_db,char_id);
  3267. +	StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'",schema_config.inventory_db,char_id);
  3268.  
  3269.  	stmt = SqlStmt_Malloc(sql_handle);
  3270.  	if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf))
  3271. @@ -296,13 +296,13 @@
  3272.  			i++;
  3273.  		}
  3274.  	}
  3275. -	
  3276. +
  3277.  	if(!i) //No items found - No need to continue
  3278.  		return 0;
  3279.  
  3280.  	//First we delete the character's items
  3281.  	StringBuf_Clear(&buf);
  3282. -	StringBuf_Printf(&buf, "DELETE FROM `%s` WHERE",inventory_db);
  3283. +	StringBuf_Printf(&buf, "DELETE FROM `%s` WHERE",schema_config.inventory_db);
  3284.  	for(j=0; j<i; j++) {
  3285.  		if( found )
  3286.  			StringBuf_AppendStr(&buf, " OR");
  3287. @@ -324,11 +324,11 @@
  3288.  	//Now let's update the guild storage with those deleted items
  3289.  	found = false;
  3290.  	StringBuf_Clear(&buf);
  3291. -	StringBuf_Printf(&buf, "INSERT INTO `%s` (`guild_id`, `nameid`, `amount`, `identify`, `refine`, `attribute`, `expire_time`, `bound`", guild_storage_db);
  3292. +	StringBuf_Printf(&buf, "INSERT INTO `%s` (`guild_id`, `nameid`, `amount`, `identify`, `refine`, `attribute`, `expire_time`, `bound`", schema_config.guild_storage_db);
  3293.  	for( j = 0; j < MAX_SLOTS; ++j )
  3294.  		StringBuf_Printf(&buf, ", `card%d`", j);
  3295.  	StringBuf_AppendStr(&buf, ") VALUES ");
  3296. -	
  3297. +
  3298.  	for( j = 0; j < i; ++j ) {
  3299.  		if( found )
  3300.  			StringBuf_AppendStr(&buf, ",");
  3301. Index: src/char/CMakeLists.txt
  3302. ===================================================================
  3303. --- src/char/CMakeLists.txt	(revision 17373)
  3304. +++ src/char/CMakeLists.txt	(working copy)
  3305. @@ -12,6 +12,10 @@
  3306.  message( STATUS "Creating target char-server_sql" )
  3307.  set( SQL_CHAR_HEADERS
  3308.  	"${CMAKE_CURRENT_SOURCE_DIR}/char.h"
  3309. +	"${CMAKE_CURRENT_SOURCE_DIR}/char_clif.h"
  3310. +	"${CMAKE_CURRENT_SOURCE_DIR}/char_cnslif.h"
  3311. +	"${CMAKE_CURRENT_SOURCE_DIR}/char_logif.h"
  3312. +	"${CMAKE_CURRENT_SOURCE_DIR}/char_mapif.h"
  3313.  	"${CMAKE_CURRENT_SOURCE_DIR}/int_auction.h"
  3314.  	"${CMAKE_CURRENT_SOURCE_DIR}/int_elemental.h"
  3315.  	"${CMAKE_CURRENT_SOURCE_DIR}/int_guild.h"
  3316. @@ -26,6 +30,10 @@
  3317.  	)
  3318.  set( SQL_CHAR_SOURCES
  3319.  	"${CMAKE_CURRENT_SOURCE_DIR}/char.c"
  3320. +	"${CMAKE_CURRENT_SOURCE_DIR}/char_clif.c"
  3321. +	"${CMAKE_CURRENT_SOURCE_DIR}/char_cnslif.c"
  3322. +	"${CMAKE_CURRENT_SOURCE_DIR}/char_logif.c"
  3323. +	"${CMAKE_CURRENT_SOURCE_DIR}/char_mapif.c"
  3324.  	"${CMAKE_CURRENT_SOURCE_DIR}/int_auction.c"
  3325.  	"${CMAKE_CURRENT_SOURCE_DIR}/int_elemental.c"
  3326.  	"${CMAKE_CURRENT_SOURCE_DIR}/int_guild.c"
  3327. Index: src/char/int_homun.c
  3328. ===================================================================
  3329. --- src/char/int_homun.c	(revision 17373)
  3330. +++ src/char/int_homun.c	(working copy)
  3331. @@ -95,7 +95,7 @@
  3332.  		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` "
  3333.  			"(`char_id`, `class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`, `rename_flag`, `vaporize`) "
  3334.  			"VALUES ('%d', '%d', '%d', '%s', '%d', '%u', '%u', '%d', '%d', %d, '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
  3335. -			homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
  3336. +			schema_config.homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
  3337.  			hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize) )
  3338.  		{
  3339.  			Sql_ShowDebug(sql_handle);
  3340. @@ -109,7 +109,7 @@
  3341.  	else
  3342.  	{
  3343.  		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_id`='%d', `class`='%d',`prev_class`='%d',`name`='%s',`level`='%d',`exp`='%u',`intimacy`='%u',`hunger`='%d', `str`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `rename_flag`='%d', `vaporize`='%d' WHERE `homun_id`='%d'",
  3344. -			homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
  3345. +			schema_config.homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
  3346.  			hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->hom_id) )
  3347.  		{
  3348.  			Sql_ShowDebug(sql_handle);
  3349. @@ -121,7 +121,7 @@
  3350.  			int i;
  3351.  
  3352.  			stmt = SqlStmt_Malloc(sql_handle);
  3353. -			if( SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `%s` (`homun_id`, `id`, `lv`) VALUES (%d, ?, ?)", skill_homunculus_db, hd->hom_id) )
  3354. +			if( SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `%s` (`homun_id`, `id`, `lv`) VALUES (%d, ?, ?)", schema_config.skill_homunculus_db, hd->hom_id) )
  3355.  				SqlStmt_ShowDebug(stmt);
  3356.  			for( i = 0; i < MAX_HOMUNSKILL; ++i )
  3357.  			{
  3358. @@ -156,7 +156,8 @@
  3359.  
  3360.  	memset(hd, 0, sizeof(*hd));
  3361.  
  3362. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `%s` WHERE `homun_id`='%u'", homunculus_db, homun_id) )
  3363. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `%s` WHERE `homun_id`='%u'",
  3364. +		schema_config.homunculus_db, homun_id) )
  3365.  	{
  3366.  		Sql_ShowDebug(sql_handle);
  3367.  		return false;
  3368. @@ -202,7 +203,7 @@
  3369.  	hd->hunger = cap_value(hd->hunger, 0, 100);
  3370.  
  3371.  	// Load Homunculus Skill
  3372. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `homun_id`=%d", skill_homunculus_db, homun_id) )
  3373. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `homun_id`=%d", schema_config.skill_homunculus_db, homun_id) )
  3374.  	{
  3375.  		Sql_ShowDebug(sql_handle);
  3376.  		return false;
  3377. @@ -223,7 +224,7 @@
  3378.  	}
  3379.  	Sql_FreeResult(sql_handle);
  3380.  
  3381. -	if( save_log )
  3382. +	if( charserv_config.save_log )
  3383.  		ShowInfo("Homunculus loaded (%d - %s).\n", hd->hom_id, hd->name);
  3384.  
  3385.  	return true;
  3386. @@ -231,8 +232,8 @@
  3387.  
  3388.  bool mapif_homunculus_delete(int homun_id)
  3389.  {
  3390. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", homunculus_db, homun_id)
  3391. -	||	SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", skill_homunculus_db, homun_id)
  3392. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", schema_config.homunculus_db, homun_id)
  3393. +	||	SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", schema_config.skill_homunculus_db, homun_id)
  3394.  	) {
  3395.  		Sql_ShowDebug(sql_handle);
  3396.  		return false;
  3397. @@ -245,16 +246,16 @@
  3398.  	int i;
  3399.  
  3400.  	// Check Authorised letters/symbols in the name of the homun
  3401. -	if( char_name_option == 1 )
  3402. +	if( charserv_config.char_name_option == 1 )
  3403.  	{// only letters/symbols in char_name_letters are authorised
  3404.  		for( i = 0; i < NAME_LENGTH && name[i]; i++ )
  3405. -			if( strchr(char_name_letters, name[i]) == NULL )
  3406. +			if( strchr(charserv_config.char_name_letters, name[i]) == NULL )
  3407.  				return false;
  3408.  	} else
  3409. -	if( char_name_option == 2 )
  3410. +	if( charserv_config.char_name_option == 2 )
  3411.  	{// letters/symbols in char_name_letters are forbidden
  3412.  		for( i = 0; i < NAME_LENGTH && name[i]; i++ )
  3413. -			if( strchr(char_name_letters, name[i]) != NULL )
  3414. +			if( strchr(charserv_config.char_name_letters, name[i]) != NULL )
  3415.  				return false;
  3416.  	}
  3417.  
  3418. Index: src/char/Makefile.in
  3419. ===================================================================
  3420. --- src/char/Makefile.in	(revision 17373)
  3421. +++ src/char/Makefile.in	(working copy)
  3422. @@ -15,12 +15,14 @@
  3423.  COMMON_SQL_OBJ = ../common/obj_sql/sql.o
  3424.  COMMON_H = ../common/sql.h
  3425.  
  3426. -CHAR_OBJ = obj_sql/char.o obj_sql/inter.o obj_sql/int_party.o obj_sql/int_guild.o \
  3427. -	obj_sql/int_storage.o obj_sql/int_pet.o obj_sql/int_homun.o obj_sql/int_mail.o obj_sql/int_auction.o obj_sql/int_quest.o obj_sql/int_mercenary.o obj_sql/int_elemental.o
  3428. -CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h int_elemental.h
  3429. +CHAR_OBJ = char.o char_clif.o char_logif.o char_mapif.o char_cnslif.o\
  3430. +	inter.o int_party.o int_guild.o int_storage.o int_pet.o int_homun.o int_mail.o int_auction.o int_quest.o int_mercenary.o int_elemental.o
  3431. +CHAR_H = char.h \
  3432. +	inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h int_elemental.h
  3433. +CHAR_SQL_OBJ = $(CHAR_OBJ:%=obj_sql/%)
  3434.  
  3435.  HAVE_MYSQL=@HAVE_MYSQL@
  3436. -ifeq ($(HAVE_MYSQL),yes)	
  3437. +ifeq ($(HAVE_MYSQL),yes)
  3438.  	SQL_DEPENDS=char-server_sql
  3439.  else
  3440.  	SQL_DEPENDS=needs_mysql
  3441. @@ -49,9 +51,9 @@
  3442.  
  3443.  #####################################################################
  3444.  
  3445. -char-server_sql: obj_sql $(CHAR_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ)
  3446. +char-server_sql: obj_sql $(CHAR_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ)
  3447.  	@echo "	LD	$@"
  3448. -	@@CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
  3449. +	@@CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
  3450.  
  3451.  needs_mysql:
  3452.  	@echo "MySQL not found or disabled by the configure script"
  3453. Index: src/char/int_pet.c
  3454. ===================================================================
  3455. --- src/char/int_pet.c	(revision 17373)
  3456. +++ src/char/int_pet.c	(working copy)
  3457. @@ -32,7 +32,7 @@
  3458.  		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` "
  3459.  			"(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) "
  3460.  			"VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
  3461. -			pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
  3462. +			schema_config.pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
  3463.  			p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate) )
  3464.  		{
  3465.  			Sql_ShowDebug(sql_handle);
  3466. @@ -43,7 +43,7 @@
  3467.  	else
  3468.  	{// Update pet.
  3469.  		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incuvate`='%d' WHERE `pet_id`='%d'",
  3470. -			pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
  3471. +			schema_config.pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
  3472.  			p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate, p->pet_id) )
  3473.  		{
  3474.  			Sql_ShowDebug(sql_handle);
  3475. @@ -51,7 +51,7 @@
  3476.  		}
  3477.  	}
  3478.  
  3479. -	if (save_log)
  3480. +	if (charserv_config.save_log)
  3481.  		ShowInfo("Pet saved %d - %s.\n", pet_id, p->name);
  3482.  	return 1;
  3483.  }
  3484. @@ -68,7 +68,7 @@
  3485.  
  3486.  	//`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`)
  3487.  
  3488. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) )
  3489. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'", schema_config.pet_db, pet_id) )
  3490.  	{
  3491.  		Sql_ShowDebug(sql_handle);
  3492.  		return 0;
  3493. @@ -94,7 +94,7 @@
  3494.  		p->hungry = cap_value(p->hungry, 0, 100);
  3495.  		p->intimate = cap_value(p->intimate, 0, 1000);
  3496.  
  3497. -		if( save_log )
  3498. +		if( charserv_config.save_log )
  3499.  			ShowInfo("Pet loaded (%d - %s).\n", pet_id, p->name);
  3500.  	}
  3501.  	return 0;
  3502. @@ -114,7 +114,7 @@
  3503.  int inter_pet_delete(int pet_id){
  3504.  	ShowInfo("delete pet request: %d...\n",pet_id);
  3505.  
  3506. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) )
  3507. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `pet_id`='%d'", schema_config.pet_db, pet_id) )
  3508.  		Sql_ShowDebug(sql_handle);
  3509.  	return 0;
  3510.  }
  3511. Index: src/char/int_quest.c
  3512. ===================================================================
  3513. --- src/char/int_quest.c	(revision 17373)
  3514. +++ src/char/int_quest.c	(working copy)
  3515. @@ -34,7 +34,7 @@
  3516.  
  3517.  	memset(&tmp_quest, 0, sizeof(struct quest));
  3518.  
  3519. -	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `quest_id`, `state`, `time`, `count1`, `count2`, `count3` FROM `%s` WHERE `char_id`=? LIMIT %d", quest_db, MAX_QUEST_DB)
  3520. +	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `quest_id`, `state`, `time`, `count1`, `count2`, `count3` FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.quest_db, MAX_QUEST_DB)
  3521.  	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
  3522.  	||	SQL_ERROR == SqlStmt_Execute(stmt)
  3523.  	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT,    &tmp_quest.quest_id, 0, NULL, NULL)
  3524. @@ -55,7 +55,7 @@
  3525.  //Delete a quest
  3526.  bool mapif_quest_delete(int char_id, int quest_id)
  3527.  {
  3528. -	if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, quest_id, char_id) )
  3529. +	if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", schema_config.quest_db, quest_id, char_id) )
  3530.  	{
  3531.  		Sql_ShowDebug(sql_handle);
  3532.  		return false;
  3533. @@ -67,7 +67,7 @@
  3534.  //Add a quest to a questlog
  3535.  bool mapif_quest_add(int char_id, struct quest qd)
  3536.  {
  3537. -	if ( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`quest_id`, `char_id`, `state`, `time`, `count1`, `count2`, `count3`) VALUES ('%d', '%d', '%d','%d', '%d', '%d', '%d')", quest_db, qd.quest_id, char_id, qd.state, qd.time, qd.count[0], qd.count[1], qd.count[2]) ) 
  3538. +	if ( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`quest_id`, `char_id`, `state`, `time`, `count1`, `count2`, `count3`) VALUES ('%d', '%d', '%d','%d', '%d', '%d', '%d')", schema_config.quest_db, qd.quest_id, char_id, qd.state, qd.time, qd.count[0], qd.count[1], qd.count[2]) )
  3539.  	{
  3540.  		Sql_ShowDebug(sql_handle);
  3541.  		return false;
  3542. @@ -79,7 +79,7 @@
  3543.  //Update a questlog
  3544.  bool mapif_quest_update(int char_id, struct quest qd)
  3545.  {
  3546. -	if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `state`='%d', `count1`='%d', `count2`='%d', `count3`='%d' WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, qd.state, qd.count[0], qd.count[1], qd.count[2], qd.quest_id, char_id) ) 
  3547. +	if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `state`='%d', `count1`='%d', `count2`='%d', `count3`='%d' WHERE `quest_id` = '%d' AND `char_id` = '%d'", schema_config.quest_db, qd.state, qd.count[0], qd.count[1], qd.count[2], qd.quest_id, char_id) )
  3548.  	{
  3549.  		Sql_ShowDebug(sql_handle);
  3550.  		return false;
  3551. Index: src/char/int_auction.c
  3552. ===================================================================
  3553. --- src/char/int_auction.c	(revision 17373)
  3554. +++ src/char/int_auction.c	(working copy)
  3555. @@ -10,6 +10,7 @@
  3556.  #include "../common/sql.h"
  3557.  #include "../common/timer.h"
  3558.  #include "char.h"
  3559. +#include "char_mapif.h"
  3560.  #include "inter.h"
  3561.  #include "int_mail.h"
  3562.  #include "int_auction.h"
  3563. @@ -50,7 +51,7 @@
  3564.  
  3565.  	StringBuf_Init(&buf);
  3566.  	StringBuf_Printf(&buf, "UPDATE `%s` SET `seller_id` = '%d', `seller_name` = ?, `buyer_id` = '%d', `buyer_name` = ?, `price` = '%d', `buynow` = '%d', `hours` = '%d', `timestamp` = '%lu', `nameid` = '%d', `item_name` = ?, `type` = '%d', `refine` = '%d', `attribute` = '%d'",
  3567. -		auction_db, auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute);
  3568. +		schema_config.auction_db, auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute);
  3569.  	for( j = 0; j < MAX_SLOTS; j++ )
  3570.  		StringBuf_Printf(&buf, ", `card%d` = '%d'", j, auction->item.card[j]);
  3571.  	StringBuf_Printf(&buf, " WHERE `auction_id` = '%d'", auction->auction_id);
  3572. @@ -81,7 +82,7 @@
  3573.  	auction->timestamp = time(NULL) + (auction->hours * 3600);
  3574.  
  3575.  	StringBuf_Init(&buf);
  3576. -	StringBuf_Printf(&buf, "INSERT INTO `%s` (`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`", auction_db);
  3577. +	StringBuf_Printf(&buf, "INSERT INTO `%s` (`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`", schema_config.auction_db);
  3578.  	for( j = 0; j < MAX_SLOTS; j++ )
  3579.  		StringBuf_Printf(&buf, ",`card%d`", j);
  3580.  	StringBuf_Printf(&buf, ") VALUES ('%d',?,'%d',?,'%d','%d','%d','%lu','%d',?,'%d','%d','%d','%"PRIu64"'",
  3581. @@ -165,7 +166,7 @@
  3582.  {
  3583.  	unsigned int auction_id = auction->auction_id;
  3584.  
  3585. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", auction_db, auction_id) )
  3586. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", schema_config.auction_db, auction_id) )
  3587.  		Sql_ShowDebug(sql_handle);
  3588.  
  3589.  	if( auction->auction_end_timer != INVALID_TIMER )
  3590. @@ -189,7 +190,7 @@
  3591.  		"`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`");
  3592.  	for( i = 0; i < MAX_SLOTS; i++ )
  3593.  		StringBuf_Printf(&buf, ",`card%d`", i);
  3594. -	StringBuf_Printf(&buf, " FROM `%s` ORDER BY `auction_id` DESC", auction_db);
  3595. +	StringBuf_Printf(&buf, " FROM `%s` ORDER BY `auction_id` DESC", schema_config.auction_db);
  3596.  
  3597.  	if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) )
  3598.  		Sql_ShowDebug(sql_handle);
  3599. Index: src/char/char.c
  3600. ===================================================================
  3601. --- src/char/char.c	(revision 17373)
  3602. +++ src/char/char.c	(working copy)
  3603. @@ -21,8 +21,12 @@
  3604.  #include "int_elemental.h"
  3605.  #include "int_party.h"
  3606.  #include "int_storage.h"
  3607. +#include "inter.h"
  3608. +#include "char_logif.h"
  3609. +#include "char_mapif.h"
  3610. +#include "char_cnslif.h"
  3611. +#include "char_clif.h"
  3612.  #include "char.h"
  3613. -#include "inter.h"
  3614.  
  3615.  #include <sys/types.h>
  3616.  #include <time.h>
  3617. @@ -33,88 +37,22 @@
  3618.  #include <stdlib.h>
  3619.  #include <malloc.h>
  3620.  
  3621. -#define MAX_STARTITEM 32
  3622. +
  3623.  #define CHAR_MAX_MSG 300
  3624.  static char* msg_table[CHAR_MAX_MSG]; // Login Server messages_conf
  3625.  
  3626. -char char_db[256] = "char";
  3627. -char scdata_db[256] = "sc_data";
  3628. -char cart_db[256] = "cart_inventory";
  3629. -char inventory_db[256] = "inventory";
  3630. -char charlog_db[256] = "charlog";
  3631. -char storage_db[256] = "storage";
  3632. -char interlog_db[256] = "interlog";
  3633. -char reg_db[256] = "global_reg_value";
  3634. -char skill_db[256] = "skill";
  3635. -char memo_db[256] = "memo";
  3636. -char guild_db[256] = "guild";
  3637. -char guild_alliance_db[256] = "guild_alliance";
  3638. -char guild_castle_db[256] = "guild_castle";
  3639. -char guild_expulsion_db[256] = "guild_expulsion";
  3640. -char guild_member_db[256] = "guild_member";
  3641. -char guild_position_db[256] = "guild_position";
  3642. -char guild_skill_db[256] = "guild_skill";
  3643. -char guild_storage_db[256] = "guild_storage";
  3644. -char party_db[256] = "party";
  3645. -char pet_db[256] = "pet";
  3646. -char mail_db[256] = "mail"; // MAIL SYSTEM
  3647. -char auction_db[256] = "auction"; // Auctions System
  3648. -char friend_db[256] = "friends";
  3649. -char hotkey_db[256] = "hotkey";
  3650. -char quest_db[256] = "quest";
  3651. -char homunculus_db[256] = "homunculus";
  3652. -char skill_homunculus_db[256] = "skill_homunculus";
  3653. -char mercenary_db[256] = "mercenary";
  3654. -char mercenary_owner_db[256] = "mercenary_owner";
  3655. -char ragsrvinfo_db[256] = "ragsrvinfo";
  3656. +// check for exit signal
  3657. +// 0 is saving complete
  3658. +// other is char_id
  3659. +unsigned int save_flag = 0;
  3660.  
  3661. -// show loading/saving messages
  3662. -int save_log = 1;
  3663. +#define MAX_STARTITEM 32
  3664. +struct startitem {
  3665. +	int nameid; //Item ID
  3666. +	int amount; //Number of items
  3667. +	int pos; //Position (for auto-equip)
  3668. +} start_items[MAX_STARTITEM+1];
  3669.  
  3670. -static DBMap* char_db_; // int char_id -> struct mmo_charstatus*
  3671. -
  3672. -char db_path[1024] = "db";
  3673. -
  3674. -int db_use_sqldbs;
  3675. -
  3676. -struct mmo_map_server {
  3677. -	int fd;
  3678. -	uint32 ip;
  3679. -	uint16 port;
  3680. -	int users;
  3681. -	unsigned short map[MAX_MAP_PER_SERVER];
  3682. -} server[MAX_MAP_SERVERS];
  3683. -
  3684. -int login_fd=-1, char_fd=-1;
  3685. -char userid[24];
  3686. -char passwd[24];
  3687. -char server_name[20];
  3688. -char wisp_server_name[NAME_LENGTH] = "Server";
  3689. -char login_ip_str[128];
  3690. -uint32 login_ip = 0;
  3691. -uint16 login_port = 6900;
  3692. -char char_ip_str[128];
  3693. -uint32 char_ip = 0;
  3694. -char bind_ip_str[128];
  3695. -uint32 bind_ip = INADDR_ANY;
  3696. -uint16 char_port = 6121;
  3697. -int char_maintenance = 0;
  3698. -bool char_new = true;
  3699. -int char_new_display = 0;
  3700. -
  3701. -bool name_ignoring_case = false; // Allow or not identical name for characters but with a different case by [Yor]
  3702. -int char_name_option = 0; // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor]
  3703. -char unknown_char_name[NAME_LENGTH] = "Unknown"; // Name to use when the requested name cannot be determined
  3704. -#define TRIM_CHARS "\255\xA0\032\t\x0A\x0D " //The following characters are trimmed regardless because they cause confusion and problems on the servers. [Skotlex]
  3705. -char char_name_letters[1024] = ""; // list of letters/symbols allowed (or not) in a character name. by [Yor]
  3706. -
  3707. -int char_per_account = 0; //Maximum chars per account (default unlimited) [Sirius]
  3708. -int char_del_level = 0; //From which level u can delete character [Lupus]
  3709. -int char_del_delay = 86400;
  3710. -
  3711. -int log_char = 1;	// loggin char or not [devil]
  3712. -int log_inter = 1;	// loggin inter or not [devil]
  3713. -
  3714.  // Advanced subnet check [LuzZza]
  3715.  struct s_subnet {
  3716.  	uint32 mask;
  3717. @@ -123,130 +61,17 @@
  3718.  } subnet[16];
  3719.  int subnet_count = 0;
  3720.  
  3721. -struct char_session_data {
  3722. -	bool auth; // whether the session is authed or not
  3723. -	int account_id, login_id1, login_id2, sex;
  3724. -	int found_char[MAX_CHARS]; // ids of chars on this account
  3725. -	char email[40]; // e-mail (default: [email protected]) by [Yor]
  3726. -	time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
  3727. -	int group_id; // permission
  3728. -	uint8 char_slots;
  3729. -	uint32 version;
  3730. -	uint8 clienttype;
  3731. -	char new_name[NAME_LENGTH];
  3732. -	char birthdate[10+1];  // YYYY-MM-DD
  3733. -	// Pincode system
  3734. -	char pincode[PINCODE_LENGTH+1];
  3735. -	uint32 pincode_seed;
  3736. -	time_t pincode_change;
  3737. -	uint16 pincode_try;
  3738. -	// Addon system
  3739. -	unsigned int char_moves[MAX_CHARS]; // character moves left
  3740. -};
  3741. +DBMap* auth_db; // int account_id -> struct auth_node*
  3742. +DBMap* online_char_db; // int account_id -> struct online_char_data*
  3743. +DBMap* char_db_; // int char_id -> struct mmo_charstatus*
  3744. +DBMap* char_get_authdb() { return auth_db; }
  3745. +DBMap* char_get_onlinedb() { return online_char_db; }
  3746. +DBMap* char_get_chardb() { return char_db_; }
  3747.  
  3748. -struct startitem {
  3749. -	int nameid; //Item ID
  3750. -	int amount; //Number of items
  3751. -	int pos; //Position (for auto-equip)
  3752. -} start_items[MAX_STARTITEM+1];
  3753. -
  3754. -int max_connect_user = -1;
  3755. -int gm_allow_group = -1;
  3756. -int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
  3757. -int start_zeny = 0;
  3758. -int guild_exp_rate = 100;
  3759. -
  3760. -// Pincode system
  3761. -#define PINCODE_OK 0
  3762. -#define PINCODE_ASK 1
  3763. -#define PINCODE_NOTSET 2
  3764. -#define PINCODE_EXPIRED 3
  3765. -#define PINCODE_NEW 4
  3766. -#define PINCODE_PASSED 7
  3767. -#define	PINCODE_WRONG 8
  3768. -
  3769. -bool pincode_enabled = true;
  3770. -int pincode_changetime = 0;
  3771. -int pincode_maxtry = 3;
  3772. -bool pincode_force = true;
  3773. -
  3774. -void pincode_check( int fd, struct char_session_data* sd );
  3775. -void pincode_change( int fd, struct char_session_data* sd );
  3776. -void pincode_setnew( int fd, struct char_session_data* sd );
  3777. -void pincode_sendstate( int fd, struct char_session_data* sd, uint16 state );
  3778. -void pincode_notifyLoginPinUpdate( int account_id, char* pin );
  3779. -void pincode_notifyLoginPinError( int account_id );
  3780. -void pincode_decrypt( uint32 userSeed, char* pin );
  3781. -int pincode_compare( int fd, struct char_session_data* sd, char* pin );
  3782. -
  3783. -// Addon system
  3784. -bool char_move_enabled = true;
  3785. -bool char_movetoused = true;
  3786. -bool char_moves_unlimited = false;
  3787. -
  3788. -void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, unsigned short to );
  3789. -void moveCharSlotReply( int fd, struct char_session_data* sd, unsigned short index, short reason );
  3790. -
  3791. -//Custom limits for the fame lists. [Skotlex]
  3792. -int fame_list_size_chemist = MAX_FAME_LIST;
  3793. -int fame_list_size_smith = MAX_FAME_LIST;
  3794. -int fame_list_size_taekwon = MAX_FAME_LIST;
  3795. -
  3796. -// Char-server-side stored fame lists [DracoRPG]
  3797. -struct fame_list smith_fame_list[MAX_FAME_LIST];
  3798. -struct fame_list chemist_fame_list[MAX_FAME_LIST];
  3799. -struct fame_list taekwon_fame_list[MAX_FAME_LIST];
  3800. -
  3801. -// check for exit signal
  3802. -// 0 is saving complete
  3803. -// other is char_id
  3804. -unsigned int save_flag = 0;
  3805. -
  3806. -// Initial position (it's possible to set it in conf file)
  3807. -struct point start_point = { 0, 53, 111 };
  3808. -
  3809. -int console = 0;
  3810. -
  3811. -//-----------------------------------------------------
  3812. -// Auth database
  3813. -//-----------------------------------------------------
  3814. -#define AUTH_TIMEOUT 30000
  3815. -
  3816. -struct auth_node {
  3817. -	int account_id;
  3818. -	int char_id;
  3819. -	uint32 login_id1;
  3820. -	uint32 login_id2;
  3821. -	uint32 ip;
  3822. -	int sex;
  3823. -	time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
  3824. -	int group_id;
  3825. -	unsigned changing_mapservers : 1;
  3826. -};
  3827. -
  3828. -static DBMap* auth_db; // int account_id -> struct auth_node*
  3829. -
  3830. -//-----------------------------------------------------
  3831. -// Online User Database
  3832. -//-----------------------------------------------------
  3833. -
  3834. -struct online_char_data {
  3835. -	int account_id;
  3836. -	int char_id;
  3837. -	int fd;
  3838. -	int waiting_disconnect;
  3839. -	short server; // -2: unknown server, -1: not connected, 0+: id of server
  3840. -	bool pincode_success;
  3841. -};
  3842. -
  3843. -static DBMap* online_char_db; // int account_id -> struct online_char_data*
  3844. -static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data);
  3845. -int delete_char_sql(int char_id);
  3846. -
  3847.  /**
  3848.   * @see DBCreateData
  3849.   */
  3850. -static DBData create_online_char_data(DBKey key, va_list args)
  3851. +DBData create_online_char_data(DBKey key, va_list args)
  3852.  {
  3853.  	struct online_char_data* character;
  3854.  	CREATE(character, struct online_char_data, 1);
  3855. @@ -276,13 +101,7 @@
  3856.  		character->waiting_disconnect = INVALID_TIMER;
  3857.  	}
  3858.  
  3859. -	if (login_fd > 0 && !session[login_fd]->flag.eof)
  3860. -	{
  3861. -		WFIFOHEAD(login_fd,6);
  3862. -		WFIFOW(login_fd,0) = 0x272b;
  3863. -		WFIFOL(login_fd,2) = account_id;
  3864. -		WFIFOSET(login_fd,6);
  3865. -	}
  3866. +	char_send_setacconline(account_id);
  3867.  
  3868.  }
  3869.  
  3870. @@ -292,7 +111,7 @@
  3871.  	struct mmo_charstatus *cp;
  3872.  
  3873.  	//Update DB
  3874. -	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) )
  3875. +	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d' LIMIT 1", schema_config.char_db, char_id) )
  3876.  		Sql_ShowDebug(sql_handle);
  3877.  
  3878.  	//Check to see for online conflicts
  3879. @@ -322,13 +141,7 @@
  3880.  	inter_guild_CharOnline(char_id, cp?cp->guild_id:-1);
  3881.  
  3882.  	//Notify login server
  3883. -	if (login_fd > 0 && !session[login_fd]->flag.eof)
  3884. -	{
  3885. -		WFIFOHEAD(login_fd,6);
  3886. -		WFIFOW(login_fd,0) = 0x272b;
  3887. -		WFIFOL(login_fd,2) = account_id;
  3888. -		WFIFOSET(login_fd,6);
  3889. -	}
  3890. +	char_send_setacconline(account_id);
  3891.  }
  3892.  
  3893.  void set_char_offline(int char_id, int account_id)
  3894. @@ -337,7 +150,7 @@
  3895.  
  3896.  	if ( char_id == -1 )
  3897.  	{
  3898. -		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", char_db, account_id) )
  3899. +		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", schema_config.char_db, account_id) )
  3900.  			Sql_ShowDebug(sql_handle);
  3901.  	}
  3902.  	else
  3903. @@ -347,7 +160,7 @@
  3904.  		if (cp)
  3905.  			idb_remove(char_db_,char_id);
  3906.  
  3907. -		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) )
  3908. +		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `char_id`='%d' LIMIT 1", schema_config.char_db, char_id) )
  3909.  			Sql_ShowDebug(sql_handle);
  3910.  	}
  3911.  
  3912. @@ -374,20 +187,15 @@
  3913.  	}
  3914.  
  3915.  	//Remove char if 1- Set all offline, or 2- character is no longer connected to char-server.
  3916. -	if (login_fd > 0 && !session[login_fd]->flag.eof && (char_id == -1 || character == NULL || character->fd == -1))
  3917. -	{
  3918. -		WFIFOHEAD(login_fd,6);
  3919. -		WFIFOW(login_fd,0) = 0x272c;
  3920. -		WFIFOL(login_fd,2) = account_id;
  3921. -		WFIFOSET(login_fd,6);
  3922. +	if (char_id == -1 || character == NULL || character->fd == -1){
  3923. +		char_send_setaccoffline(login_fd,account_id);
  3924.  	}
  3925.  }
  3926.  
  3927.  /**
  3928.   * @see DBApply
  3929.   */
  3930. -static int char_db_setoffline(DBKey key, DBData *data, va_list ap)
  3931. -{
  3932. +int char_db_setoffline(DBKey key, DBData *data, va_list ap) {
  3933.  	struct online_char_data* character = (struct online_char_data*)db_data2ptr(data);
  3934.  	int server = va_arg(ap, int);
  3935.  	if (server == -1) {
  3936. @@ -434,20 +242,17 @@
  3937.  
  3938.  	if (id >= 0 || login_fd <= 0 || session[login_fd]->flag.eof)
  3939.  		return;
  3940. -	//Tell login-server to also mark all our characters as offline.
  3941. -	WFIFOHEAD(login_fd,2);
  3942. -	WFIFOW(login_fd,0) = 0x2737;
  3943. -	WFIFOSET(login_fd,2);
  3944. +	char_send_setallaccoffline(login_fd);
  3945.  }
  3946.  
  3947.  void set_all_offline_sql(void)
  3948.  {
  3949.  	//Set all players to 'OFFLINE'
  3950. -	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", char_db) )
  3951. +	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", schema_config.char_db) )
  3952.  		Sql_ShowDebug(sql_handle);
  3953. -	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", guild_member_db) )
  3954. +	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", schema_config.guild_member_db) )
  3955.  		Sql_ShowDebug(sql_handle);
  3956. -	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `connect_member` = '0'", guild_db) )
  3957. +	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `connect_member` = '0'", schema_config.guild_db) )
  3958.  		Sql_ShowDebug(sql_handle);
  3959.  }
  3960.  
  3961. @@ -533,7 +338,7 @@
  3962.  			"`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d',"
  3963.  			"`delete_date`='%lu',`robe`='%d',`moves`='%d'"
  3964.  			" WHERE  `account_id`='%d' AND `char_id` = '%d'",
  3965. -			char_db, p->base_level, p->job_level,
  3966. +			schema_config.char_db, p->base_level, p->job_level,
  3967.  			p->base_exp, p->job_exp, p->zeny,
  3968.  			p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point,
  3969.  			p->str, p->agi, p->vit, p->int_, p->dex, p->luk,
  3970. @@ -566,7 +371,7 @@
  3971.  			"`partner_id`='%d', `father`='%d', `mother`='%d', `child`='%d',"
  3972.  			"`karma`='%d',`manner`='%d', `fame`='%d'"
  3973.  			" WHERE  `account_id`='%d' AND `char_id` = '%d'",
  3974. -			char_db, p->class_,
  3975. +			schema_config.char_db, p->class_,
  3976.  			p->hair, p->hair_color, p->clothes_color,
  3977.  			p->partner_id, p->father, p->mother, p->child,
  3978.  			p->karma, p->manner, p->fame,
  3979. @@ -596,7 +401,7 @@
  3980.  		char esc_mapname[NAME_LENGTH*2+1];
  3981.  
  3982.  		//`memo` (`memo_id`,`char_id`,`map`,`x`,`y`)
  3983. -		if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, p->char_id) )
  3984. +		if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.memo_db, p->char_id) )
  3985.  		{
  3986.  			Sql_ShowDebug(sql_handle);
  3987.  			errors++;
  3988. @@ -604,7 +409,7 @@
  3989.  
  3990.  		//insert here.
  3991.  		StringBuf_Clear(&buf);
  3992. -		StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", memo_db);
  3993. +		StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", schema_config.memo_db);
  3994.  		for( i = 0, count = 0; i < MAX_MEMOPOINTS; ++i )
  3995.  		{
  3996.  			if( p->memo_point[i].map )
  3997. @@ -637,14 +442,14 @@
  3998.  	if( memcmp(p->skill, cp->skill, sizeof(p->skill)) )
  3999.  	{
  4000.  		//`skill` (`char_id`, `id`, `lv`)
  4001. -		if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, p->char_id) )
  4002. +		if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.skill_db, p->char_id) )
  4003.  		{
  4004.  			Sql_ShowDebug(sql_handle);
  4005.  			errors++;
  4006.  		}
  4007.  
  4008.  		StringBuf_Clear(&buf);
  4009. -		StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`,`flag`) VALUES ", skill_db);
  4010. +		StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`,`flag`) VALUES ", schema_config.skill_db);
  4011.  		//insert here.
  4012.  		for( i = 0, count = 0; i < MAX_SKILL; ++i ) {
  4013.  			if( p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY ) {
  4014. @@ -684,14 +489,14 @@
  4015.  
  4016.  	if(diff == 1)
  4017.  	{	//Save friends
  4018. -		if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", friend_db, char_id) )
  4019. +		if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.friend_db, char_id) )
  4020.  		{
  4021.  			Sql_ShowDebug(sql_handle);
  4022.  			errors++;
  4023.  		}
  4024.  
  4025.  		StringBuf_Clear(&buf);
  4026. -		StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", friend_db);
  4027. +		StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", schema_config.friend_db);
  4028.  		for( i = 0, count = 0; i < MAX_FRIENDS; ++i )
  4029.  		{
  4030.  			if( p->friends[i].char_id > 0 )
  4031. @@ -716,7 +521,7 @@
  4032.  #ifdef HOTKEY_SAVING
  4033.  	// hotkeys
  4034.  	StringBuf_Clear(&buf);
  4035. -	StringBuf_Printf(&buf, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", hotkey_db);
  4036. +	StringBuf_Printf(&buf, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", schema_config.hotkey_db);
  4037.  	diff = 0;
  4038.  	for(i = 0; i < ARRAYLENGTH(p->hotkeys); i++){
  4039.  		if(memcmp(&p->hotkeys[i], &cp->hotkeys[i], sizeof(struct hotkey)))
  4040. @@ -737,7 +542,7 @@
  4041.  	}
  4042.  #endif
  4043.  	StringBuf_Destroy(&buf);
  4044. -	if (save_status[0]!='\0' && save_log)
  4045. +	if (save_status[0]!='\0' && charserv_config.save_log)
  4046.  		ShowInfo("Saved char %d - %s:%s.\n", char_id, p->name, save_status);
  4047.  	if (!errors)
  4048.  		memcpy(cp, p, sizeof(struct mmo_charstatus));
  4049. @@ -759,10 +564,10 @@
  4050.  	int errors = 0;
  4051.  
  4052.  	switch (tableswitch) {
  4053. -	case TABLE_INVENTORY:     tablename = inventory_db;     selectoption = "char_id";    break;
  4054. -	case TABLE_CART:          tablename = cart_db;          selectoption = "char_id";    break;
  4055. -	case TABLE_STORAGE:       tablename = storage_db;       selectoption = "account_id"; break;
  4056. -	case TABLE_GUILD_STORAGE: tablename = guild_storage_db; selectoption = "guild_id";   break;
  4057. +	case TABLE_INVENTORY:     tablename = schema_config.inventory_db;     selectoption = "char_id";    break;
  4058. +	case TABLE_CART:          tablename = schema_config.cart_db;          selectoption = "char_id";    break;
  4059. +	case TABLE_STORAGE:       tablename = schema_config.storage_db;       selectoption = "account_id"; break;
  4060. +	case TABLE_GUILD_STORAGE: tablename = schema_config.guild_storage_db; selectoption = "guild_id";   break;
  4061.  	default:
  4062.  		ShowError("Invalid table name!\n");
  4063.  		return 1;
  4064. @@ -924,7 +729,7 @@
  4065.  	StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`");
  4066.  	for( j = 0; j < MAX_SLOTS; ++j )
  4067.  		StringBuf_Printf(&buf, ", `card%d`", j);
  4068. -	StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", inventory_db, id);
  4069. +	StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", schema_config.inventory_db, id);
  4070.  
  4071.  	stmt = SqlStmt_Malloc(sql_handle);
  4072.  	if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf))
  4073. @@ -980,7 +785,7 @@
  4074.  					// update all fields.
  4075.  					StringBuf_Clear(&buf);
  4076.  					StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `favorite`='%d', `bound`='%d'",
  4077. -									 inventory_db, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound);
  4078. +					    schema_config.inventory_db, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound);
  4079.  					for( j = 0; j < MAX_SLOTS; ++j )
  4080.  						StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]);
  4081.  					StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id);
  4082. @@ -996,7 +801,7 @@
  4083.  			}
  4084.  		}
  4085.  		if( !found ) {// Item not present in inventory, remove it.
  4086. -			if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", inventory_db, item.id) ) {
  4087. +			if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", schema_config.inventory_db, item.id) ) {
  4088.  				Sql_ShowDebug(sql_handle);
  4089.  				errors++;
  4090.  			}
  4091. @@ -1005,7 +810,7 @@
  4092.  	SqlStmt_Free(stmt);
  4093.  
  4094.  	StringBuf_Clear(&buf);
  4095. -	StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`", inventory_db);
  4096. +	StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`", schema_config.inventory_db);
  4097.  	for( j = 0; j < MAX_SLOTS; ++j )
  4098.  		StringBuf_Printf(&buf, ", `card%d`", j);
  4099.  	StringBuf_AppendStr(&buf, ") VALUES ");
  4100. @@ -1074,7 +879,7 @@
  4101.  		"`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`,"
  4102.  		"`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`,"
  4103.  		"`robe`,`moves`"
  4104. -		" FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS)
  4105. +		" FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", schema_config.char_db, sd->account_id, MAX_CHARS)
  4106.  	||	SQL_ERROR == SqlStmt_Execute(stmt)
  4107.  	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0,  SQLDT_INT,    &p.char_id, 0, NULL, NULL)
  4108.  	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 1,  SQLDT_UCHAR,  &p.slot, 0, NULL, NULL)
  4109. @@ -1159,7 +964,7 @@
  4110.  
  4111.  	memset(p, 0, sizeof(struct mmo_charstatus));
  4112.  
  4113. -	if (save_log) ShowInfo("Char load request (%d)\n", char_id);
  4114. +	if (charserv_config.save_log) ShowInfo("Char load request (%d)\n", char_id);
  4115.  
  4116.  	stmt = SqlStmt_Malloc(sql_handle);
  4117.  	if( stmt == NULL )
  4118. @@ -1175,7 +980,7 @@
  4119.  		"`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`,"
  4120.  		"`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`,"
  4121.  		"`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`, `moves`"
  4122. -		" FROM `%s` WHERE `char_id`=? LIMIT 1", char_db)
  4123. +		" FROM `%s` WHERE `char_id`=? LIMIT 1", schema_config.char_db)
  4124.  	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
  4125.  	||	SQL_ERROR == SqlStmt_Execute(stmt)
  4126.  	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0,  SQLDT_INT,    &p->char_id, 0, NULL, NULL)
  4127. @@ -1268,7 +1073,7 @@
  4128.  
  4129.  	//read memo data
  4130.  	//`memo` (`memo_id`,`char_id`,`map`,`x`,`y`)
  4131. -	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`=? ORDER by `memo_id` LIMIT %d", memo_db, MAX_MEMOPOINTS)
  4132. +	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`=? ORDER by `memo_id` LIMIT %d", schema_config.memo_db, MAX_MEMOPOINTS)
  4133.  	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
  4134.  	||	SQL_ERROR == SqlStmt_Execute(stmt)
  4135.  	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &point_map, sizeof(point_map), NULL, NULL)
  4136. @@ -1289,7 +1094,7 @@
  4137.  	StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`");
  4138.  	for( i = 0; i < MAX_SLOTS; ++i )
  4139.  		StringBuf_Printf(&buf, ", `card%d`", i);
  4140. -	StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", inventory_db, MAX_INVENTORY);
  4141. +	StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.inventory_db, MAX_INVENTORY);
  4142.  
  4143.  	if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf))
  4144.  	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
  4145. @@ -1321,7 +1126,7 @@
  4146.  	StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`");
  4147.  	for( j = 0; j < MAX_SLOTS; ++j )
  4148.  		StringBuf_Printf(&buf, ", `card%d`", j);
  4149. -	StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", cart_db, MAX_CART);
  4150. +	StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.cart_db, MAX_CART);
  4151.  
  4152.  	if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf))
  4153.  	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
  4154. @@ -1351,7 +1156,7 @@
  4155.  
  4156.  	//read skill
  4157.  	//`skill` (`char_id`, `id`, `lv`)
  4158. -	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", skill_db, MAX_SKILL)
  4159. +	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.skill_db, MAX_SKILL)
  4160.  	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
  4161.  	||	SQL_ERROR == SqlStmt_Execute(stmt)
  4162.  	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id  , 0, NULL, NULL)
  4163. @@ -1373,7 +1178,7 @@
  4164.  
  4165.  	//read friends
  4166.  	//`friends` (`char_id`, `friend_account`, `friend_id`)
  4167. -	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT c.`account_id`, c.`char_id`, c.`name` FROM `%s` c LEFT JOIN `%s` f ON f.`friend_account` = c.`account_id` AND f.`friend_id` = c.`char_id` WHERE f.`char_id`=? LIMIT %d", char_db, friend_db, MAX_FRIENDS)
  4168. +	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT c.`account_id`, c.`char_id`, c.`name` FROM `%s` c LEFT JOIN `%s` f ON f.`friend_account` = c.`account_id` AND f.`friend_id` = c.`char_id` WHERE f.`char_id`=? LIMIT %d", schema_config.char_db, schema_config.friend_db, MAX_FRIENDS)
  4169.  	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
  4170.  	||	SQL_ERROR == SqlStmt_Execute(stmt)
  4171.  	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT,    &tmp_friend.account_id, 0, NULL, NULL)
  4172. @@ -1388,7 +1193,7 @@
  4173.  #ifdef HOTKEY_SAVING
  4174.  	//read hotkeys
  4175.  	//`hotkey` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`
  4176. -	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`=?", hotkey_db)
  4177. +	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`=?", schema_config.hotkey_db)
  4178.  	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
  4179.  	||	SQL_ERROR == SqlStmt_Execute(stmt)
  4180.  	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT,    &hotkey_num, 0, NULL, NULL)
  4181. @@ -1412,7 +1217,7 @@
  4182.  	strcat(t_msg, " mercenary");
  4183.  
  4184.  
  4185. -	if (save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg);	//ok. all data load successfuly!
  4186. +	if (charserv_config.save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg);	//ok. all data load successfuly!
  4187.  	SqlStmt_Free(stmt);
  4188.  	StringBuf_Destroy(&buf);
  4189.  
  4190. @@ -1426,7 +1231,7 @@
  4191.  {
  4192.  	char_db_= idb_alloc(DB_OPT_RELEASE_DATA);
  4193.  
  4194. -	ShowStatus("Characters per Account: '%d'.\n", char_per_account);
  4195. +	ShowStatus("Characters per Account: '%d'.\n", char_config.char_per_account);
  4196.  
  4197.  	//the 'set offline' part is now in check_login_conn ...
  4198.  	//if the server connects to loginserver
  4199. @@ -1460,13 +1265,13 @@
  4200.  	Sql_EscapeStringLen(sql_handle, esc_name, sd->new_name, strnlen(sd->new_name, NAME_LENGTH));
  4201.  
  4202.  	// check if the char exist
  4203. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` LIKE '%s' LIMIT 1", char_db, esc_name) )
  4204. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` LIKE '%s' LIMIT 1", schema_config.char_db, esc_name) )
  4205.  	{
  4206.  		Sql_ShowDebug(sql_handle);
  4207.  		return 4;
  4208.  	}
  4209.  
  4210. -	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name` = '%s', `rename` = '%d' WHERE `char_id` = '%d'", char_db, esc_name, --char_dat.rename, char_id) )
  4211. +	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name` = '%s', `rename` = '%d' WHERE `char_id` = '%d'", schema_config.char_db, esc_name, --char_dat.rename, char_id) )
  4212.  	{
  4213.  		Sql_ShowDebug(sql_handle);
  4214.  		return 3;
  4215. @@ -1480,11 +1285,11 @@
  4216.  	memset(sd->new_name,0,sizeof(sd->new_name));
  4217.  
  4218.  	// log change
  4219. -	if( log_char )
  4220. +	if( charserv_config.log_char )
  4221.  	{
  4222.  		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)"
  4223.  			"VALUES (NOW(), '%s', '%d', '%d', '%s', '0', '0', '0', '0', '0', '0', '0', '0')",
  4224. -			charlog_db, "change char name", sd->account_id, char_dat.slot, esc_name) )
  4225. +			schema_config.charlog_db, "change char name", sd->account_id, char_dat.slot, esc_name) )
  4226.  			Sql_ShowDebug(sql_handle);
  4227.  	}
  4228.  
  4229. @@ -1509,29 +1314,29 @@
  4230.  		return -2; // control chars in name
  4231.  
  4232.  	// check for reserved names
  4233. -	if( strcmpi(name, wisp_server_name) == 0 )
  4234. +	if( strcmpi(name, charserv_config.wisp_server_name) == 0 )
  4235.  		return -1; // nick reserved for internal server messages
  4236.  
  4237.  	// Check Authorised letters/symbols in the name of the character
  4238. -	if( char_name_option == 1 )
  4239. +	if( charserv_config.char_name_option == 1 )
  4240.  	{ // only letters/symbols in char_name_letters are authorised
  4241.  		for( i = 0; i < NAME_LENGTH && name[i]; i++ )
  4242. -			if( strchr(char_name_letters, name[i]) == NULL )
  4243. +			if( strchr(charserv_config.char_name_letters, name[i]) == NULL )
  4244.  				return -2;
  4245.  	}
  4246. -	else if( char_name_option == 2 )
  4247. +	else if( charserv_config.char_name_option == 2 )
  4248.  	{ // letters/symbols in char_name_letters are forbidden
  4249.  		for( i = 0; i < NAME_LENGTH && name[i]; i++ )
  4250. -			if( strchr(char_name_letters, name[i]) != NULL )
  4251. +			if( strchr(charserv_config.char_name_letters, name[i]) != NULL )
  4252.  				return -2;
  4253.  	}
  4254. -	if( name_ignoring_case ) {
  4255. -		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", char_db, esc_name) ) {
  4256. +	if( charserv_config.name_ignoring_case ) {
  4257. +		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", schema_config.char_db, esc_name) ) {
  4258.  			Sql_ShowDebug(sql_handle);
  4259.  			return -2;
  4260.  		}
  4261.  	} else {
  4262. -		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", char_db, esc_name) ) {
  4263. +		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", schema_config.char_db, esc_name) ) {
  4264.  			Sql_ShowDebug(sql_handle);
  4265.  			return -2;
  4266.  		}
  4267. @@ -1581,24 +1386,24 @@
  4268.  
  4269.  
  4270.  	// check the number of already existing chars in this account
  4271. -	if( char_per_account != 0 ) {
  4272. -		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d'", char_db, sd->account_id) )
  4273. +	if( char_config.char_per_account != 0 ) {
  4274. +		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d'", schema_config.char_db, sd->account_id) )
  4275.  			Sql_ShowDebug(sql_handle);
  4276. -		if( Sql_NumRows(sql_handle) >= char_per_account )
  4277. +		if( Sql_NumRows(sql_handle) >= char_config.char_per_account )
  4278.  			return -2; // character account limit exceeded
  4279.  	}
  4280.  
  4281.  	// check char slot
  4282. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' LIMIT 1", char_db, sd->account_id, slot) )
  4283. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' LIMIT 1", schema_config.char_db, sd->account_id, slot) )
  4284.  		Sql_ShowDebug(sql_handle);
  4285.  	if( Sql_NumRows(sql_handle) > 0 )
  4286.  		return -2; // slot already in use
  4287.  
  4288.  	// validation success, log result
  4289. -	if (log_char) {
  4290. +	if (charserv_config.log_char) {
  4291.  		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)"
  4292.  			"VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
  4293. -			charlog_db, "make new char", sd->account_id, slot, esc_name, str, agi, vit, int_, dex, luk, hair_style, hair_color) )
  4294. +			schema_config.charlog_db, "make new char", sd->account_id, slot, esc_name, str, agi, vit, int_, dex, luk, hair_style, hair_color) )
  4295.  			Sql_ShowDebug(sql_handle);
  4296.  	}
  4297.  #if PACKETVER >= 20120307
  4298. @@ -1606,9 +1411,9 @@
  4299.  	if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `status_point`,`str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`,"
  4300.  		"`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES ("
  4301.  		"'%d', '%d', '%s', '%d',  '%d','%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')",
  4302. -		char_db, sd->account_id , slot, esc_name, start_zeny, 48, str, agi, vit, int_, dex, luk,
  4303. +		schema_config.char_db, sd->account_id , slot, esc_name, charserv_config.start_zeny, 48, str, agi, vit, int_, dex, luk,
  4304.  		(40 * (100 + vit)/100) , (40 * (100 + vit)/100 ),  (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color,
  4305. -		mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y) )
  4306. +		mapindex_id2name(charserv_config.start_point.map), charserv_config.start_point.x, charserv_config.start_point.y, mapindex_id2name(charserv_config.start_point.map), charserv_config.start_point.x, charserv_config.start_point.y) )
  4307.  	{
  4308.  		Sql_ShowDebug(sql_handle);
  4309.  		return -2; //No, stop the procedure!
  4310. @@ -1616,11 +1421,11 @@
  4311.  #else
  4312.  	//Insert the new char entry to the database
  4313.  	if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`,"
  4314. -							   "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES ("
  4315. -							   "'%d', '%d', '%s', '%d',  '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')",
  4316. -							   char_db, sd->account_id , slot, esc_name, start_zeny, str, agi, vit, int_, dex, luk,
  4317. -							   (40 * (100 + vit)/100) , (40 * (100 + vit)/100 ),  (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color,
  4318. -							   mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y) )
  4319. +		"`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES ("
  4320. +		"'%d', '%d', '%s', '%d',  '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')",
  4321. +		char_db, sd->account_id , slot, esc_name, start_zeny, str, agi, vit, int_, dex, luk,
  4322. +		(40 * (100 + vit)/100) , (40 * (100 + vit)/100 ),  (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color,
  4323. +		mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y) )
  4324.  	{
  4325.  		Sql_ShowDebug(sql_handle);
  4326.  		return -2; //No, stop the procedure!
  4327. @@ -1630,7 +1435,7 @@
  4328.  	char_id = (int)Sql_LastInsertId(sql_handle);
  4329.  	//Give the char the default items
  4330.  	for (k = 0; k <= MAX_STARTITEM && start_items[k].nameid != 0; k ++) {
  4331. -		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", inventory_db, char_id, start_items[k].nameid, start_items[k].amount, start_items[k].pos, 1) )
  4332. +		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", schema_config.inventory_db, char_id, start_items[k].nameid, start_items[k].amount, start_items[k].pos, 1) )
  4333.  			Sql_ShowDebug(sql_handle);
  4334.  	}
  4335.  
  4336. @@ -1641,20 +1446,12 @@
  4337.  /*----------------------------------------------------------------------------------------------------------*/
  4338.  /* Divorce Players */
  4339.  /*----------------------------------------------------------------------------------------------------------*/
  4340. -int divorce_char_sql(int partner_id1, int partner_id2)
  4341. -{
  4342. -	unsigned char buf[64];
  4343. -
  4344. -	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `partner_id`='0' WHERE `char_id`='%d' OR `char_id`='%d' LIMIT 2", char_db, partner_id1, partner_id2) )
  4345. +int divorce_char_sql(int partner_id1, int partner_id2){
  4346. +	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `partner_id`='0' WHERE `char_id`='%d' OR `char_id`='%d' LIMIT 2", schema_config.char_db, partner_id1, partner_id2) )
  4347.  		Sql_ShowDebug(sql_handle);
  4348. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE (`nameid`='%d' OR `nameid`='%d') AND (`char_id`='%d' OR `char_id`='%d') LIMIT 2", inventory_db, WEDDING_RING_M, WEDDING_RING_F, partner_id1, partner_id2) )
  4349. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE (`nameid`='%d' OR `nameid`='%d') AND (`char_id`='%d' OR `char_id`='%d') LIMIT 2", schema_config.inventory_db, WEDDING_RING_M, WEDDING_RING_F, partner_id1, partner_id2) )
  4350.  		Sql_ShowDebug(sql_handle);
  4351. -
  4352. -	WBUFW(buf,0) = 0x2b12;
  4353. -	WBUFL(buf,2) = partner_id1;
  4354. -	WBUFL(buf,6) = partner_id2;
  4355. -	mapif_sendall(buf,10);
  4356. -
  4357. +	char_send_ackdivorce(partner_id1, partner_id2);
  4358.  	return 0;
  4359.  }
  4360.  
  4361. @@ -1672,7 +1469,7 @@
  4362.  	char *data;
  4363.  	size_t len;
  4364.  
  4365. -	if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother`,`elemental_id` FROM `%s` WHERE `char_id`='%d'", char_db, char_id))
  4366. +	if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother`,`elemental_id` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id))
  4367.  		Sql_ShowDebug(sql_handle);
  4368.  
  4369.  	if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  4370. @@ -1698,8 +1495,8 @@
  4371.  
  4372.  	//check for config char del condition [Lupus]
  4373.  	// TODO: Move this out to packet processing (0x68/0x1fb).
  4374. -	if( ( char_del_level > 0 && base_level >= char_del_level )
  4375. -	 || ( char_del_level < 0 && base_level <= -char_del_level )
  4376. +	if( ( char_config.char_del_level > 0 && base_level >= char_config.char_del_level )
  4377. +	 || ( char_config.char_del_level < 0 && base_level <= -char_config.char_del_level )
  4378.  	) {
  4379.  			ShowInfo("Char deletion aborted: %s, BaseLevel: %i\n", name, base_level);
  4380.  			return -1;
  4381. @@ -1714,9 +1511,9 @@
  4382.  	{ // Char is Baby
  4383.  		unsigned char buf[64];
  4384.  
  4385. -		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `child`='0' WHERE `char_id`='%d' OR `char_id`='%d'", char_db, father_id, mother_id) )
  4386. +		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `child`='0' WHERE `char_id`='%d' OR `char_id`='%d'", schema_config.char_db, father_id, mother_id) )
  4387.  			Sql_ShowDebug(sql_handle);
  4388. -		if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '410'AND (`char_id`='%d' OR `char_id`='%d')", skill_db, father_id, mother_id) )
  4389. +		if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '410'AND (`char_id`='%d' OR `char_id`='%d')", schema_config.skill_db, father_id, mother_id) )
  4390.  			Sql_ShowDebug(sql_handle);
  4391.  
  4392.  		WBUFW(buf,0) = 0x2b25;
  4393. @@ -1732,13 +1529,13 @@
  4394.  
  4395.  	/* delete char's pet */
  4396.  	//Delete the hatched pet if you have one...
  4397. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `incuvate` = '0'", pet_db, char_id) )
  4398. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `incuvate` = '0'", schema_config.pet_db, char_id) )
  4399.  		Sql_ShowDebug(sql_handle);
  4400.  
  4401.  	//Delete all pets that are stored in eggs (inventory + cart)
  4402. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", pet_db, pet_db, inventory_db, inventory_db, char_id) )
  4403. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", schema_config.pet_db, schema_config.pet_db, schema_config.inventory_db, schema_config.inventory_db, char_id) )
  4404.  		Sql_ShowDebug(sql_handle);
  4405. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", pet_db, pet_db, cart_db, cart_db, char_id) )
  4406. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", schema_config.pet_db, schema_config.pet_db, schema_config.cart_db, schema_config.cart_db, char_id) )
  4407.  		Sql_ShowDebug(sql_handle);
  4408.  
  4409.  	/* remove homunculus */
  4410. @@ -1753,58 +1550,58 @@
  4411.  	mercenary_owner_delete(char_id);
  4412.  
  4413.  	/* delete char's friends list */
  4414. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", friend_db, char_id) )
  4415. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", schema_config.friend_db, char_id) )
  4416.  		Sql_ShowDebug(sql_handle);
  4417.  
  4418.  	/* delete char from other's friend list */
  4419.  	//NOTE: Won't this cause problems for people who are already online? [Skotlex]
  4420. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `friend_id` = '%d'", friend_db, char_id) )
  4421. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `friend_id` = '%d'", schema_config.friend_db, char_id) )
  4422.  		Sql_ShowDebug(sql_handle);
  4423.  
  4424.  #ifdef HOTKEY_SAVING
  4425.  	/* delete hotkeys */
  4426. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", hotkey_db, char_id) )
  4427. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.hotkey_db, char_id) )
  4428.  		Sql_ShowDebug(sql_handle);
  4429.  #endif
  4430.  
  4431.  	/* delete inventory */
  4432. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", inventory_db, char_id) )
  4433. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.inventory_db, char_id) )
  4434.  		Sql_ShowDebug(sql_handle);
  4435.  
  4436.  	/* delete cart inventory */
  4437. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", cart_db, char_id) )
  4438. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.cart_db, char_id) )
  4439.  		Sql_ShowDebug(sql_handle);
  4440.  
  4441.  	/* delete memo areas */
  4442. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, char_id) )
  4443. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.memo_db, char_id) )
  4444.  		Sql_ShowDebug(sql_handle);
  4445.  
  4446.  	/* delete character registry */
  4447. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) )
  4448. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", schema_config.reg_db, char_id) )
  4449.  		Sql_ShowDebug(sql_handle);
  4450.  
  4451.  	/* delete skills */
  4452. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, char_id) )
  4453. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.skill_db, char_id) )
  4454.  		Sql_ShowDebug(sql_handle);
  4455.  
  4456.  	/* delete mails (only received) */
  4457. -	if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `dest_id`='%d'", mail_db, char_id))
  4458. +	if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `dest_id`='%d'", schema_config.mail_db, char_id))
  4459.  		Sql_ShowDebug(sql_handle);
  4460.  
  4461.  #ifdef ENABLE_SC_SAVING
  4462.  	/* status changes */
  4463. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, account_id, char_id) )
  4464. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.scdata_db, account_id, char_id) )
  4465.  		Sql_ShowDebug(sql_handle);
  4466.  #endif
  4467.  
  4468. -	if (log_char) {
  4469. +	if (charserv_config.log_char) {
  4470.  		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`char_msg`,`name`) VALUES (NOW(), '%d', '%d', 'Deleted char (CID %d)', '%s')",
  4471. -			charlog_db, account_id, 0, char_id, esc_name) )
  4472. +			schema_config.charlog_db, account_id, 0, char_id, esc_name) )
  4473.  			Sql_ShowDebug(sql_handle);
  4474.  	}
  4475.  
  4476.  	/* delete character */
  4477. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", char_db, char_id) )
  4478. +	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) )
  4479.  		Sql_ShowDebug(sql_handle);
  4480.  
  4481.  	/* No need as we used inter_guild_leave [Skotlex]
  4482. @@ -1813,7 +1610,7 @@
  4483.  		Sql_ShowDebug(sql_handle);
  4484.  	*/
  4485.  
  4486. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `char_id` = '%d'", guild_db, char_id) )
  4487. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `char_id` = '%d'", schema_config.guild_db, char_id) )
  4488.  		Sql_ShowDebug(sql_handle);
  4489.  	else if( Sql_NumRows(sql_handle) > 0 )
  4490.  		mapif_parse_BreakGuild(0,guild_id);
  4491. @@ -1841,7 +1638,6 @@
  4492.  // Writes char data to the buffer in the format used by the client.
  4493.  // Used in packets 0x6b (chars info) and 0x6d (new char info)
  4494.  // Returns the size
  4495. -#define MAX_CHAR_BUF 144 //Max size (for WFIFOHEAD calls)
  4496.  int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
  4497.  {
  4498.  	unsigned short offset = 0;
  4499. @@ -1908,9 +1704,9 @@
  4500.  #if PACKETVER != 20111116 //2011-11-16 wants 136, ask gravity.
  4501.  	#if PACKETVER >= 20110928
  4502.  		// change slot feature (0 = disabled, otherwise enabled)
  4503. -		if( !char_move_enabled )
  4504. +		if( (charmove_config.char_move_enabled)==0 )
  4505.  			WBUFL(buf,132) = 0;
  4506. -		else if( char_moves_unlimited )
  4507. +		else if( charmove_config.char_moves_unlimited )
  4508.  			WBUFL(buf,132) = 1;
  4509.  		else
  4510.  			WBUFL(buf,132) = max( 0, (int)p->character_moves );
  4511. @@ -1925,101 +1721,9 @@
  4512.  	return 106+offset;
  4513.  }
  4514.  
  4515. -//----------------------------------------
  4516. -// Tell client how many pages, kRO sends 17 (Yommy)
  4517. -//----------------------------------------
  4518. -void char_charlist_notify( int fd, struct char_session_data* sd ){
  4519. -	WFIFOHEAD(fd, 6);
  4520. -	WFIFOW(fd, 0) = 0x9a0;
  4521. -	// pages to req / send them all in 1 until mmo_chars_fromsql can split them up
  4522. -	WFIFOL(fd, 2) = (sd->char_slots>3)?sd->char_slots/3:1; //int TotalCnt (nb page to load)
  4523. -	WFIFOSET(fd,6);
  4524. -}
  4525. -
  4526. -void char_block_character( int fd, struct char_session_data* sd ){
  4527. -	WFIFOHEAD(fd, 4);
  4528. -	WFIFOW(fd, 0) = 0x20d;
  4529. -	WFIFOW(fd, 2) = 4; //packet len
  4530. -	WFIFOSET(fd,4);
  4531. -}
  4532. -
  4533. -void mmo_char_send099d(int fd, struct char_session_data *sd) {
  4534. -	WFIFOHEAD(fd,4 + (MAX_CHARS*MAX_CHAR_BUF));
  4535. -	WFIFOW(fd,0) = 0x99d;
  4536. -	WFIFOW(fd,2) = mmo_chars_fromsql(sd, WFIFOP(fd,4)) + 4;
  4537. -	WFIFOSET(fd,WFIFOW(fd,2));
  4538. -}
  4539. -
  4540. -//struct PACKET_CH_CHARLIST_REQ { 0x0 short PacketType}
  4541. -void char_parse_req_charlist(int fd, struct char_session_data* sd){
  4542. -	mmo_char_send099d(fd,sd);
  4543. -}
  4544. -
  4545. -//----------------------------------------
  4546. -// Function to send characters to a player
  4547. -//----------------------------------------
  4548. -int mmo_char_send006b(int fd, struct char_session_data* sd){
  4549. -	int j, offset = 0;
  4550. -	//bool newvers = (sd->version >= date2version(20100413) );
  4551. -#if PACKETVER >= 20100413
  4552. -	//if(newvers) //20100413
  4553. -		offset += 3;
  4554. -#endif
  4555. -	if (save_log)
  4556. -		ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id);
  4557. -
  4558. -	j = 24 + offset; // offset
  4559. -	WFIFOHEAD(fd,j + MAX_CHARS*MAX_CHAR_BUF);
  4560. -	WFIFOW(fd,0) = 0x6b;
  4561. -#if PACKETVER >= 20100413
  4562. -//	if(newvers){ //20100413
  4563. -		WFIFOB(fd,4) = MAX_CHARS; // Max slots.
  4564. -		WFIFOB(fd,5) = sd->char_slots; // Available slots. (PremiumStartSlot)
  4565. -		WFIFOB(fd,6) = MAX_CHARS; // Premium slots. (Any existent chars past sd->char_slots but within MAX_CHARS will show a 'Premium Service' in red)
  4566. -//	}
  4567. -#endif
  4568. -	memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes
  4569. -	j+=mmo_chars_fromsql(sd, WFIFOP(fd,j));
  4570. -	WFIFOW(fd,2) = j; // packet len
  4571. -	WFIFOSET(fd,j);
  4572. -
  4573. -	return 0;
  4574. -}
  4575. -
  4576. -//----------------------------------------
  4577. -// Notify client about charselect window data [Ind]
  4578. -//----------------------------------------
  4579. -void mmo_char_send082d(int fd, struct char_session_data* sd) {
  4580. -	if (save_log)
  4581. -		ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id);
  4582. -	WFIFOHEAD(fd,29);
  4583. -	WFIFOW(fd,0) = 0x82d;
  4584. -	WFIFOW(fd,2) = 29;
  4585. -	WFIFOB(fd,4) = sd->char_slots;
  4586. -	WFIFOB(fd,5) = MAX_CHARS - sd->char_slots;
  4587. -	WFIFOB(fd,6) = MAX_CHARS - sd->char_slots;
  4588. -	WFIFOB(fd,7) = sd->char_slots;
  4589. -	WFIFOB(fd,8) = sd->char_slots;
  4590. -	memset(WFIFOP(fd,9), 0, 20); // unused bytes
  4591. -	WFIFOSET(fd,29);
  4592. -}
  4593. -
  4594. -void mmo_char_send(int fd, struct char_session_data* sd){
  4595. -	//ShowInfo("sd->version = %d\n",sd->version);
  4596. -#if PACKETVER >= 20130000
  4597. -	//if(sd->version > date2version(20130000) ){
  4598. -		mmo_char_send082d(fd,sd);
  4599. -		char_charlist_notify(fd,sd);
  4600. -		char_block_character(fd,sd);
  4601. -#endif
  4602. -	//}
  4603. -	//@FIXME dump from kro doesn't show 6b transmission
  4604. -	mmo_char_send006b(fd,sd);
  4605. -}
  4606. -
  4607.  int char_married(int pl1, int pl2)
  4608.  {
  4609. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", char_db, pl1) )
  4610. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", schema_config.char_db, pl1) )
  4611.  		Sql_ShowDebug(sql_handle);
  4612.  	else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
  4613.  	{
  4614. @@ -2038,7 +1742,7 @@
  4615.  
  4616.  int char_child(int parent_id, int child_id)
  4617.  {
  4618. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", char_db, parent_id) )
  4619. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", schema_config.char_db, parent_id) )
  4620.  		Sql_ShowDebug(sql_handle);
  4621.  	else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
  4622.  	{
  4623. @@ -2057,7 +1761,7 @@
  4624.  
  4625.  int char_family(int cid1, int cid2, int cid3)
  4626.  {
  4627. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", char_db, cid1, cid2, cid3) )
  4628. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", schema_config.char_db, cid1, cid2, cid3) )
  4629.  		Sql_ShowDebug(sql_handle);
  4630.  	else while( SQL_SUCCESS == Sql_NextRow(sql_handle) )
  4631.  	{
  4632. @@ -2096,8 +1800,9 @@
  4633.  		set_eof(i);
  4634.  }
  4635.  
  4636. -static void char_auth_ok(int fd, struct char_session_data *sd)
  4637. -{
  4638. +
  4639. +
  4640. +void char_auth_ok(int fd, struct char_session_data *sd) {
  4641.  	struct online_char_data* character;
  4642.  
  4643.  	if( (character = (struct online_char_data*)idb_get(online_char_db, sd->account_id)) != NULL )
  4644. @@ -2107,30 +1812,18 @@
  4645.  			mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
  4646.  			if (character->waiting_disconnect == INVALID_TIMER)
  4647.  				character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
  4648. -			WFIFOHEAD(fd,3);
  4649. -			WFIFOW(fd,0) = 0x81;
  4650. -			WFIFOB(fd,2) = 8;
  4651. -			WFIFOSET(fd,3);
  4652. +			char_send_auth_result(fd,8);
  4653.  			return;
  4654.  		}
  4655.  		if (character->fd >= 0 && character->fd != fd)
  4656.  		{	//There's already a connection from this account that hasn't picked a char yet.
  4657. -			WFIFOHEAD(fd,3);
  4658. -			WFIFOW(fd,0) = 0x81;
  4659. -			WFIFOB(fd,2) = 8;
  4660. -			WFIFOSET(fd,3);
  4661. +			char_send_auth_result(fd,8);
  4662.  			return;
  4663.  		}
  4664.  		character->fd = fd;
  4665.  	}
  4666.  
  4667. -	if (login_fd > 0) {
  4668. -		// request account data
  4669. -		WFIFOHEAD(login_fd,6);
  4670. -		WFIFOW(login_fd,0) = 0x2716;
  4671. -		WFIFOL(login_fd,2) = sd->account_id;
  4672. -		WFIFOSET(login_fd,6);
  4673. -	}
  4674. +	char_send_reqaccdata(login_fd,sd); // request account data
  4675.  
  4676.  	// mark session as 'authed'
  4677.  	sd->auth = true;
  4678. @@ -2141,469 +1834,6 @@
  4679.  	// continues when account data is received...
  4680.  }
  4681.  
  4682. -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data);
  4683. -void mapif_server_reset(int id);
  4684. -
  4685. -
  4686. -/// Resets all the data.
  4687. -void loginif_reset(void)
  4688. -{
  4689. -	int id;
  4690. -	// TODO kick everyone out and reset everything or wait for connect and try to reaquire locks [FlavioJS]
  4691. -	for( id = 0; id < ARRAYLENGTH(server); ++id )
  4692. -		mapif_server_reset(id);
  4693. -	flush_fifos();
  4694. -	exit(EXIT_FAILURE);
  4695. -}
  4696. -
  4697. -
  4698. -/// Checks the conditions for the server to stop.
  4699. -/// Releases the cookie when all characters are saved.
  4700. -/// If all the conditions are met, it stops the core loop.
  4701. -void loginif_check_shutdown(void)
  4702. -{
  4703. -	if( runflag != CHARSERVER_ST_SHUTDOWN )
  4704. -		return;
  4705. -	runflag = CORE_ST_STOP;
  4706. -}
  4707. -
  4708. -
  4709. -/// Called when the connection to Login Server is disconnected.
  4710. -void loginif_on_disconnect(void)
  4711. -{
  4712. -	ShowWarning("Connection to Login Server lost.\n\n");
  4713. -}
  4714. -
  4715. -
  4716. -/// Called when all the connection steps are completed.
  4717. -void loginif_on_ready(void)
  4718. -{
  4719. -	int i;
  4720. -
  4721. -	loginif_check_shutdown();
  4722. -
  4723. -	//Send online accounts to login server.
  4724. -	send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0);
  4725. -
  4726. -	// if no map-server already connected, display a message...
  4727. -	ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd > 0 && server[i].map[0] );
  4728. -	if( i == ARRAYLENGTH(server) )
  4729. -		ShowStatus("Awaiting maps from map-server.\n");
  4730. -}
  4731. -
  4732. -
  4733. -int parse_fromlogin(int fd) {
  4734. -	struct char_session_data* sd = NULL;
  4735. -	int i;
  4736. -
  4737. -	// only process data from the login-server
  4738. -	if( fd != login_fd ) {
  4739. -		ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd);
  4740. -		do_close(fd);
  4741. -		return 0;
  4742. -	}
  4743. -
  4744. -	if( session[fd]->flag.eof ) {
  4745. -		do_close(fd);
  4746. -		login_fd = -1;
  4747. -		loginif_on_disconnect();
  4748. -		return 0;
  4749. -	} else if ( session[fd]->flag.ping ) {/* we've reached stall time */
  4750. -		if( DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2) ) {/* we can't wait any longer */
  4751. -			set_eof(fd);
  4752. -			return 0;
  4753. -		} else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */
  4754. -			WFIFOHEAD(fd,2);// sends a ping packet to login server (will receive pong 0x2718)
  4755. -			WFIFOW(fd,0) = 0x2719;
  4756. -			WFIFOSET(fd,2);
  4757. -
  4758. -			session[fd]->flag.ping = 2;
  4759. -		}
  4760. -	}
  4761. -
  4762. -	sd = (struct char_session_data*)session[fd]->session_data;
  4763. -
  4764. -	while(RFIFOREST(fd) >= 2) {
  4765. -		uint16 command = RFIFOW(fd,0);
  4766. -
  4767. -		switch( command )
  4768. -		{
  4769. -
  4770. -		// acknowledgement of connect-to-loginserver request
  4771. -		case 0x2711:
  4772. -			if (RFIFOREST(fd) < 3)
  4773. -				return 0;
  4774. -
  4775. -			if (RFIFOB(fd,2)) {
  4776. -				//printf("connect login server error : %d\n", RFIFOB(fd,2));
  4777. -				ShowError("Can not connect to login-server.\n");
  4778. -				ShowError("The server communication passwords (default s1/p1) are probably invalid.\n");
  4779. -				ShowError("Also, please make sure your login db has the correct communication username/passwords and the gender of the account is S.\n");
  4780. -				ShowError("The communication passwords are set in map_athena.conf and char_athena.conf\n");
  4781. -				set_eof(fd);
  4782. -				return 0;
  4783. -			} else {
  4784. -				ShowStatus("Connected to login-server (connection #%d).\n", fd);
  4785. -				loginif_on_ready();
  4786. -			}
  4787. -			RFIFOSKIP(fd,3);
  4788. -		break;
  4789. -
  4790. -		// acknowledgement of account authentication request
  4791. -		case 0x2713:
  4792. -			if (RFIFOREST(fd) < 25)
  4793. -				return 0;
  4794. -		{
  4795. -			int account_id = RFIFOL(fd,2);
  4796. -			uint32 login_id1 = RFIFOL(fd,6);
  4797. -			uint32 login_id2 = RFIFOL(fd,10);
  4798. -			uint8 sex = RFIFOB(fd,14);
  4799. -			uint8 result = RFIFOB(fd,15);
  4800. -			int request_id = RFIFOL(fd,16);
  4801. -			uint32 version = RFIFOL(fd,20);
  4802. -			uint8 clienttype = RFIFOB(fd,24);
  4803. -			RFIFOSKIP(fd,25);
  4804. -
  4805. -			if( session_isActive(request_id) && (sd=(struct char_session_data*)session[request_id]->session_data) &&
  4806. -				!sd->auth && sd->account_id == account_id && sd->login_id1 == login_id1 && sd->login_id2 == login_id2 && sd->sex == sex )
  4807. -			{
  4808. -				int client_fd = request_id;
  4809. -				sd->version = version;
  4810. -				sd->clienttype = clienttype;
  4811. -				switch( result )
  4812. -				{
  4813. -				case 0:// ok
  4814. -					char_auth_ok(client_fd, sd);
  4815. -					break;
  4816. -				case 1:// auth failed
  4817. -					WFIFOHEAD(client_fd,3);
  4818. -					WFIFOW(client_fd,0) = 0x6c;
  4819. -					WFIFOB(client_fd,2) = 0;// rejected from server
  4820. -					WFIFOSET(client_fd,3);
  4821. -					break;
  4822. -				}
  4823. -			}
  4824. -		}
  4825. -		break;
  4826. -
  4827. -		case 0x2717: // account data
  4828. -			if (RFIFOREST(fd) < 72)
  4829. -				return 0;
  4830. -
  4831. -			// find the authenticated session with this account id
  4832. -			ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->auth && sd->account_id == RFIFOL(fd,2) );
  4833. -			if( i < fd_max )
  4834. -			{
  4835. -				int server_id;
  4836. -				memcpy(sd->email, RFIFOP(fd,6), 40);
  4837. -				sd->expiration_time = (time_t)RFIFOL(fd,46);
  4838. -				sd->group_id = RFIFOB(fd,50);
  4839. -				sd->char_slots = RFIFOB(fd,51);
  4840. -				if( sd->char_slots > MAX_CHARS ) {
  4841. -					ShowError("Account '%d' `character_slots` column is higher than supported MAX_CHARS (%d), update MAX_CHARS in mmo.h! capping to MAX_CHARS...\n",sd->account_id,sd->char_slots);
  4842. -					sd->char_slots = MAX_CHARS;/* cap to maximum */
  4843. -				} else if ( !sd->char_slots )/* no value aka 0 in sql */
  4844. -					sd->char_slots = MAX_CHARS;/* cap to maximum */
  4845. -				safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,52), sizeof(sd->birthdate));
  4846. -				safestrncpy(sd->pincode, (const char*)RFIFOP(fd,63), sizeof(sd->pincode));
  4847. -				sd->pincode_change = (time_t)RFIFOL(fd,68);
  4848. -				ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] );
  4849. -				// continued from char_auth_ok...
  4850. -				if( server_id == ARRAYLENGTH(server) || //server not online, bugreport:2359
  4851. -					(max_connect_user == 0 && sd->group_id != gm_allow_group) ||
  4852. -					( max_connect_user > 0 && count_users() >= max_connect_user && sd->group_id != gm_allow_group ) ) {
  4853. -					// refuse connection (over populated)
  4854. -					WFIFOHEAD(i,3);
  4855. -					WFIFOW(i,0) = 0x6c;
  4856. -					WFIFOW(i,2) = 0;
  4857. -					WFIFOSET(i,3);
  4858. -				} else {
  4859. -					// send characters to player
  4860. -					mmo_char_send(i, sd);
  4861. -#if PACKETVER >=  20110309
  4862. -					if( pincode_enabled ){
  4863. -						// PIN code system enabled
  4864. -						if( strlen( sd->pincode ) <= 0 ){
  4865. -							// No PIN code has been set yet
  4866. -							if( pincode_force ){
  4867. -								pincode_sendstate( i, sd, PINCODE_NEW );
  4868. -							}else{
  4869. -								pincode_sendstate( i, sd, PINCODE_PASSED );
  4870. -							}
  4871. -						}else{
  4872. -							if( !pincode_changetime || ( sd->pincode_change + pincode_changetime ) > time(NULL) ){
  4873. -								struct online_char_data* node = (struct online_char_data*)idb_get( online_char_db, sd->account_id );
  4874. -
  4875. -								if( node != NULL && node->pincode_success ){
  4876. -									// User has already passed the check
  4877. -									pincode_sendstate( i, sd, PINCODE_PASSED );
  4878. -								}else{
  4879. -									// Ask user for his PIN code
  4880. -									pincode_sendstate( i, sd, PINCODE_ASK );
  4881. -								}
  4882. -							}else{
  4883. -								// User hasnt changed his PIN code too long
  4884. -								pincode_sendstate( i, sd, PINCODE_EXPIRED );
  4885. -							}
  4886. -						}
  4887. -					}else{
  4888. -						// PIN code system disabled
  4889. -						pincode_sendstate( i, sd, PINCODE_OK );
  4890. -					}
  4891. -#endif
  4892. -				}
  4893. -			}
  4894. -			RFIFOSKIP(fd,72);
  4895. -		break;
  4896. -
  4897. -		// login-server alive packet
  4898. -		case 0x2718:
  4899. -			if (RFIFOREST(fd) < 2)
  4900. -				return 0;
  4901. -			RFIFOSKIP(fd,2);
  4902. -			session[fd]->flag.ping = 0;
  4903. -		break;
  4904. -
  4905. -		// changesex reply
  4906. -		case 0x2723:
  4907. -			if (RFIFOREST(fd) < 7)
  4908. -				return 0;
  4909. -		{
  4910. -			unsigned char buf[7];
  4911. -
  4912. -			int acc = RFIFOL(fd,2);
  4913. -			int sex = RFIFOB(fd,6);
  4914. -			RFIFOSKIP(fd,7);
  4915. -
  4916. -			if( acc > 0 )
  4917. -			{// TODO: Is this even possible?
  4918. -				int char_id[MAX_CHARS];
  4919. -				int class_[MAX_CHARS];
  4920. -				int guild_id[MAX_CHARS];
  4921. -				int num;
  4922. -				char* data;
  4923. -
  4924. -				struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc);
  4925. -				if( node != NULL )
  4926. -					node->sex = sex;
  4927. -
  4928. -				// get characters
  4929. -				if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc) )
  4930. -					Sql_ShowDebug(sql_handle);
  4931. -				for( i = 0; i < MAX_CHARS && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
  4932. -				{
  4933. -					Sql_GetData(sql_handle, 0, &data, NULL); char_id[i] = atoi(data);
  4934. -					Sql_GetData(sql_handle, 1, &data, NULL); class_[i] = atoi(data);
  4935. -					Sql_GetData(sql_handle, 2, &data, NULL); guild_id[i] = atoi(data);
  4936. -				}
  4937. -				num = i;
  4938. -				for( i = 0; i < num; ++i )
  4939. -				{
  4940. -					if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER ||
  4941. -						class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY ||
  4942. -						class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER ||
  4943. -						class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER ||
  4944. -						class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T ||
  4945. -						class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER ||
  4946. -						class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO )
  4947. -					{
  4948. -						// job modification
  4949. -						if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER )
  4950. -							class_[i] = (sex ? JOB_BARD : JOB_DANCER);
  4951. -						else if( class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY )
  4952. -							class_[i] = (sex ? JOB_CLOWN : JOB_GYPSY);
  4953. -						else if( class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER )
  4954. -							class_[i] = (sex ? JOB_BABY_BARD : JOB_BABY_DANCER);
  4955. -						else if( class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER )
  4956. -							class_[i] = (sex ? JOB_MINSTREL : JOB_WANDERER);
  4957. -						else if( class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T )
  4958. -							class_[i] = (sex ? JOB_MINSTREL_T : JOB_WANDERER_T);
  4959. -						else if( class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER )
  4960. -							class_[i] = (sex ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER);
  4961. -						else if( class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO )
  4962. -							class_[i] = (sex ? JOB_KAGEROU : JOB_OBORO);
  4963. -					}
  4964. -
  4965. -					if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', `head_bottom`='0' WHERE `char_id`='%d'", char_db, class_[i], char_id[i]) )
  4966. -						Sql_ShowDebug(sql_handle);
  4967. -
  4968. -					if( guild_id[i] )// If there is a guild, update the guild_member data [Skotlex]
  4969. -						inter_guild_sex_changed(guild_id[i], acc, char_id[i], sex);
  4970. -				}
  4971. -				Sql_FreeResult(sql_handle);
  4972. -
  4973. -				// disconnect player if online on char-server
  4974. -				disconnect_player(acc);
  4975. -			}
  4976. -
  4977. -			// notify all mapservers about this change
  4978. -			WBUFW(buf,0) = 0x2b0d;
  4979. -			WBUFL(buf,2) = acc;
  4980. -			WBUFB(buf,6) = sex;
  4981. -			mapif_sendall(buf, 7);
  4982. -		}
  4983. -		break;
  4984. -
  4985. -		// reply to an account_reg2 registry request
  4986. -		case 0x2729:
  4987. -			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  4988. -				return 0;
  4989. -
  4990. -		{	//Receive account_reg2 registry, forward to map servers.
  4991. -			unsigned char buf[13+ACCOUNT_REG2_NUM*sizeof(struct global_reg)];
  4992. -			memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2));
  4993. -			WBUFW(buf,0) = 0x3804; //Map server can now receive all kinds of reg values with the same packet. [Skotlex]
  4994. -			mapif_sendall(buf, WBUFW(buf,2));
  4995. -			RFIFOSKIP(fd, RFIFOW(fd,2));
  4996. -		}
  4997. -		break;
  4998. -
  4999. -		// State change of account/ban notification (from login-server)
  5000. -		case 0x2731:
  5001. -			if (RFIFOREST(fd) < 11)
  5002. -				return 0;
  5003. -
  5004. -		{	// send to all map-servers to disconnect the player
  5005. -			unsigned char buf[11];
  5006. -			WBUFW(buf,0) = 0x2b14;
  5007. -			WBUFL(buf,2) = RFIFOL(fd,2);
  5008. -			WBUFB(buf,6) = RFIFOB(fd,6); // 0: change of statut, 1: ban
  5009. -			WBUFL(buf,7) = RFIFOL(fd,7); // status or final date of a banishment
  5010. -			mapif_sendall(buf, 11);
  5011. -		}
  5012. -			// disconnect player if online on char-server
  5013. -			disconnect_player(RFIFOL(fd,2));
  5014. -
  5015. -			RFIFOSKIP(fd,11);
  5016. -		break;
  5017. -
  5018. -		// Login server request to kick a character out. [Skotlex]
  5019. -		case 0x2734:
  5020. -			if (RFIFOREST(fd) < 6)
  5021. -				return 0;
  5022. -		{
  5023. -			int aid = RFIFOL(fd,2);
  5024. -			struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid);
  5025. -			RFIFOSKIP(fd,6);
  5026. -			if( character != NULL )
  5027. -			{// account is already marked as online!
  5028. -				if( character->server > -1 )
  5029. -				{	//Kick it from the map server it is on.
  5030. -					mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
  5031. -					if (character->waiting_disconnect == INVALID_TIMER)
  5032. -						character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, chardb_waiting_disconnect, character->account_id, 0);
  5033. -				}
  5034. -				else
  5035. -				{// Manual kick from char server.
  5036. -					struct char_session_data *tsd;
  5037. -					int i;
  5038. -					ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid );
  5039. -					if( i < fd_max )
  5040. -					{
  5041. -						WFIFOHEAD(i,3);
  5042. -						WFIFOW(i,0) = 0x81;
  5043. -						WFIFOB(i,2) = 2; // "Someone has already logged in with this id"
  5044. -						WFIFOSET(i,3);
  5045. -						set_eof(i);
  5046. -					}
  5047. -					else // still moving to the map-server
  5048. -						set_char_offline(-1, aid);
  5049. -				}
  5050. -			}
  5051. -			idb_remove(auth_db, aid);// reject auth attempts from map-server
  5052. -		}
  5053. -		break;
  5054. -
  5055. -		// ip address update signal from login server
  5056. -		case 0x2735:
  5057. -		{
  5058. -			unsigned char buf[2];
  5059. -			uint32 new_ip = 0;
  5060. -
  5061. -			WBUFW(buf,0) = 0x2b1e;
  5062. -			mapif_sendall(buf, 2);
  5063. -
  5064. -			new_ip = host2ip(login_ip_str);
  5065. -			if (new_ip && new_ip != login_ip)
  5066. -				login_ip = new_ip; //Update login ip, too.
  5067. -
  5068. -			new_ip = host2ip(char_ip_str);
  5069. -			if (new_ip && new_ip != char_ip)
  5070. -			{	//Update ip.
  5071. -				char_ip = new_ip;
  5072. -				ShowInfo("Updating IP for [%s].\n", char_ip_str);
  5073. -				// notify login server about the change
  5074. -				WFIFOHEAD(fd,6);
  5075. -				WFIFOW(fd,0) = 0x2736;
  5076. -				WFIFOL(fd,2) = htonl(char_ip);
  5077. -				WFIFOSET(fd,6);
  5078. -			}
  5079. -
  5080. -			RFIFOSKIP(fd,2);
  5081. -		}
  5082. -		break;
  5083. -
  5084. -		default:
  5085. -			ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command);
  5086. -			set_eof(fd);
  5087. -			return 0;
  5088. -		}
  5089. -	}
  5090. -
  5091. -	RFIFOFLUSH(fd);
  5092. -	return 0;
  5093. -}
  5094. -
  5095. -int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data);
  5096. -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data);
  5097. -
  5098. -void do_init_loginif(void)
  5099. -{
  5100. -	// establish char-login connection if not present
  5101. -	add_timer_func_list(check_connect_login_server, "check_connect_login_server");
  5102. -	add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000);
  5103. -
  5104. -	// send a list of all online account IDs to login server
  5105. -	add_timer_func_list(send_accounts_tologin, "send_accounts_tologin");
  5106. -	add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour
  5107. -}
  5108. -
  5109. -void do_final_loginif(void)
  5110. -{
  5111. -	if( login_fd != -1 )
  5112. -	{
  5113. -		do_close(login_fd);
  5114. -		login_fd = -1;
  5115. -	}
  5116. -}
  5117. -
  5118. -int request_accreg2(int account_id, int char_id)
  5119. -{
  5120. -	if (login_fd > 0) {
  5121. -		WFIFOHEAD(login_fd,10);
  5122. -		WFIFOW(login_fd,0) = 0x272e;
  5123. -		WFIFOL(login_fd,2) = account_id;
  5124. -		WFIFOL(login_fd,6) = char_id;
  5125. -		WFIFOSET(login_fd,10);
  5126. -		return 1;
  5127. -	}
  5128. -	return 0;
  5129. -}
  5130. -
  5131. -//Send packet forward to login-server for account saving
  5132. -int save_accreg2(unsigned char* buf, int len)
  5133. -{
  5134. -	if (login_fd > 0) {
  5135. -		WFIFOHEAD(login_fd,len+4);
  5136. -		memcpy(WFIFOP(login_fd,4), buf, len);
  5137. -		WFIFOW(login_fd,0) = 0x2728;
  5138. -		WFIFOW(login_fd,2) = len+4;
  5139. -		WFIFOSET(login_fd,len+4);
  5140. -		return 1;
  5141. -	}
  5142. -	return 0;
  5143. -}
  5144. -
  5145.  void char_read_fame_list(void)
  5146.  {
  5147.  	int i;
  5148. @@ -2615,7 +1845,7 @@
  5149.  	memset(chemist_fame_list, 0, sizeof(chemist_fame_list));
  5150.  	memset(taekwon_fame_list, 0, sizeof(taekwon_fame_list));
  5151.  	// Build Blacksmith ranking list
  5152. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_BLACKSMITH, JOB_WHITESMITH, JOB_BABY_BLACKSMITH, JOB_MECHANIC, JOB_MECHANIC_T, JOB_BABY_MECHANIC, fame_list_size_smith) )
  5153. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", schema_config.char_db, JOB_BLACKSMITH, JOB_WHITESMITH, JOB_BABY_BLACKSMITH, JOB_MECHANIC, JOB_MECHANIC_T, JOB_BABY_MECHANIC, fame_list_size_smith) )
  5154.  		Sql_ShowDebug(sql_handle);
  5155.  	for( i = 0; i < fame_list_size_smith && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
  5156.  	{
  5157. @@ -2630,7 +1860,7 @@
  5158.  		memcpy(smith_fame_list[i].name, data, min(len, NAME_LENGTH));
  5159.  	}
  5160.  	// Build Alchemist ranking list
  5161. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_ALCHEMIST, JOB_CREATOR, JOB_BABY_ALCHEMIST, JOB_GENETIC, JOB_GENETIC_T, JOB_BABY_GENETIC, fame_list_size_chemist) )
  5162. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", schema_config.char_db, JOB_ALCHEMIST, JOB_CREATOR, JOB_BABY_ALCHEMIST, JOB_GENETIC, JOB_GENETIC_T, JOB_BABY_GENETIC, fame_list_size_chemist) )
  5163.  		Sql_ShowDebug(sql_handle);
  5164.  	for( i = 0; i < fame_list_size_chemist && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
  5165.  	{
  5166. @@ -2645,7 +1875,7 @@
  5167.  		memcpy(chemist_fame_list[i].name, data, min(len, NAME_LENGTH));
  5168.  	}
  5169.  	// Build Taekwon ranking list
  5170. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_TAEKWON, fame_list_size_taekwon) )
  5171. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", schema_config.char_db, JOB_TAEKWON, fame_list_size_taekwon) )
  5172.  		Sql_ShowDebug(sql_handle);
  5173.  	for( i = 0; i < fame_list_size_taekwon && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
  5174.  	{
  5175. @@ -2662,53 +1892,7 @@
  5176.  	Sql_FreeResult(sql_handle);
  5177.  }
  5178.  
  5179. -// Send map-servers the fame ranking lists
  5180. -int char_send_fame_list(int fd)
  5181. -{
  5182. -	int i, len = 8;
  5183. -	unsigned char buf[32000];
  5184.  
  5185. -	WBUFW(buf,0) = 0x2b1b;
  5186. -
  5187. -	for(i = 0; i < fame_list_size_smith && smith_fame_list[i].id; i++) {
  5188. -		memcpy(WBUFP(buf, len), &smith_fame_list[i], sizeof(struct fame_list));
  5189. -		len += sizeof(struct fame_list);
  5190. -	}
  5191. -	// add blacksmith's block length
  5192. -	WBUFW(buf, 6) = len;
  5193. -
  5194. -	for(i = 0; i < fame_list_size_chemist && chemist_fame_list[i].id; i++) {
  5195. -		memcpy(WBUFP(buf, len), &chemist_fame_list[i], sizeof(struct fame_list));
  5196. -		len += sizeof(struct fame_list);
  5197. -	}
  5198. -	// add alchemist's block length
  5199. -	WBUFW(buf, 4) = len;
  5200. -
  5201. -	for(i = 0; i < fame_list_size_taekwon && taekwon_fame_list[i].id; i++) {
  5202. -		memcpy(WBUFP(buf, len), &taekwon_fame_list[i], sizeof(struct fame_list));
  5203. -		len += sizeof(struct fame_list);
  5204. -	}
  5205. -	// add total packet length
  5206. -	WBUFW(buf, 2) = len;
  5207. -
  5208. -	if (fd != -1)
  5209. -		mapif_send(fd, buf, len);
  5210. -	else
  5211. -		mapif_sendall(buf, len);
  5212. -
  5213. -	return 0;
  5214. -}
  5215. -
  5216. -void char_update_fame_list(int type, int index, int fame)
  5217. -{
  5218. -	unsigned char buf[8];
  5219. -	WBUFW(buf,0) = 0x2b22;
  5220. -	WBUFB(buf,2) = type;
  5221. -	WBUFB(buf,3) = index;
  5222. -	WBUFL(buf,4) = fame;
  5223. -	mapif_sendall(buf, 8);
  5224. -}
  5225. -
  5226.  //Loads a character's name and stores it in the buffer given (must be NAME_LENGTH in size)
  5227.  //Returns 1 on found, 0 on not found (buffer is filled with Unknown char name)
  5228.  int char_loadName(int char_id, char* name)
  5229. @@ -2716,7 +1900,7 @@
  5230.  	char* data;
  5231.  	size_t len;
  5232.  
  5233. -	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) )
  5234. +	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) )
  5235.  		Sql_ShowDebug(sql_handle);
  5236.  	else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
  5237.  	{
  5238. @@ -2726,7 +1910,7 @@
  5239.  	}
  5240.  	else
  5241.  	{
  5242. -		safestrncpy(name, unknown_char_name, NAME_LENGTH);
  5243. +		safestrncpy(name, charserv_config.unknown_char_name, NAME_LENGTH);
  5244.  	}
  5245.  	return 0;
  5246.  }
  5247. @@ -2734,806 +1918,6 @@
  5248.  int search_mapserver(unsigned short map, uint32 ip, uint16 port);
  5249.  
  5250.  
  5251. -/// Initializes a server structure.
  5252. -void mapif_server_init(int id)
  5253. -{
  5254. -	memset(&server[id], 0, sizeof(server[id]));
  5255. -	server[id].fd = -1;
  5256. -}
  5257. -
  5258. -
  5259. -/// Destroys a server structure.
  5260. -void mapif_server_destroy(int id)
  5261. -{
  5262. -	if( server[id].fd == -1 )
  5263. -	{
  5264. -		do_close(server[id].fd);
  5265. -		server[id].fd = -1;
  5266. -	}
  5267. -}
  5268. -
  5269. -
  5270. -/// Resets all the data related to a server.
  5271. -void mapif_server_reset(int id)
  5272. -{
  5273. -	int i,j;
  5274. -	unsigned char buf[16384];
  5275. -	int fd = server[id].fd;
  5276. -	//Notify other map servers that this one is gone. [Skotlex]
  5277. -	WBUFW(buf,0) = 0x2b20;
  5278. -	WBUFL(buf,4) = htonl(server[id].ip);
  5279. -	WBUFW(buf,8) = htons(server[id].port);
  5280. -	j = 0;
  5281. -	for(i = 0; i < MAX_MAP_PER_SERVER; i++)
  5282. -		if (server[id].map[i])
  5283. -			WBUFW(buf,10+(j++)*4) = server[id].map[i];
  5284. -	if (j > 0) {
  5285. -		WBUFW(buf,2) = j * 4 + 10;
  5286. -		mapif_sendallwos(fd, buf, WBUFW(buf,2));
  5287. -	}
  5288. -	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `index`='%d'", ragsrvinfo_db, server[id].fd) )
  5289. -		Sql_ShowDebug(sql_handle);
  5290. -	online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server.
  5291. -	mapif_server_destroy(id);
  5292. -	mapif_server_init(id);
  5293. -}
  5294. -
  5295. -
  5296. -/// Called when the connection to a Map Server is disconnected.
  5297. -void mapif_on_disconnect(int id)
  5298. -{
  5299. -	ShowStatus("Map-server #%d has disconnected.\n", id);
  5300. -	mapif_server_reset(id);
  5301. -}
  5302. -
  5303. -
  5304. -int parse_frommap(int fd)
  5305. -{
  5306. -	int i, j;
  5307. -	int id;
  5308. -
  5309. -	ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd );
  5310. -	if( id == ARRAYLENGTH(server) )
  5311. -	{// not a map server
  5312. -		ShowDebug("parse_frommap: Disconnecting invalid session #%d (is not a map-server)\n", fd);
  5313. -		do_close(fd);
  5314. -		return 0;
  5315. -	}
  5316. -	if( session[fd]->flag.eof )
  5317. -	{
  5318. -		do_close(fd);
  5319. -		server[id].fd = -1;
  5320. -		mapif_on_disconnect(id);
  5321. -		return 0;
  5322. -	}
  5323. -
  5324. -	while(RFIFOREST(fd) >= 2){
  5325. -		switch(RFIFOW(fd,0)){
  5326. -
  5327. -		case 0x2afa: // Receiving map names list from the map-server
  5328. -			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  5329. -				return 0;
  5330. -
  5331. -			memset(server[id].map, 0, sizeof(server[id].map));
  5332. -			j = 0;
  5333. -			for(i = 4; i < RFIFOW(fd,2); i += 4) {
  5334. -				server[id].map[j] = RFIFOW(fd,i);
  5335. -				j++;
  5336. -			}
  5337. -
  5338. -			ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
  5339. -						id, j, CONVIP(server[id].ip), server[id].port);
  5340. -			ShowStatus("Map-server %d loading complete.\n", id);
  5341. -
  5342. -			// send name for wisp to player
  5343. -			WFIFOHEAD(fd, 3 + NAME_LENGTH);
  5344. -			WFIFOW(fd,0) = 0x2afb;
  5345. -			WFIFOB(fd,2) = 0;
  5346. -			memcpy(WFIFOP(fd,3), wisp_server_name, NAME_LENGTH);
  5347. -			WFIFOSET(fd,3+NAME_LENGTH);
  5348. -
  5349. -			char_send_fame_list(fd); //Send fame list.
  5350. -
  5351. -			{
  5352. -			unsigned char buf[16384];
  5353. -			int x;
  5354. -			if (j == 0) {
  5355. -				ShowWarning("Map-server %d has NO maps.\n", id);
  5356. -			} else {
  5357. -				// Transmitting maps information to the other map-servers
  5358. -				WBUFW(buf,0) = 0x2b04;
  5359. -				WBUFW(buf,2) = j * 4 + 10;
  5360. -				WBUFL(buf,4) = htonl(server[id].ip);
  5361. -				WBUFW(buf,8) = htons(server[id].port);
  5362. -				memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4);
  5363. -				mapif_sendallwos(fd, buf, WBUFW(buf,2));
  5364. -			}
  5365. -			// Transmitting the maps of the other map-servers to the new map-server
  5366. -			for(x = 0; x < ARRAYLENGTH(server); x++) {
  5367. -				if (server[x].fd > 0 && x != id) {
  5368. -					WFIFOHEAD(fd,10 +4*ARRAYLENGTH(server[x].map));
  5369. -					WFIFOW(fd,0) = 0x2b04;
  5370. -					WFIFOL(fd,4) = htonl(server[x].ip);
  5371. -					WFIFOW(fd,8) = htons(server[x].port);
  5372. -					j = 0;
  5373. -					for(i = 0; i < ARRAYLENGTH(server[x].map); i++)
  5374. -						if (server[x].map[i])
  5375. -							WFIFOW(fd,10+(j++)*4) = server[x].map[i];
  5376. -					if (j > 0) {
  5377. -						WFIFOW(fd,2) = j * 4 + 10;
  5378. -						WFIFOSET(fd,WFIFOW(fd,2));
  5379. -					}
  5380. -				}
  5381. -			}
  5382. -			}
  5383. -			RFIFOSKIP(fd,RFIFOW(fd,2));
  5384. -		break;
  5385. -
  5386. -		case 0x2afc: //Packet command is now used for sc_data request. [Skotlex]
  5387. -			if (RFIFOREST(fd) < 10)
  5388. -				return 0;
  5389. -		{
  5390. -#ifdef ENABLE_SC_SAVING
  5391. -			int aid, cid;
  5392. -			aid = RFIFOL(fd,2);
  5393. -			cid = RFIFOL(fd,6);
  5394. -			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'",
  5395. -				scdata_db, aid, cid) )
  5396. -			{
  5397. -				Sql_ShowDebug(sql_handle);
  5398. -				break;
  5399. -			}
  5400. -			if( Sql_NumRows(sql_handle) > 0 )
  5401. -			{
  5402. -				struct status_change_data scdata;
  5403. -				int count;
  5404. -				char* data;
  5405. -
  5406. -				WFIFOHEAD(fd,14+50*sizeof(struct status_change_data));
  5407. -				WFIFOW(fd,0) = 0x2b1d;
  5408. -				WFIFOL(fd,4) = aid;
  5409. -				WFIFOL(fd,8) = cid;
  5410. -				for( count = 0; count < 50 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count )
  5411. -				{
  5412. -					Sql_GetData(sql_handle, 0, &data, NULL); scdata.type = atoi(data);
  5413. -					Sql_GetData(sql_handle, 1, &data, NULL); scdata.tick = atoi(data);
  5414. -					Sql_GetData(sql_handle, 2, &data, NULL); scdata.val1 = atoi(data);
  5415. -					Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data);
  5416. -					Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data);
  5417. -					Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data);
  5418. -					memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data));
  5419. -				}
  5420. -				if (count >= 50)
  5421. -					ShowWarning("Too many status changes for %d:%d, some of them were not loaded.\n", aid, cid);
  5422. -				if (count > 0)
  5423. -				{
  5424. -					WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data);
  5425. -					WFIFOW(fd,12) = count;
  5426. -					WFIFOSET(fd,WFIFOW(fd,2));
  5427. -
  5428. -					//Clear the data once loaded.
  5429. -					if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, aid, cid) )
  5430. -						Sql_ShowDebug(sql_handle);
  5431. -				}
  5432. -			}
  5433. -			Sql_FreeResult(sql_handle);
  5434. -#endif
  5435. -			RFIFOSKIP(fd, 10);
  5436. -		}
  5437. -		break;
  5438. -
  5439. -		case 0x2afe: //set MAP user count
  5440. -			if (RFIFOREST(fd) < 4)
  5441. -				return 0;
  5442. -			if (RFIFOW(fd,2) != server[id].users) {
  5443. -				server[id].users = RFIFOW(fd,2);
  5444. -				ShowInfo("User Count: %d (Server: %d)\n", server[id].users, id);
  5445. -			}
  5446. -			RFIFOSKIP(fd, 4);
  5447. -			break;
  5448. -
  5449. -		case 0x2aff: //set MAP users
  5450. -			if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2))
  5451. -				return 0;
  5452. -		{
  5453. -			//TODO: When data mismatches memory, update guild/party online/offline states.
  5454. -			int aid, cid;
  5455. -			struct online_char_data* character;
  5456. -
  5457. -			server[id].users = RFIFOW(fd,4);
  5458. -			online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown'
  5459. -			for(i = 0; i < server[id].users; i++) {
  5460. -				aid = RFIFOL(fd,6+i*8);
  5461. -				cid = RFIFOL(fd,6+i*8+4);
  5462. -				character = idb_ensure(online_char_db, aid, create_online_char_data);
  5463. -				if( character->server > -1 && character->server != id )
  5464. -				{
  5465. -					ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n",
  5466. -						character->account_id, character->char_id, character->server, id, aid, cid);
  5467. -					mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
  5468. -				}
  5469. -				character->server = id;
  5470. -				character->char_id = cid;
  5471. -			}
  5472. -			//If any chars remain in -2, they will be cleaned in the cleanup timer.
  5473. -			RFIFOSKIP(fd,RFIFOW(fd,2));
  5474. -		}
  5475. -		break;
  5476. -
  5477. -		case 0x2b01: // Receive character data from map-server for saving
  5478. -			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  5479. -				return 0;
  5480. -		{
  5481. -			int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2);
  5482. -			struct online_char_data* character;
  5483. -
  5484. -			if (size - 13 != sizeof(struct mmo_charstatus))
  5485. -			{
  5486. -				ShowError("parse_from_map (save-char): Size mismatch! %d != %d\n", size-13, sizeof(struct mmo_charstatus));
  5487. -				RFIFOSKIP(fd,size);
  5488. -				break;
  5489. -			}
  5490. -			//Check account only if this ain't final save. Final-save goes through because of the char-map reconnect
  5491. -			if (RFIFOB(fd,12) || RFIFOB(fd,13) || (
  5492. -				(character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL &&
  5493. -				character->char_id == cid))
  5494. -			{
  5495. -				struct mmo_charstatus char_dat;
  5496. -				memcpy(&char_dat, RFIFOP(fd,13), sizeof(struct mmo_charstatus));
  5497. -				mmo_char_tosql(cid, &char_dat);
  5498. -			} else {	//This may be valid on char-server reconnection, when re-sending characters that already logged off.
  5499. -				ShowError("parse_from_map (save-char): Received data for non-existant/offline character (%d:%d).\n", aid, cid);
  5500. -				set_char_online(id, cid, aid);
  5501. -			}
  5502. -
  5503. -			if (RFIFOB(fd,12))
  5504. -			{	//Flag, set character offline after saving. [Skotlex]
  5505. -				set_char_offline(cid, aid);
  5506. -				WFIFOHEAD(fd,10);
  5507. -				WFIFOW(fd,0) = 0x2b21; //Save ack only needed on final save.
  5508. -				WFIFOL(fd,2) = aid;
  5509. -				WFIFOL(fd,6) = cid;
  5510. -				WFIFOSET(fd,10);
  5511. -			}
  5512. -			RFIFOSKIP(fd,size);
  5513. -		}
  5514. -		break;
  5515. -
  5516. -		case 0x2b02: // req char selection
  5517. -			if( RFIFOREST(fd) < 18 )
  5518. -				return 0;
  5519. -			else{
  5520. -				int account_id = RFIFOL(fd,2);
  5521. -				uint32 login_id1 = RFIFOL(fd,6);
  5522. -				uint32 login_id2 = RFIFOL(fd,10);
  5523. -				uint32 ip = RFIFOL(fd,14);
  5524. -				RFIFOSKIP(fd,18);
  5525. -
  5526. -				if( runflag != CHARSERVER_ST_RUNNING ){
  5527. -					WFIFOHEAD(fd,7);
  5528. -					WFIFOW(fd,0) = 0x2b03;
  5529. -					WFIFOL(fd,2) = account_id;
  5530. -					WFIFOB(fd,6) = 0;// not ok
  5531. -					WFIFOSET(fd,7);
  5532. -				}else{
  5533. -					struct auth_node* node;
  5534. -
  5535. -					// create temporary auth entry
  5536. -					CREATE(node, struct auth_node, 1);
  5537. -					node->account_id = account_id;
  5538. -					node->char_id = 0;
  5539. -					node->login_id1 = login_id1;
  5540. -					node->login_id2 = login_id2;
  5541. -					//node->sex = 0;
  5542. -					node->ip = ntohl(ip);
  5543. -					//node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
  5544. -					//node->gmlevel = 0;
  5545. -					idb_put(auth_db, account_id, node);
  5546. -
  5547. -					//Set char to "@ char select" in online db [Kevin]
  5548. -					set_char_charselect(account_id);
  5549. -
  5550. -					{
  5551. -						struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, account_id);
  5552. -
  5553. -						if( character != NULL ){
  5554. -							character->pincode_success = true;
  5555. -						}
  5556. -					}
  5557. -
  5558. -					WFIFOHEAD(fd,7);
  5559. -					WFIFOW(fd,0) = 0x2b03;
  5560. -					WFIFOL(fd,2) = account_id;
  5561. -					WFIFOB(fd,6) = 1;// ok
  5562. -					WFIFOSET(fd,7);
  5563. -				}
  5564. -			}
  5565. -		break;
  5566. -
  5567. -		case 0x2b05: // request "change map server"
  5568. -			if (RFIFOREST(fd) < 39)
  5569. -				return 0;
  5570. -		{
  5571. -			int map_id, map_fd = -1;
  5572. -			struct mmo_charstatus* char_data;
  5573. -			struct mmo_charstatus char_dat;
  5574. -
  5575. -			map_id = search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port.
  5576. -			if (map_id >= 0)
  5577. -				map_fd = server[map_id].fd;
  5578. -			//Char should just had been saved before this packet, so this should be safe. [Skotlex]
  5579. -			char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
  5580. -			if (char_data == NULL) {	//Really shouldn't happen.
  5581. -				mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true);
  5582. -				char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
  5583. -			}
  5584. -
  5585. -			if( runflag == CHARSERVER_ST_RUNNING &&
  5586. -				session_isActive(map_fd) &&
  5587. -				char_data )
  5588. -			{	//Send the map server the auth of this player.
  5589. -				struct online_char_data* data;
  5590. -				struct auth_node* node;
  5591. -
  5592. -				//Update the "last map" as this is where the player must be spawned on the new map server.
  5593. -				char_data->last_point.map = RFIFOW(fd,18);
  5594. -				char_data->last_point.x = RFIFOW(fd,20);
  5595. -				char_data->last_point.y = RFIFOW(fd,22);
  5596. -				char_data->sex = RFIFOB(fd,30);
  5597. -
  5598. -				// create temporary auth entry
  5599. -				CREATE(node, struct auth_node, 1);
  5600. -				node->account_id = RFIFOL(fd,2);
  5601. -				node->char_id = RFIFOL(fd,14);
  5602. -				node->login_id1 = RFIFOL(fd,6);
  5603. -				node->login_id2 = RFIFOL(fd,10);
  5604. -				node->sex = RFIFOB(fd,30);
  5605. -				node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing)
  5606. -				node->ip = ntohl(RFIFOL(fd,31));
  5607. -				node->group_id = RFIFOL(fd,35);
  5608. -				node->changing_mapservers = 1;
  5609. -				idb_put(auth_db, RFIFOL(fd,2), node);
  5610. -
  5611. -				data = idb_ensure(online_char_db, RFIFOL(fd,2), create_online_char_data);
  5612. -				data->char_id = char_data->char_id;
  5613. -				data->server = map_id; //Update server where char is.
  5614. -
  5615. -				//Reply with an ack.
  5616. -				WFIFOHEAD(fd,30);
  5617. -				WFIFOW(fd,0) = 0x2b06;
  5618. -				memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28);
  5619. -				WFIFOSET(fd,30);
  5620. -			} else { //Reply with nak
  5621. -				WFIFOHEAD(fd,30);
  5622. -				WFIFOW(fd,0) = 0x2b06;
  5623. -				memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28);
  5624. -				WFIFOL(fd,6) = 0; //Set login1 to 0.
  5625. -				WFIFOSET(fd,30);
  5626. -			}
  5627. -			RFIFOSKIP(fd,39);
  5628. -		}
  5629. -		break;
  5630. -
  5631. -		case 0x2b07: // Remove RFIFOL(fd,6) (friend_id) from RFIFOL(fd,2) (char_id) friend list [Ind]
  5632. -			if (RFIFOREST(fd) < 10)
  5633. -				return 0;
  5634. -			{
  5635. -				int char_id, friend_id;
  5636. -				char_id = RFIFOL(fd,2);
  5637. -				friend_id = RFIFOL(fd,6);
  5638. -				if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `friend_id`='%d' LIMIT 1",
  5639. -					friend_db, char_id, friend_id) ) {
  5640. -					Sql_ShowDebug(sql_handle);
  5641. -					break;
  5642. -				}
  5643. -				RFIFOSKIP(fd,10);
  5644. -			}
  5645. -		break;
  5646. -
  5647. -		case 0x2b08: // char name request
  5648. -			if (RFIFOREST(fd) < 6)
  5649. -				return 0;
  5650. -
  5651. -			WFIFOHEAD(fd,30);
  5652. -			WFIFOW(fd,0) = 0x2b09;
  5653. -			WFIFOL(fd,2) = RFIFOL(fd,2);
  5654. -			char_loadName((int)RFIFOL(fd,2), (char*)WFIFOP(fd,6));
  5655. -			WFIFOSET(fd,30);
  5656. -
  5657. -			RFIFOSKIP(fd,6);
  5658. -		break;
  5659. -
  5660. -		case 0x2b0c: // Map server send information to change an email of an account -> login-server
  5661. -			if (RFIFOREST(fd) < 86)
  5662. -				return 0;
  5663. -			if (login_fd > 0) { // don't send request if no login-server
  5664. -				WFIFOHEAD(login_fd,86);
  5665. -				memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0),86); // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
  5666. -				WFIFOW(login_fd,0) = 0x2722;
  5667. -				WFIFOSET(login_fd,86);
  5668. -			}
  5669. -			RFIFOSKIP(fd, 86);
  5670. -		break;
  5671. -
  5672. -		case 0x2b0e: // Request from map-server to change an account's status (will just be forwarded to login server)
  5673. -			if (RFIFOREST(fd) < 44)
  5674. -				return 0;
  5675. -		{
  5676. -			int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline
  5677. -			char esc_name[NAME_LENGTH*2+1];
  5678. -
  5679. -			int acc = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request)
  5680. -			const char* name = (char*)RFIFOP(fd,6); // name of the target character
  5681. -			int type = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban
  5682. -			short year = RFIFOW(fd,32);
  5683. -			short month = RFIFOW(fd,34);
  5684. -			short day = RFIFOW(fd,36);
  5685. -			short hour = RFIFOW(fd,38);
  5686. -			short minute = RFIFOW(fd,40);
  5687. -			short second = RFIFOW(fd,42);
  5688. -			RFIFOSKIP(fd,44);
  5689. -
  5690. -			Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
  5691. -			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) )
  5692. -				Sql_ShowDebug(sql_handle);
  5693. -			else
  5694. -			if( Sql_NumRows(sql_handle) == 0 )
  5695. -			{
  5696. -				result = 1; // 1-player not found
  5697. -			}
  5698. -			else
  5699. -			if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  5700. -				Sql_ShowDebug(sql_handle);
  5701. -				//FIXME: set proper result value?
  5702. -			else
  5703. -			{
  5704. -				char name[NAME_LENGTH];
  5705. -				int account_id;
  5706. -				char* data;
  5707. -
  5708. -				Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
  5709. -				Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
  5710. -
  5711. -				if( login_fd <= 0 )
  5712. -					result = 3; // 3-login-server offline
  5713. -				//FIXME: need to move this check to login server [ultramage]
  5714. -//				else
  5715. -//				if( acc != -1 && isGM(acc) < isGM(account_id) )
  5716. -//					result = 2; // 2-gm level too low
  5717. -				else
  5718. -				switch( type ) {
  5719. -				case 1: // block
  5720. -						WFIFOHEAD(login_fd,10);
  5721. -						WFIFOW(login_fd,0) = 0x2724;
  5722. -						WFIFOL(login_fd,2) = account_id;
  5723. -						WFIFOL(login_fd,6) = 5; // new account status
  5724. -						WFIFOSET(login_fd,10);
  5725. -				break;
  5726. -				case 2: // ban
  5727. -						WFIFOHEAD(login_fd,18);
  5728. -						WFIFOW(login_fd, 0) = 0x2725;
  5729. -						WFIFOL(login_fd, 2) = account_id;
  5730. -						WFIFOW(login_fd, 6) = year;
  5731. -						WFIFOW(login_fd, 8) = month;
  5732. -						WFIFOW(login_fd,10) = day;
  5733. -						WFIFOW(login_fd,12) = hour;
  5734. -						WFIFOW(login_fd,14) = minute;
  5735. -						WFIFOW(login_fd,16) = second;
  5736. -						WFIFOSET(login_fd,18);
  5737. -				break;
  5738. -				case 3: // unblock
  5739. -						WFIFOHEAD(login_fd,10);
  5740. -						WFIFOW(login_fd,0) = 0x2724;
  5741. -						WFIFOL(login_fd,2) = account_id;
  5742. -						WFIFOL(login_fd,6) = 0; // new account status
  5743. -						WFIFOSET(login_fd,10);
  5744. -				break;
  5745. -				case 4: // unban
  5746. -						WFIFOHEAD(login_fd,6);
  5747. -						WFIFOW(login_fd,0) = 0x272a;
  5748. -						WFIFOL(login_fd,2) = account_id;
  5749. -						WFIFOSET(login_fd,6);
  5750. -				break;
  5751. -				case 5: // changesex
  5752. -						WFIFOHEAD(login_fd,6);
  5753. -						WFIFOW(login_fd,0) = 0x2727;
  5754. -						WFIFOL(login_fd,2) = account_id;
  5755. -						WFIFOSET(login_fd,6);
  5756. -				break;
  5757. -				}
  5758. -			}
  5759. -
  5760. -			Sql_FreeResult(sql_handle);
  5761. -
  5762. -			// send answer if a player ask, not if the server ask
  5763. -			if( acc != -1 && type != 5) { // Don't send answer for changesex
  5764. -				WFIFOHEAD(fd,34);
  5765. -				WFIFOW(fd, 0) = 0x2b0f;
  5766. -				WFIFOL(fd, 2) = acc;
  5767. -				safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH);
  5768. -				WFIFOW(fd,30) = type;
  5769. -				WFIFOW(fd,32) = result;
  5770. -				WFIFOSET(fd,34);
  5771. -			}
  5772. -		}
  5773. -		break;
  5774. -
  5775. -		case 0x2b10: // Update and send fame ranking list
  5776. -			if (RFIFOREST(fd) < 11)
  5777. -				return 0;
  5778. -		{
  5779. -			int cid = RFIFOL(fd, 2);
  5780. -			int fame = RFIFOL(fd, 6);
  5781. -			char type = RFIFOB(fd, 10);
  5782. -			int size;
  5783. -			struct fame_list* list;
  5784. -			int player_pos;
  5785. -			int fame_pos;
  5786. -
  5787. -			switch(type)
  5788. -			{
  5789. -				case 1:  size = fame_list_size_smith;   list = smith_fame_list;   break;
  5790. -				case 2:  size = fame_list_size_chemist; list = chemist_fame_list; break;
  5791. -				case 3:  size = fame_list_size_taekwon; list = taekwon_fame_list; break;
  5792. -				default: size = 0;                      list = NULL;              break;
  5793. -			}
  5794. -
  5795. -			ARR_FIND(0, size, player_pos, list[player_pos].id == cid);// position of the player
  5796. -			ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame);// where the player should be
  5797. -
  5798. -			if( player_pos == size && fame_pos == size )
  5799. -				;// not on list and not enough fame to get on it
  5800. -			else if( fame_pos == player_pos )
  5801. -			{// same position
  5802. -				list[player_pos].fame = fame;
  5803. -				char_update_fame_list(type, player_pos, fame);
  5804. -			}
  5805. -			else
  5806. -			{// move in the list
  5807. -				if( player_pos == size )
  5808. -				{// new ranker - not in the list
  5809. -					ARR_MOVE(size - 1, fame_pos, list, struct fame_list);
  5810. -					list[fame_pos].id = cid;
  5811. -					list[fame_pos].fame = fame;
  5812. -					char_loadName(cid, list[fame_pos].name);
  5813. -				}
  5814. -				else
  5815. -				{// already in the list
  5816. -					if( fame_pos == size )
  5817. -						--fame_pos;// move to the end of the list
  5818. -					ARR_MOVE(player_pos, fame_pos, list, struct fame_list);
  5819. -					list[fame_pos].fame = fame;
  5820. -				}
  5821. -				char_send_fame_list(-1);
  5822. -			}
  5823. -
  5824. -			RFIFOSKIP(fd,11);
  5825. -		}
  5826. -		break;
  5827. -
  5828. -		// Divorce chars
  5829. -		case 0x2b11:
  5830. -			if( RFIFOREST(fd) < 10 )
  5831. -				return 0;
  5832. -			divorce_char_sql(RFIFOL(fd,2), RFIFOL(fd,6));
  5833. -			RFIFOSKIP(fd,10);
  5834. -		break;
  5835. -
  5836. -		case 0x2b16: // Receive rates [Wizputer]
  5837. -			if( RFIFOREST(fd) < 14 )
  5838. -				return 0;
  5839. -		{
  5840. -			char esc_server_name[sizeof(server_name)*2+1];
  5841. -
  5842. -			Sql_EscapeString(sql_handle, esc_server_name, server_name);
  5843. -
  5844. -			if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` SET `index`='%d',`name`='%s',`exp`='%d',`jexp`='%d',`drop`='%d'",
  5845. -				ragsrvinfo_db, fd, esc_server_name, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)) )
  5846. -				Sql_ShowDebug(sql_handle);
  5847. -			RFIFOSKIP(fd,14);
  5848. -		}
  5849. -		break;
  5850. -
  5851. -		case 0x2b17: // Character disconnected set online 0 [Wizputer]
  5852. -			if (RFIFOREST(fd) < 6)
  5853. -				return 0;
  5854. -			set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6));
  5855. -			RFIFOSKIP(fd,10);
  5856. -		break;
  5857. -
  5858. -		case 0x2b18: // Reset all chars to offline [Wizputer]
  5859. -			set_all_offline(id);
  5860. -			RFIFOSKIP(fd,2);
  5861. -		break;
  5862. -
  5863. -		case 0x2b19: // Character set online [Wizputer]
  5864. -			if (RFIFOREST(fd) < 10)
  5865. -				return 0;
  5866. -			set_char_online(id, RFIFOL(fd,2),RFIFOL(fd,6));
  5867. -			RFIFOSKIP(fd,10);
  5868. -		break;
  5869. -
  5870. -		case 0x2b1a: // Build and send fame ranking lists [DracoRPG]
  5871. -			if (RFIFOREST(fd) < 2)
  5872. -				return 0;
  5873. -			char_read_fame_list();
  5874. -			char_send_fame_list(-1);
  5875. -			RFIFOSKIP(fd,2);
  5876. -		break;
  5877. -
  5878. -		case 0x2b1c: //Request to save status change data. [Skotlex]
  5879. -			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  5880. -				return 0;
  5881. -		{
  5882. -#ifdef ENABLE_SC_SAVING
  5883. -			int count, aid, cid;
  5884. -
  5885. -			aid = RFIFOL(fd, 4);
  5886. -			cid = RFIFOL(fd, 8);
  5887. -			count = RFIFOW(fd, 12);
  5888. -
  5889. -			if( count > 0 )
  5890. -			{
  5891. -				struct status_change_data data;
  5892. -				StringBuf buf;
  5893. -				int i;
  5894. -
  5895. -				StringBuf_Init(&buf);
  5896. -				StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", scdata_db);
  5897. -				for( i = 0; i < count; ++i )
  5898. -				{
  5899. -					memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data));
  5900. -					if( i > 0 )
  5901. -						StringBuf_AppendStr(&buf, ", ");
  5902. -					StringBuf_Printf(&buf, "('%d','%d','%hu','%d','%d','%d','%d','%d')", aid, cid,
  5903. -						data.type, data.tick, data.val1, data.val2, data.val3, data.val4);
  5904. -				}
  5905. -				if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
  5906. -					Sql_ShowDebug(sql_handle);
  5907. -				StringBuf_Destroy(&buf);
  5908. -			}
  5909. -#endif
  5910. -			RFIFOSKIP(fd, RFIFOW(fd, 2));
  5911. -		}
  5912. -		break;
  5913. -
  5914. -		case 0x2b23: // map-server alive packet
  5915. -			WFIFOHEAD(fd,2);
  5916. -			WFIFOW(fd,0) = 0x2b24;
  5917. -			WFIFOSET(fd,2);
  5918. -			RFIFOSKIP(fd,2);
  5919. -		break;
  5920. -
  5921. -		case 0x2b26: // auth request from map-server
  5922. -			if (RFIFOREST(fd) < 19)
  5923. -				return 0;
  5924. -
  5925. -		{
  5926. -			int account_id;
  5927. -			int char_id;
  5928. -			int login_id1;
  5929. -			char sex;
  5930. -			uint32 ip;
  5931. -			struct auth_node* node;
  5932. -			struct mmo_charstatus* cd;
  5933. -			struct mmo_charstatus char_dat;
  5934. -
  5935. -			account_id = RFIFOL(fd,2);
  5936. -			char_id    = RFIFOL(fd,6);
  5937. -			login_id1  = RFIFOL(fd,10);
  5938. -			sex        = RFIFOB(fd,14);
  5939. -			ip         = ntohl(RFIFOL(fd,15));
  5940. -			RFIFOSKIP(fd,19);
  5941. -
  5942. -			node = (struct auth_node*)idb_get(auth_db, account_id);
  5943. -			cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id);
  5944. -			if( cd == NULL )
  5945. -			{	//Really shouldn't happen.
  5946. -				mmo_char_fromsql(char_id, &char_dat, true);
  5947. -				cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id);
  5948. -			}
  5949. -			if( runflag == CHARSERVER_ST_RUNNING &&
  5950. -				cd != NULL &&
  5951. -				node != NULL &&
  5952. -				node->account_id == account_id &&
  5953. -				node->char_id == char_id &&
  5954. -				node->login_id1 == login_id1 &&
  5955. -				node->sex == sex /*&&
  5956. -				node->ip == ip*/ )
  5957. -			{// auth ok
  5958. -				cd->sex = sex;
  5959. -
  5960. -				WFIFOHEAD(fd,25 + sizeof(struct mmo_charstatus));
  5961. -				WFIFOW(fd,0) = 0x2afd;
  5962. -				WFIFOW(fd,2) = 25 + sizeof(struct mmo_charstatus);
  5963. -				WFIFOL(fd,4) = account_id;
  5964. -				WFIFOL(fd,8) = node->login_id1;
  5965. -				WFIFOL(fd,12) = node->login_id2;
  5966. -				WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT"
  5967. -				WFIFOL(fd,20) = node->group_id;
  5968. -				WFIFOB(fd,24) = node->changing_mapservers;
  5969. -				memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus));
  5970. -				WFIFOSET(fd, WFIFOW(fd,2));
  5971. -
  5972. -				// only use the auth once and mark user online
  5973. -				idb_remove(auth_db, account_id);
  5974. -				set_char_online(id, char_id, account_id);
  5975. -			}
  5976. -			else
  5977. -			{// auth failed
  5978. -				WFIFOHEAD(fd,19);
  5979. -				WFIFOW(fd,0) = 0x2b27;
  5980. -				WFIFOL(fd,2) = account_id;
  5981. -				WFIFOL(fd,6) = char_id;
  5982. -				WFIFOL(fd,10) = login_id1;
  5983. -				WFIFOB(fd,14) = sex;
  5984. -				WFIFOL(fd,15) = htonl(ip);
  5985. -				WFIFOSET(fd,19);
  5986. -			}
  5987. -		}
  5988. -		break;
  5989. -
  5990. -		case 0x2736: // ip address update
  5991. -			if (RFIFOREST(fd) < 6) return 0;
  5992. -			server[id].ip = ntohl(RFIFOL(fd, 2));
  5993. -			ShowInfo("Updated IP address of map-server #%d to %d.%d.%d.%d.\n", id, CONVIP(server[id].ip));
  5994. -			RFIFOSKIP(fd,6);
  5995. -		break;
  5996. -
  5997. -		case 0x3008:
  5998. -			if( RFIFOREST(fd) < RFIFOW(fd,4) )
  5999. -				return 0;/* packet wasn't fully received yet (still fragmented) */
  6000. -			else {
  6001. -				int sfd;/* stat server fd */
  6002. -				RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */
  6003. -
  6004. -				if( (sfd = make_connection(host2ip("stats.rathena.org"),(uint16)25421,true,10) ) == -1 ) {
  6005. -					RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */
  6006. -					break;/* connection not possible, we drop the report */
  6007. -				}
  6008. -
  6009. -				session[sfd]->flag.server = 1;/* to ensure we won't drop our own packet */
  6010. -				WFIFOHEAD(sfd, RFIFOW(fd,2) );
  6011. -				memcpy((char*)WFIFOP(sfd,0), (char*)RFIFOP(fd, 0), RFIFOW(fd,2));
  6012. -				WFIFOSET(sfd, RFIFOW(fd,2) );
  6013. -				flush_fifo(sfd);
  6014. -				do_close(sfd);
  6015. -				RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */
  6016. -		}
  6017. -		break;
  6018. -
  6019. -		default:
  6020. -		{
  6021. -			// inter server - packet
  6022. -			int r = inter_parse_frommap(fd);
  6023. -			if (r == 1) break;		// processed
  6024. -			if (r == 2) return 0;	// need more packet
  6025. -
  6026. -			// no inter server packet. no char server packet -> disconnect
  6027. -			ShowError("Unknown packet 0x%04x from map server, disconnecting.\n", RFIFOW(fd,0));
  6028. -			set_eof(fd);
  6029. -			return 0;
  6030. -		}
  6031. -		} // switch
  6032. -	} // while
  6033. -
  6034. -	return 0;
  6035. -}
  6036. -
  6037. -void do_init_mapif(void)
  6038. -{
  6039. -	int i;
  6040. -	for( i = 0; i < ARRAYLENGTH(server); ++i )
  6041. -		mapif_server_init(i);
  6042. -}
  6043. -
  6044. -void do_final_mapif(void)
  6045. -{
  6046. -	int i;
  6047. -	for( i = 0; i < ARRAYLENGTH(server); ++i )
  6048. -		mapif_server_destroy(i);
  6049. -}
  6050. -
  6051.  // Searches for the mapserver that has a given map (and optionally ip/port, if not -1).
  6052.  // If found, returns the server's index in the 'server' array (otherwise returns -1).
  6053.  int search_mapserver(unsigned short map, uint32 ip, uint16 port)
  6054. @@ -3555,17 +1939,10 @@
  6055.  	return -1;
  6056.  }
  6057.  
  6058. -// Initialization process (currently only initialization inter_mapif)
  6059. -static int char_mapif_init(int fd)
  6060. -{
  6061. -	return inter_mapif_init(fd);
  6062. -}
  6063. -
  6064.  //--------------------------------------------
  6065.  // Test to know if an IP come from LAN or WAN.
  6066.  //--------------------------------------------
  6067. -int lan_subnetcheck(uint32 ip)
  6068. -{
  6069. +int lan_subnetcheck(uint32 ip){
  6070.  	int i;
  6071.  	ARR_FIND( 0, subnet_count, i, (subnet[i].char_ip & subnet[i].mask) == (ip & subnet[i].mask) );
  6072.  	if( i < subnet_count ) {
  6073. @@ -3578,937 +1955,8 @@
  6074.  }
  6075.  
  6076.  
  6077. -/// @param result
  6078. -/// 0 (0x718): An unknown error has occurred.
  6079. -/// 1: none/success
  6080. -/// 3 (0x719): A database error occurred.
  6081. -/// 4 (0x71a): To delete a character you must withdraw from the guild.
  6082. -/// 5 (0x71b): To delete a character you must withdraw from the party.
  6083. -/// Any (0x718): An unknown error has occurred.
  6084. -void char_delete2_ack(int fd, int char_id, uint32 result, time_t delete_date)
  6085. -{// HC: <0828>.W <char id>.L <Msg:0-5>.L <deleteDate>.L
  6086. -	WFIFOHEAD(fd,14);
  6087. -	WFIFOW(fd,0) = 0x828;
  6088. -	WFIFOL(fd,2) = char_id;
  6089. -	WFIFOL(fd,6) = result;
  6090. -	WFIFOL(fd,10) = TOL(delete_date);
  6091. -	WFIFOSET(fd,14);
  6092. -}
  6093.  
  6094. -
  6095. -/// @param result
  6096. -/// 0 (0x718): An unknown error has occurred.
  6097. -/// 1: none/success
  6098. -/// 2 (0x71c): Due to system settings can not be deleted.
  6099. -/// 3 (0x719): A database error occurred.
  6100. -/// 4 (0x71d): Deleting not yet possible time.
  6101. -/// 5 (0x71e): Date of birth do not match.
  6102. -/// Any (0x718): An unknown error has occurred.
  6103. -void char_delete2_accept_ack(int fd, int char_id, uint32 result)
  6104. -{// HC: <082a>.W <char id>.L <Msg:0-5>.L
  6105. -	WFIFOHEAD(fd,10);
  6106. -	WFIFOW(fd,0) = 0x82a;
  6107. -	WFIFOL(fd,2) = char_id;
  6108. -	WFIFOL(fd,6) = result;
  6109. -	WFIFOSET(fd,10);
  6110. -}
  6111. -
  6112. -
  6113. -/// @param result
  6114. -/// 1 (0x718): none/success, (if char id not in deletion process): An unknown error has occurred.
  6115. -/// 2 (0x719): A database error occurred.
  6116. -/// Any (0x718): An unknown error has occurred.
  6117. -void char_delete2_cancel_ack(int fd, int char_id, uint32 result)
  6118. -{// HC: <082c>.W <char id>.L <Msg:1-2>.L
  6119. -	WFIFOHEAD(fd,10);
  6120. -	WFIFOW(fd,0) = 0x82c;
  6121. -	WFIFOL(fd,2) = char_id;
  6122. -	WFIFOL(fd,6) = result;
  6123. -	WFIFOSET(fd,10);
  6124. -}
  6125. -
  6126. -
  6127. -static void char_delete2_req(int fd, struct char_session_data* sd)
  6128. -{// CH: <0827>.W <char id>.L
  6129. -	int char_id, i;
  6130. -	char* data;
  6131. -	time_t delete_date;
  6132. -
  6133. -	char_id = RFIFOL(fd,2);
  6134. -
  6135. -	ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
  6136. -	if( i == MAX_CHARS )
  6137. -	{// character not found
  6138. -		char_delete2_ack(fd, char_id, 3, 0);
  6139. -		return;
  6140. -	}
  6141. -
  6142. -	if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) )
  6143. -	{
  6144. -		Sql_ShowDebug(sql_handle);
  6145. -		char_delete2_ack(fd, char_id, 3, 0);
  6146. -		return;
  6147. -	}
  6148. -
  6149. -	Sql_GetData(sql_handle, 0, &data, NULL); delete_date = strtoul(data, NULL, 10);
  6150. -
  6151. -	if( delete_date ) {// character already queued for deletion
  6152. -		char_delete2_ack(fd, char_id, 0, 0);
  6153. -		return;
  6154. -	}
  6155. -
  6156. -/*
  6157. -	// Aegis imposes these checks probably to avoid dead member
  6158. -	// entries in guilds/parties, otherwise they are not required.
  6159. -	// TODO: Figure out how these are enforced during waiting.
  6160. -	if( guild_id )
  6161. -	{// character in guild
  6162. -		char_delete2_ack(fd, char_id, 4, 0);
  6163. -		return;
  6164. -	}
  6165. -
  6166. -	if( party_id )
  6167. -	{// character in party
  6168. -		char_delete2_ack(fd, char_id, 5, 0);
  6169. -		return;
  6170. -	}
  6171. -*/
  6172. -
  6173. -	// success
  6174. -	delete_date = time(NULL)+char_del_delay;
  6175. -
  6176. -	if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='%lu' WHERE `char_id`='%d'", char_db, (unsigned long)delete_date, char_id) )
  6177. -	{
  6178. -		Sql_ShowDebug(sql_handle);
  6179. -		char_delete2_ack(fd, char_id, 3, 0);
  6180. -		return;
  6181. -	}
  6182. -
  6183. -	char_delete2_ack(fd, char_id, 1, delete_date);
  6184. -}
  6185. -
  6186. -
  6187. -static void char_delete2_accept(int fd, struct char_session_data* sd)
  6188. -{// CH: <0829>.W <char id>.L <birth date:YYMMDD>.6B
  6189. -	char birthdate[8+1];
  6190. -	int char_id, i, k;
  6191. -	unsigned int base_level;
  6192. -	char* data;
  6193. -	time_t delete_date;
  6194. -
  6195. -	char_id = RFIFOL(fd,2);
  6196. -
  6197. -	ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id);
  6198. -
  6199. -	// construct "YY-MM-DD"
  6200. -	birthdate[0] = RFIFOB(fd,6);
  6201. -	birthdate[1] = RFIFOB(fd,7);
  6202. -	birthdate[2] = '-';
  6203. -	birthdate[3] = RFIFOB(fd,8);
  6204. -	birthdate[4] = RFIFOB(fd,9);
  6205. -	birthdate[5] = '-';
  6206. -	birthdate[6] = RFIFOB(fd,10);
  6207. -	birthdate[7] = RFIFOB(fd,11);
  6208. -	birthdate[8] = 0;
  6209. -
  6210. -	ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
  6211. -	if( i == MAX_CHARS )
  6212. -	{// character not found
  6213. -		char_delete2_accept_ack(fd, char_id, 3);
  6214. -		return;
  6215. -	}
  6216. -
  6217. -	if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) )
  6218. -	{// data error
  6219. -		Sql_ShowDebug(sql_handle);
  6220. -		char_delete2_accept_ack(fd, char_id, 3);
  6221. -		return;
  6222. -	}
  6223. -
  6224. -	Sql_GetData(sql_handle, 0, &data, NULL); base_level = (unsigned int)strtoul(data, NULL, 10);
  6225. -	Sql_GetData(sql_handle, 1, &data, NULL); delete_date = strtoul(data, NULL, 10);
  6226. -
  6227. -	if( !delete_date || delete_date>time(NULL) )
  6228. -	{// not queued or delay not yet passed
  6229. -		char_delete2_accept_ack(fd, char_id, 4);
  6230. -		return;
  6231. -	}
  6232. -
  6233. -	if( strcmp(sd->birthdate+2, birthdate) )  // +2 to cut off the century
  6234. -	{// birth date is wrong
  6235. -		char_delete2_accept_ack(fd, char_id, 5);
  6236. -		return;
  6237. -	}
  6238. -
  6239. -	if( ( char_del_level > 0 && base_level >= (unsigned int)char_del_level ) || ( char_del_level < 0 && base_level <= (unsigned int)(-char_del_level) ) )
  6240. -	{// character level config restriction
  6241. -		char_delete2_accept_ack(fd, char_id, 2);
  6242. -		return;
  6243. -	}
  6244. -
  6245. -	// success
  6246. -	if( delete_char_sql(char_id) < 0 )
  6247. -	{
  6248. -		char_delete2_accept_ack(fd, char_id, 3);
  6249. -		return;
  6250. -	}
  6251. -
  6252. -	// refresh character list cache
  6253. -	for(k = i; k < MAX_CHARS-1; k++)
  6254. -	{
  6255. -		sd->found_char[k] = sd->found_char[k+1];
  6256. -	}
  6257. -	sd->found_char[MAX_CHARS-1] = -1;
  6258. -
  6259. -	char_delete2_accept_ack(fd, char_id, 1);
  6260. -}
  6261. -
  6262. -
  6263. -static void char_delete2_cancel(int fd, struct char_session_data* sd)
  6264. -{// CH: <082b>.W <char id>.L
  6265. -	int char_id, i;
  6266. -
  6267. -	char_id = RFIFOL(fd,2);
  6268. -
  6269. -	ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
  6270. -	if( i == MAX_CHARS )
  6271. -	{// character not found
  6272. -		char_delete2_cancel_ack(fd, char_id, 2);
  6273. -		return;
  6274. -	}
  6275. -
  6276. -	// there is no need to check, whether or not the character was
  6277. -	// queued for deletion, as the client prints an error message by
  6278. -	// itself, if it was not the case (@see char_delete2_cancel_ack)
  6279. -	if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='0' WHERE `char_id`='%d'", char_db, char_id) )
  6280. -	{
  6281. -		Sql_ShowDebug(sql_handle);
  6282. -		char_delete2_cancel_ack(fd, char_id, 2);
  6283. -		return;
  6284. -	}
  6285. -
  6286. -	char_delete2_cancel_ack(fd, char_id, 1);
  6287. -}
  6288. -
  6289. -
  6290. -int parse_char(int fd)
  6291. -{
  6292. -	int i, ch;
  6293. -	char email[40];
  6294. -	unsigned short cmd;
  6295. -	int map_fd;
  6296. -	struct char_session_data* sd;
  6297. -	uint32 ipl = session[fd]->client_addr;
  6298. -
  6299. -	sd = (struct char_session_data*)session[fd]->session_data;
  6300. -
  6301. -	// disconnect any player if no login-server.
  6302. -	if(login_fd < 0)
  6303. -		set_eof(fd);
  6304. -
  6305. -	if(session[fd]->flag.eof)
  6306. -	{
  6307. -		if( sd != NULL && sd->auth )
  6308. -		{	// already authed client
  6309. -			struct online_char_data* data = (struct online_char_data*)idb_get(online_char_db, sd->account_id);
  6310. -			if( data != NULL && data->fd == fd)
  6311. -				data->fd = -1;
  6312. -			if( data == NULL || data->server == -1) //If it is not in any server, send it offline. [Skotlex]
  6313. -				set_char_offline(-1,sd->account_id);
  6314. -		}
  6315. -		do_close(fd);
  6316. -		return 0;
  6317. -	}
  6318. -
  6319. -	while( RFIFOREST(fd) >= 2 )
  6320. -	{
  6321. -		//For use in packets that depend on an sd being present [Skotlex]
  6322. -		#define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } }
  6323. -
  6324. -		cmd = RFIFOW(fd,0);
  6325. -		switch( cmd )
  6326. -		{
  6327. -
  6328. -		// request to connect
  6329. -		// 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B
  6330. -		case 0x65:
  6331. -			if( RFIFOREST(fd) < 17 )
  6332. -				return 0;
  6333. -		{
  6334. -			struct auth_node* node;
  6335. -
  6336. -			int account_id = RFIFOL(fd,2);
  6337. -			uint32 login_id1 = RFIFOL(fd,6);
  6338. -			uint32 login_id2 = RFIFOL(fd,10);
  6339. -			int sex = RFIFOB(fd,16);
  6340. -			RFIFOSKIP(fd,17);
  6341. -
  6342. -			ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", account_id, login_id1, login_id2);
  6343. -
  6344. -			if (sd) {
  6345. -				//Received again auth packet for already authentified account?? Discard it.
  6346. -				//TODO: Perhaps log this as a hack attempt?
  6347. -				//TODO: and perhaps send back a reply?
  6348. -				break;
  6349. -			}
  6350. -
  6351. -			CREATE(session[fd]->session_data, struct char_session_data, 1);
  6352. -			sd = (struct char_session_data*)session[fd]->session_data;
  6353. -			sd->account_id = account_id;
  6354. -			sd->login_id1 = login_id1;
  6355. -			sd->login_id2 = login_id2;
  6356. -			sd->sex = sex;
  6357. -			sd->auth = false; // not authed yet
  6358. -
  6359. -			// send back account_id
  6360. -			WFIFOHEAD(fd,4);
  6361. -			WFIFOL(fd,0) = account_id;
  6362. -			WFIFOSET(fd,4);
  6363. -
  6364. -			if( runflag != CHARSERVER_ST_RUNNING )
  6365. -			{
  6366. -				WFIFOHEAD(fd,3);
  6367. -				WFIFOW(fd,0) = 0x6c;
  6368. -				WFIFOB(fd,2) = 0;// rejected from server
  6369. -				WFIFOSET(fd,3);
  6370. -				break;
  6371. -			}
  6372. -
  6373. -			// search authentification
  6374. -			node = (struct auth_node*)idb_get(auth_db, account_id);
  6375. -			if( node != NULL &&
  6376. -			    node->account_id == account_id &&
  6377. -				node->login_id1  == login_id1 &&
  6378. -				node->login_id2  == login_id2 /*&&
  6379. -				node->ip         == ipl*/ )
  6380. -			{// authentication found (coming from map server)
  6381. -				idb_remove(auth_db, account_id);
  6382. -				char_auth_ok(fd, sd);
  6383. -			}
  6384. -			else
  6385. -			{// authentication not found (coming from login server)
  6386. -				if (login_fd > 0) { // don't send request if no login-server
  6387. -					WFIFOHEAD(login_fd,23);
  6388. -					WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account
  6389. -					WFIFOL(login_fd,2) = sd->account_id;
  6390. -					WFIFOL(login_fd,6) = sd->login_id1;
  6391. -					WFIFOL(login_fd,10) = sd->login_id2;
  6392. -					WFIFOB(login_fd,14) = sd->sex;
  6393. -					WFIFOL(login_fd,15) = htonl(ipl);
  6394. -					WFIFOL(login_fd,19) = fd;
  6395. -					WFIFOSET(login_fd,23);
  6396. -				} else { // if no login-server, we must refuse connection
  6397. -					WFIFOHEAD(fd,3);
  6398. -					WFIFOW(fd,0) = 0x6c;
  6399. -					WFIFOB(fd,2) = 0;
  6400. -					WFIFOSET(fd,3);
  6401. -				}
  6402. -			}
  6403. -		}
  6404. -		break;
  6405. -
  6406. -		// char select
  6407. -		case 0x66:
  6408. -			FIFOSD_CHECK(3);
  6409. -		{
  6410. -			struct mmo_charstatus char_dat;
  6411. -			struct mmo_charstatus *cd;
  6412. -			char* data;
  6413. -			int char_id;
  6414. -			uint32 subnet_map_ip;
  6415. -			struct auth_node* node;
  6416. -
  6417. -			int slot = RFIFOB(fd,2);
  6418. -			RFIFOSKIP(fd,3);
  6419. -
  6420. -			if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", char_db, sd->account_id, slot)
  6421. -			  || SQL_SUCCESS != Sql_NextRow(sql_handle)
  6422. -			  || SQL_SUCCESS != Sql_GetData(sql_handle, 0, &data, NULL) )
  6423. -			{	//Not found?? May be forged packet.
  6424. -				Sql_ShowDebug(sql_handle);
  6425. -				Sql_FreeResult(sql_handle);
  6426. -				WFIFOHEAD(fd,3);
  6427. -				WFIFOW(fd,0) = 0x6c;
  6428. -				WFIFOB(fd,2) = 0; // rejected from server
  6429. -				WFIFOSET(fd,3);
  6430. -				break;
  6431. -			}
  6432. -
  6433. -			char_id = atoi(data);
  6434. -			Sql_FreeResult(sql_handle);
  6435. -
  6436. -			/* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */
  6437. -			set_char_online(-2,char_id,sd->account_id);
  6438. -			if( !mmo_char_fromsql(char_id, &char_dat, true) ) { /* failed? set it back offline */
  6439. -				set_char_offline(char_id, sd->account_id);
  6440. -				/* failed to load something. REJECT! */
  6441. -				WFIFOHEAD(fd,3);
  6442. -				WFIFOW(fd,0) = 0x6c;
  6443. -				WFIFOB(fd,2) = 0;
  6444. -				WFIFOSET(fd,3);
  6445. -				break;/* jump off this boat */
  6446. -			}
  6447. -
  6448. -			//Have to switch over to the DB instance otherwise data won't propagate [Kevin]
  6449. -			cd = (struct mmo_charstatus *)idb_get(char_db_, char_id);
  6450. -			cd->sex = sd->sex;
  6451. -
  6452. -			if (log_char) {
  6453. -				char esc_name[NAME_LENGTH*2+1];
  6454. -
  6455. -				Sql_EscapeStringLen(sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH));
  6456. -				if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')",
  6457. -					charlog_db, sd->account_id, slot, esc_name) )
  6458. -					Sql_ShowDebug(sql_handle);
  6459. -			}
  6460. -			ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name);
  6461. -
  6462. -			// searching map server
  6463. -			i = search_mapserver(cd->last_point.map, -1, -1);
  6464. -
  6465. -			// if map is not found, we check major cities
  6466. -			if (i < 0 || !cd->last_point.map) {
  6467. -				unsigned short j;
  6468. -				//First check that there's actually a map server online.
  6469. -				ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] );
  6470. -				if (j == ARRAYLENGTH(server)) {
  6471. -					ShowInfo("Connection Closed. No map servers available.\n");
  6472. -					WFIFOHEAD(fd,3);
  6473. -					WFIFOW(fd,0) = 0x81;
  6474. -					WFIFOB(fd,2) = 1; // 01 = Server closed
  6475. -					WFIFOSET(fd,3);
  6476. -					break;
  6477. -				}
  6478. -				if ((i = search_mapserver((j=mapindex_name2id(MAP_PRONTERA)),-1,-1)) >= 0) {
  6479. -					cd->last_point.x = 273;
  6480. -					cd->last_point.y = 354;
  6481. -				} else if ((i = search_mapserver((j=mapindex_name2id(MAP_GEFFEN)),-1,-1)) >= 0) {
  6482. -					cd->last_point.x = 120;
  6483. -					cd->last_point.y = 100;
  6484. -				} else if ((i = search_mapserver((j=mapindex_name2id(MAP_MORROC)),-1,-1)) >= 0) {
  6485. -					cd->last_point.x = 160;
  6486. -					cd->last_point.y = 94;
  6487. -				} else if ((i = search_mapserver((j=mapindex_name2id(MAP_ALBERTA)),-1,-1)) >= 0) {
  6488. -					cd->last_point.x = 116;
  6489. -					cd->last_point.y = 57;
  6490. -				} else if ((i = search_mapserver((j=mapindex_name2id(MAP_PAYON)),-1,-1)) >= 0) {
  6491. -					cd->last_point.x = 87;
  6492. -					cd->last_point.y = 117;
  6493. -				} else if ((i = search_mapserver((j=mapindex_name2id(MAP_IZLUDE)),-1,-1)) >= 0) {
  6494. -					cd->last_point.x = 94;
  6495. -					cd->last_point.y = 103;
  6496. -				} else {
  6497. -					ShowInfo("Connection Closed. No map server available that has a major city, and unable to find map-server for '%s'.\n", mapindex_id2name(cd->last_point.map));
  6498. -					WFIFOHEAD(fd,3);
  6499. -					WFIFOW(fd,0) = 0x81;
  6500. -					WFIFOB(fd,2) = 1; // 01 = Server closed
  6501. -					WFIFOSET(fd,3);
  6502. -					break;
  6503. -				}
  6504. -				ShowWarning("Unable to find map-server for '%s', sending to major city '%s'.\n", mapindex_id2name(cd->last_point.map), mapindex_id2name(j));
  6505. -				cd->last_point.map = j;
  6506. -			}
  6507. -
  6508. -			//Send NEW auth packet [Kevin]
  6509. -			//FIXME: is this case even possible? [ultramage]
  6510. -			if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL)
  6511. -			{
  6512. -				ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i);
  6513. -				server[i].fd = -1;
  6514. -				memset(&server[i], 0, sizeof(struct mmo_map_server));
  6515. -				//Send server closed.
  6516. -				WFIFOHEAD(fd,3);
  6517. -				WFIFOW(fd,0) = 0x81;
  6518. -				WFIFOB(fd,2) = 1; // 01 = Server closed
  6519. -				WFIFOSET(fd,3);
  6520. -				break;
  6521. -			}
  6522. -
  6523. -			//Send player to map
  6524. -			WFIFOHEAD(fd,28);
  6525. -			WFIFOW(fd,0) = 0x71;
  6526. -			WFIFOL(fd,2) = cd->char_id;
  6527. -			mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6));
  6528. -			subnet_map_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza]
  6529. -			WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : server[i].ip);
  6530. -			WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
  6531. -			WFIFOSET(fd,28);
  6532. -
  6533. -			// create temporary auth entry
  6534. -			CREATE(node, struct auth_node, 1);
  6535. -			node->account_id = sd->account_id;
  6536. -			node->char_id = cd->char_id;
  6537. -			node->login_id1 = sd->login_id1;
  6538. -			node->login_id2 = sd->login_id2;
  6539. -			node->sex = sd->sex;
  6540. -			node->expiration_time = sd->expiration_time;
  6541. -			node->group_id = sd->group_id;
  6542. -			node->ip = ipl;
  6543. -			idb_put(auth_db, sd->account_id, node);
  6544. -
  6545. -		}
  6546. -		break;
  6547. -
  6548. -		// create new char
  6549. -#if PACKETVER >= 20120307
  6550. -		// S 0970 <name>.24B <slot>.B <hair color>.W <hair style>.W
  6551. -		case 0x970:
  6552. -			FIFOSD_CHECK(31);
  6553. -#else
  6554. -		// S 0067 <name>.24B <str>.B <agi>.B <vit>.B <int>.B <dex>.B <luk>.B <slot>.B <hair color>.W <hair style>.W
  6555. -		case 0x67:
  6556. -			FIFOSD_CHECK(37);
  6557. -#endif
  6558. -
  6559. -			if( !char_new ) //turn character creation on/off [Kevin]
  6560. -				i = -2;
  6561. -			else
  6562. -#if PACKETVER >= 20120307
  6563. -				i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOW(fd,27),RFIFOW(fd,29));
  6564. -#else
  6565. -				i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOB(fd,27),RFIFOB(fd,28),RFIFOB(fd,29),RFIFOB(fd,30),RFIFOB(fd,31),RFIFOB(fd,32),RFIFOW(fd,33),RFIFOW(fd,35));
  6566. -#endif
  6567. -
  6568. -			//'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3)
  6569. -			if (i < 0) {
  6570. -				WFIFOHEAD(fd,3);
  6571. -				WFIFOW(fd,0) = 0x6e;
  6572. -				/* Others I found [Ind] */
  6573. -				/* 0x02 = Symbols in Character Names are forbidden */
  6574. -				/* 0x03 = You are not elegible to open the Character Slot. */
  6575. -				switch (i) {
  6576. -					case -1: WFIFOB(fd,2) = 0x00; break;
  6577. -					case -2: WFIFOB(fd,2) = 0xFF; break;
  6578. -					case -3: WFIFOB(fd,2) = 0x01; break;
  6579. -					case -4: WFIFOB(fd,2) = 0x03; break;
  6580. -				}
  6581. -				WFIFOSET(fd,3);
  6582. -			} else {
  6583. -				int len;
  6584. -				// retrieve data
  6585. -				struct mmo_charstatus char_dat;
  6586. -				mmo_char_fromsql(i, &char_dat, false); //Only the short data is needed.
  6587. -
  6588. -				// send to player
  6589. -				WFIFOHEAD(fd,2+MAX_CHAR_BUF);
  6590. -				WFIFOW(fd,0) = 0x6d;
  6591. -				len = 2 + mmo_char_tobuf(WFIFOP(fd,2), &char_dat);
  6592. -				WFIFOSET(fd,len);
  6593. -
  6594. -				// add new entry to the chars list
  6595. -				ARR_FIND( 0, MAX_CHARS, ch, sd->found_char[ch] == -1 );
  6596. -				if( ch < MAX_CHARS )
  6597. -					sd->found_char[ch] = i; // the char_id of the new char
  6598. -			}
  6599. -#if PACKETVER >= 20120307
  6600. -			RFIFOSKIP(fd,31);
  6601. -#else
  6602. -			RFIFOSKIP(fd,37);
  6603. -#endif
  6604. -		break;
  6605. -
  6606. -		// delete char
  6607. -		case 0x68:
  6608. -		// 2004-04-19aSakexe+ langtype 12 char deletion packet
  6609. -		case 0x1fb:
  6610. -			if (cmd == 0x68) FIFOSD_CHECK(46);
  6611. -			if (cmd == 0x1fb) FIFOSD_CHECK(56);
  6612. -		{
  6613. -			int cid = RFIFOL(fd,2);
  6614. -
  6615. -			ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid);
  6616. -			memcpy(email, RFIFOP(fd,6), 40);
  6617. -			RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56);
  6618. -
  6619. -			// Check if e-mail is correct
  6620. -			if(strcmpi(email, sd->email) && //email does not matches and
  6621. -			(
  6622. -				strcmp("[email protected]", sd->email) || //it is not default email, or
  6623. -				(strcmp("[email protected]", email) && strcmp("", email)) //email sent does not matches default
  6624. -			)) {	//Fail
  6625. -				WFIFOHEAD(fd,3);
  6626. -				WFIFOW(fd,0) = 0x70;
  6627. -				WFIFOB(fd,2) = 0; // 00 = Incorrect Email address
  6628. -				WFIFOSET(fd,3);
  6629. -				break;
  6630. -			}
  6631. -
  6632. -			// check if this char exists
  6633. -			ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
  6634. -			if( i == MAX_CHARS )
  6635. -			{ // Such a character does not exist in the account
  6636. -				WFIFOHEAD(fd,3);
  6637. -				WFIFOW(fd,0) = 0x70;
  6638. -				WFIFOB(fd,2) = 0;
  6639. -				WFIFOSET(fd,3);
  6640. -				break;
  6641. -			}
  6642. -
  6643. -			// remove char from list and compact it
  6644. -			for(ch = i; ch < MAX_CHARS-1; ch++)
  6645. -				sd->found_char[ch] = sd->found_char[ch+1];
  6646. -			sd->found_char[MAX_CHARS-1] = -1;
  6647. -
  6648. -			/* Delete character */
  6649. -			if(delete_char_sql(cid)<0){
  6650. -				//can't delete the char
  6651. -				//either SQL error or can't delete by some CONFIG conditions
  6652. -				//del fail
  6653. -				WFIFOHEAD(fd,3);
  6654. -				WFIFOW(fd, 0) = 0x70;
  6655. -				WFIFOB(fd, 2) = 0;
  6656. -				WFIFOSET(fd, 3);
  6657. -				break;
  6658. -			}
  6659. -			/* Char successfully deleted.*/
  6660. -			WFIFOHEAD(fd,2);
  6661. -			WFIFOW(fd,0) = 0x6f;
  6662. -			WFIFOSET(fd,2);
  6663. -		}
  6664. -		break;
  6665. -
  6666. -		// client keep-alive packet (every 12 seconds)
  6667. -		// R 0187 <account ID>.l
  6668. -		case 0x187:
  6669. -			if (RFIFOREST(fd) < 6)
  6670. -				return 0;
  6671. -			RFIFOSKIP(fd,6);
  6672. -		break;
  6673. -		// char rename request
  6674. -		// R 08fc <char ID>.l <new name>.24B
  6675. -		case 0x8fc:
  6676. -			FIFOSD_CHECK(30);
  6677. -			{
  6678. -				int i, cid =RFIFOL(fd,2);
  6679. -				char name[NAME_LENGTH];
  6680. -				char esc_name[NAME_LENGTH*2+1];
  6681. -				safestrncpy(name, (char *)RFIFOP(fd,6), NAME_LENGTH);
  6682. -				RFIFOSKIP(fd,30);
  6683. -
  6684. -				ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
  6685. -				if( i == MAX_CHARS )