Browse Source

Another round of login server cleaning
* fixed passwordencrypt on SQL not behaving correctly (since r10753)
* corrected some column lengths in the login db (username, password,...)
* fixed some places which used wfifo without first reallocating it
* removed interserver packet 0x7532 (Request to end connection), as there was no code that actually sent this packet
* moved RFIFOSKIP actions to execute as soon as possible

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12043 54d463be-8e91-2dee-dedb-b68131a5f0ec

ultramage 17 years ago
parent
commit
fafb4b8476
11 changed files with 412 additions and 449 deletions
  1. 7 0
      Changelog-Trunk.txt
  2. 4 4
      sql-files/main.sql
  3. 5 0
      sql-files/upgrade_svn12043.sql
  4. 0 5
      src/char/char.c
  5. 0 5
      src/char_sql/char.c
  6. 0 6
      src/login/admin.c
  7. 249 250
      src/login/login.c
  8. 139 169
      src/login_sql/login.c
  9. 3 7
      src/map/itemdb.c
  10. 1 0
      src/map/itemdb.h
  11. 4 3
      src/map/skill.c

+ 7 - 0
Changelog-Trunk.txt

@@ -4,6 +4,13 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 2008/01/10
+	* Another round of login server cleaning [ultramage]
+	- fixed passwordencrypt on SQL not behaving correctly (since r10753)
+	- corrected some column lengths in the login db (username, password,...)
+	- fixed some places which used wfifo without first reallocating it
+	- removed interserver packet 0x7532 (Request to end connection), as
+	  there was no code that actually sent this packet
+	- moved RFIFOSKIP actions to execute as soon as possible
 	* Corrected @slaveclone/@clone behaving as @evilclone when you change the @
 	  symbol.
 	* Modified SC_ARMOR_ELEMENT so it grants elemental resist as if it they

+ 4 - 4
sql-files/main.sql

@@ -93,7 +93,7 @@ CREATE TABLE `charlog` (
   `char_msg` varchar(255) NOT NULL default 'char select',
   `account_id` int(11) NOT NULL default '0',
   `char_num` tinyint(4) NOT NULL default '0',
-  `name` varchar(255) NOT NULL default '',
+  `name` varchar(23) NOT NULL default '',
   `str` int(11) unsigned NOT NULL default '0',
   `agi` int(11) unsigned NOT NULL default '0',
   `vit` int(11) unsigned NOT NULL default '0',
@@ -392,8 +392,8 @@ CREATE TABLE `ipbanlist` (
 DROP TABLE IF EXISTS `login`;
 CREATE TABLE `login` (
   `account_id` int(11) unsigned NOT NULL auto_increment,
-  `userid` varchar(255) NOT NULL default '',
-  `user_pass` varchar(32) NOT NULL default '',
+  `userid` varchar(23) NOT NULL default '',
+  `user_pass` varchar(23) NOT NULL default '',
   `lastlogin` datetime NOT NULL default '0000-00-00 00:00:00',
   `sex` enum('M','F','S') NOT NULL default 'M',
   `logincount` mediumint(9) unsigned NOT NULL default '0',
@@ -453,7 +453,7 @@ DROP TABLE IF EXISTS `loginlog`;
 CREATE TABLE `loginlog` (
   `time` datetime NOT NULL default '0000-00-00 00:00:00',
   `ip` int(10) unsigned NOT NULL default '0',
-  `user` varchar(32) NOT NULL default '',
+  `user` varchar(23) NOT NULL default '',
   `rcode` tinyint(4) NOT NULL default '0',
   `log` varchar(255) NOT NULL default '',
   INDEX (`ip`)

+ 5 - 0
sql-files/upgrade_svn12043.sql

@@ -0,0 +1,5 @@
+ALTER TABLE `login` MODIFY COLUMN `userid` VARCHAR(23) NOT NULL default '';
+ALTER TABLE `login` MODIFY COLUMN `user_pass` VARCHAR(23) NOT NULL default '';
+
+ALTER TABLE `loginlog` MODIFY COLUMN `user` VARCHAR(23) NOT NULL default '';
+ALTER TABLE `charlog` MODIFY COLUMN `name` VARCHAR(23) NOT NULL default '';

+ 0 - 5
src/char/char.c

@@ -3681,11 +3681,6 @@ int parse_char(int fd)
 			RFIFOSKIP(fd,2);
 		break;
 
-		// disconnect request from login server
-		case 0x7532:
-			set_eof(fd);
-			return 0;
-
 		// unknown packet received
 		default:
 			ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL));

+ 0 - 5
src/char_sql/char.c

@@ -3229,11 +3229,6 @@ int parse_char(int fd)
 			RFIFOSKIP(fd,2);
 		break;
 
-		// disconnect request from login server
-		case 0x7532:
-			set_eof(fd);
-			return 0;
-
 		// unknown packet received
 		default:
 			ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL));

+ 0 - 6
src/login/admin.c

@@ -74,12 +74,6 @@ int parse_admin(int fd)
 			RFIFOSKIP(fd,2);
 			break;
 
-		case 0x7532:	// Request of end of connection
-			ShowStatus("'ladmin': End of connection (ip: %s)\n", ip);
-			RFIFOSKIP(fd,2);
-			set_eof(fd);
-			break;
-
 		case 0x7920:	// Request of an accounts list
 			if (RFIFOREST(fd) < 10)
 				return 0;

+ 249 - 250
src/login/login.c

@@ -1052,8 +1052,7 @@ int mmo_auth(struct mmo_account* account, int fd)
 	}
 
 	//Client Version check
-	if( login_config.check_client_version && account->version != 0 &&
-		account->version != login_config.client_version_to_connect )
+	if( login_config.check_client_version && account->version != login_config.client_version_to_connect )
 		return 5;
 
 	len = strnlen(account->userid, NAME_LENGTH);
@@ -1251,11 +1250,11 @@ int parse_fromchar(int fd)
 		{
 
 		case 0x2709: // request from map-server via char-server to reload GM accounts
+			RFIFOSKIP(fd,2);
 			ShowStatus("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n", server[id].name, ip);
 			read_gm_account();
 			// send GM accounts to all char-servers
 			send_GM_accounts(-1);
-			RFIFOSKIP(fd,2);
 		break;
 
 		case 0x2712: // request from char-server to authenticate an account
@@ -1263,25 +1262,43 @@ int parse_fromchar(int fd)
 				return 0;
 		{
 			int account_id = RFIFOL(fd,2);
+			int login_id1 = RFIFOL(fd,6);
+			int login_id2 = RFIFOL(fd,10);
+			char sex = RFIFOB(fd,14);
+			uint32 ip_ = ntohl(RFIFOL(fd,15));
+			RFIFOSKIP(fd,19);
+
 			ARR_FIND( 0, AUTH_FIFO_SIZE, i, 
-				auth_fifo[i].account_id == RFIFOL(fd,2) &&
-				auth_fifo[i].login_id1  == RFIFOL(fd,6) &&
-				auth_fifo[i].login_id2  == RFIFOL(fd,10) &&
-				auth_fifo[i].sex        == RFIFOB(fd,14) &&
-				auth_fifo[i].ip         == ntohl(RFIFOL(fd,15)) &&
+				auth_fifo[i].account_id == account_id &&
+				auth_fifo[i].login_id1  == login_id1 &&
+				auth_fifo[i].login_id2  == login_id2 &&
+				auth_fifo[i].sex        == sex &&
+				auth_fifo[i].ip         == ip_ &&
 				!auth_fifo[i].delflag );
 
-			if( i < AUTH_FIFO_SIZE )
-				auth_fifo[i].delflag = 1;
-
-			if( i < AUTH_FIFO_SIZE && account_id > 0 )
-			{// send ack 
+			if( i == AUTH_FIFO_SIZE || account_id <= 0 )
+			{// authentication not found
+				ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip);
+				WFIFOHEAD(fd,51);
+				WFIFOW(fd,0) = 0x2713;
+				WFIFOL(fd,2) = account_id;
+				WFIFOB(fd,6) = 1;
+				// It is unnecessary to send email
+				// It is unnecessary to send validity date of the account
+				WFIFOSET(fd,51);
+			}
+			else
+			{// found
 				time_t connect_until_time;
 				char email[40];
 				unsigned int k;
 
 				//ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip);
 
+				// each auth entry can only be used once
+				auth_fifo[i].delflag = 1;
+
+				// retrieve email and account expiration time
 				ARR_FIND( 0, auth_num, k, auth_dat[k].account_id == account_id );
 				if( k < auth_num )
 				{
@@ -1294,6 +1311,7 @@ int parse_fromchar(int fd)
 					connect_until_time = 0;
 				}
 
+				// send ack
 				WFIFOHEAD(fd,51);
 				WFIFOW(fd,0) = 0x2713;
 				WFIFOL(fd,2) = account_id;
@@ -1302,19 +1320,6 @@ int parse_fromchar(int fd)
 				WFIFOL(fd,47) = (unsigned long)connect_until_time;
 				WFIFOSET(fd,51);
 			}
-			else
-			{// authentication not found
-				ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip);
-				WFIFOHEAD(fd,51);
-				WFIFOW(fd,0) = 0x2713;
-				WFIFOL(fd,2) = account_id;
-				WFIFOB(fd,6) = 1;
-				// It is unnecessary to send email
-				// It is unnecessary to send validity date of the account
-				WFIFOSET(fd,51);
-			}
-
-			RFIFOSKIP(fd,19);
 		}
 		break;
 
@@ -1323,7 +1328,6 @@ int parse_fromchar(int fd)
 				return 0;
 			//printf("parse_fromchar: Receiving of the users number of the server '%s': %d\n", server[id].name, RFIFOL(fd,2));
 			server[id].users = RFIFOL(fd,2);
-
 			RFIFOSKIP(fd,6);
 		break;
 
@@ -1333,8 +1337,9 @@ int parse_fromchar(int fd)
 		{
 			char email[40];
 			int acc = RFIFOL(fd,2);
-			safestrncpy(email, (char*)RFIFOP(fd,6), 40);
-			remove_control_chars(email);
+			safestrncpy(email, (char*)RFIFOP(fd,6), 40); remove_control_chars(email);
+			RFIFOSKIP(fd,46);
+
 			if( e_mail_check(email) == 0 )
 				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, acc, ip);
 			else
@@ -1350,64 +1355,70 @@ int parse_fromchar(int fd)
 					mmo_auth_sync();
 				}
 			}
-
-			RFIFOSKIP(fd,46);
 		}
 		break;
 
 		case 0x2716: // received an e-mail/limited time request, because a player comes back from a map-server to the char-server
 			if( RFIFOREST(fd) < 6 )
 				return 0;
+		{
+			uint32 connect_until_time = 0;
+			char* email = "";
+
+			int account_id = RFIFOL(fd,2);
+			RFIFOSKIP(fd,6);
 
-			ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == (int)RFIFOL(fd,2) );
+			ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id );
 			if( i == auth_num )
 				ShowNotice("Char-server '%s': e-mail of the account %d NOT found (ip: %s).\n", server[id].name, RFIFOL(fd,2), ip);
 			else
 			{
-				//ShowNotice("Char-server '%s': e-mail of the account %d found (ip: %s).\n", server[id].name, RFIFOL(fd,2), ip);
-				WFIFOW(fd,0) = 0x2717;
-				WFIFOL(fd,2) = RFIFOL(fd,2);
-				safestrncpy((char*)WFIFOP(fd, 6), auth_dat[i].email, 40);
-				WFIFOL(fd,46) = (unsigned long)auth_dat[i].connect_until_time;
-				WFIFOSET(fd,50);
+				email = auth_dat[i].email;
+				connect_until_time = (uint32)auth_dat[i].connect_until_time;
 			}
 
-			RFIFOSKIP(fd,6);
+			WFIFOHEAD(fd,50);
+			WFIFOW(fd,0) = 0x2717;
+			WFIFOL(fd,2) = account_id;
+			safestrncpy((char*)WFIFOP(fd,6), email, 40);
+			WFIFOL(fd,46) = connect_until_time;
+			WFIFOSET(fd,50);
+		}
 		break;
 
 		case 0x2719: // ping request from charserver
 			if( RFIFOREST(fd) < 2 )
 				return 0;
+			RFIFOSKIP(fd,2);
 
 			WFIFOHEAD(fd,2);
 			WFIFOW(fd,0) = 0x2718;
 			WFIFOSET(fd,2);
-
-			RFIFOSKIP(fd,2);
 		break;
 
 		case 0x2720: // Request to become a GM
 			if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
 				return 0;
 		{
-			unsigned char buf[10];
+			int level = 0;
 			FILE *fp;
+
+			char pass[60];
 			int acc = RFIFOL(fd,4);
-			WBUFW(buf,0) = 0x2721;
-			WBUFL(buf,2) = acc;
-			WBUFL(buf,6) = 0;
+			safestrncpy(pass, (char*)RFIFOP(fd,8), sizeof(pass));
+			RFIFOSKIP(fd, RFIFOW(fd,2));
 
-			if( strcmp((char*)RFIFOP(fd,8), gm_pass) != 0 ) // password check
-				ShowError("Char-server '%s': Error of GM change (suggested account: %d, invalid password, ip: %s).\n", server[id].name, acc, ip);
+			if( strcmp(pass, gm_pass) != 0 ) // password check
+				ShowError("Char-server '%s': Error of GM change (account: %d, invalid password, ip: %s).\n", server[id].name, acc, ip);
 			else
 			if( isGM(acc) > 0 ) // only non-GM can become GM
-				ShowError("Char-server '%s': Error of GM change (suggested account: %d (already GM), correct password, ip: %s).\n", server[id].name, acc, ip);
+				ShowError("Char-server '%s': Error of GM change (account: %d (already GM), correct password, ip: %s).\n", server[id].name, acc, ip);
 			else
 			if( level_new_gm == 0 ) // if we autorise creation
-				ShowError("Char-server '%s': Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0), ip: %s).\n", server[id].name, acc, ip);
+				ShowError("Char-server '%s': Error of GM change (account: %d, correct password, but GM creation is disable (level_new_gm = 0), ip: %s).\n", server[id].name, acc, ip);
 			else
 			if( (fp = fopen(GM_account_filename, "a")) == NULL ) // if we can open the file to add the new GM
-				ShowError("Char-server '%s': Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file, ip: %s).\n", server[id].name, acc, ip);
+				ShowError("Char-server '%s': Error of GM change (account: %d, correct password, unable to add a GM account in GM accounts file, ip: %s).\n", server[id].name, acc, ip);
 			else
 			{
 				char tmpstr[24];
@@ -1416,51 +1427,54 @@ int parse_fromchar(int fd)
 				strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time));
 				fprintf(fp, "\n// %s: @GM command on account %d\n%d %d\n", tmpstr, acc, acc, level_new_gm);
 				fclose(fp);
-				WBUFL(buf,6) = level_new_gm;
+				level = level_new_gm;
 				read_gm_account();
 				send_GM_accounts(-1);
 
 				ShowNotice("Char-server '%s': GM Change of the account %d: level 0 -> %d (ip: %s).\n", server[id].name, acc, level_new_gm, ip);
-
 			}
-			// announce gm level update
-			charif_sendallwos(-1, buf, 10);
 
-			RFIFOSKIP(fd, RFIFOW(fd,2));
-			return 0;
+			// announce gm level update result
+			WFIFOHEAD(fd,10);
+			WFIFOW(fd,0) = 0x2721;
+			WFIFOL(fd,2) = acc;
+			WFIFOL(fd,6) = level; // 0:failed, >0:success
+			WFIFOSET(fd,10);
 		}
+		break;
 
 		// Map server send information to change an email of an account via char-server
 		case 0x2722:	// 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
 			if (RFIFOREST(fd) < 86)
 				return 0;
 		{
-			char actual_email[40], new_email[40];
-			int acc = RFIFOL(fd,2);
-			memcpy(actual_email, RFIFOP(fd,6), 40); actual_email[39] = '\0'; remove_control_chars(actual_email);
-			memcpy(new_email, RFIFOP(fd,46), 40); new_email[39] = '\0'; remove_control_chars(new_email);
-			if (e_mail_check(actual_email) == 0)
-				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, acc, ip);
+			char actual_email[40];
+			char new_email[40];
+			int account_id = RFIFOL(fd,2);
+			safestrncpy(actual_email, RFIFOP(fd,6), 40); remove_control_chars(actual_email);
+			safestrncpy(new_email, RFIFOP(fd,46), 40); remove_control_chars(new_email);
+			RFIFOSKIP(fd, 86);
+
+			if( e_mail_check(actual_email) == 0 )
+				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);
 			else if (e_mail_check(new_email) == 0)
-				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, acc, ip);
+				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);
 			else if (strcmpi(new_email, "a@a.com") == 0)
-				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, acc, ip);
+				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);
 			else {
-				ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == acc );
+				ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id );
 				if( i == auth_num )
-					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, acc, ip);
+					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);
 				else
 				if( strcmpi(auth_dat[i].email, actual_email) != 0 )
-					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, acc, auth_dat[i].userid, auth_dat[i].email, actual_email, ip);
+					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, auth_dat[i].userid, auth_dat[i].email, actual_email, ip);
 				else {
-					memcpy(auth_dat[i].email, new_email, 40);
-					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, acc, auth_dat[i].userid, new_email, ip);
+					safestrncpy(auth_dat[i].email, new_email, 40);
+					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, auth_dat[i].userid, new_email, ip);
 					// Save
 					mmo_auth_sync();
 				}
 			}
-
-			RFIFOSKIP(fd, 86);
 		}
 		break;
 
@@ -1470,6 +1484,7 @@ int parse_fromchar(int fd)
 		{
 			int account_id = RFIFOL(fd,2);
 			uint32 state = RFIFOL(fd,6);
+			RFIFOSKIP(fd,10);
 
 			ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id );
 			if( i == auth_num )
@@ -1494,19 +1509,25 @@ int parse_fromchar(int fd)
 				// Save
 				mmo_auth_sync();
 			}
-
-			RFIFOSKIP(fd,10);
-			return 0;
 		}
+		break;
 
 		case 0x2725: // Receiving of map-server via char-server a ban request
 			if (RFIFOREST(fd) < 18)
 				return 0;
 		{
-			int acc = RFIFOL(fd,2);
-			ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == acc );
+			int account_id = RFIFOL(fd,2);
+			int year = (short)RFIFOW(fd,6);
+			int month = (short)RFIFOW(fd,8);
+			int mday = (short)RFIFOW(fd,10);
+			int hour = (short)RFIFOW(fd,12);
+			int min = (short)RFIFOW(fd,14);
+			int sec = (short)RFIFOW(fd,16);
+			RFIFOSKIP(fd,18);
+
+			ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id );
 			if( i == auth_num )
-				ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", server[id].name, acc, ip);
+				ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
 			else
 			{
 				time_t timestamp;
@@ -1516,152 +1537,133 @@ int parse_fromchar(int fd)
 				else
 					timestamp = auth_dat[i].ban_until_time;
 				tmtime = localtime(&timestamp);
-				tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,6);
-				tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,8);
-				tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,10);
-				tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,12);
-				tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,14);
-				tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,16);
+				tmtime->tm_year = tmtime->tm_year + year;
+				tmtime->tm_mon = tmtime->tm_mon + month;
+				tmtime->tm_mday = tmtime->tm_mday + mday;
+				tmtime->tm_hour = tmtime->tm_hour + hour;
+				tmtime->tm_min = tmtime->tm_min + min;
+				tmtime->tm_sec = tmtime->tm_sec + sec;
 				timestamp = mktime(tmtime);
 				if (timestamp == -1)
-					ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", server[id].name, acc, ip);
+					ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", server[id].name, account_id, ip);
+				else
+				if( timestamp <= time(NULL) || timestamp == 0 )
+					ShowNotice("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", server[id].name, account_id, ip);
 				else
 				{
-					if (timestamp <= time(NULL))
-						timestamp = 0;
-					else
-					{
-						if (timestamp == 0)
-							ShowNotice("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", server[id].name, acc, ip);
-						else
-						{
-							unsigned char buf[16];
-							char tmpstr[2048];
-							strftime(tmpstr, 24, login_config.date_format, localtime(&timestamp));
-							ShowNotice("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s).\n", server[id].name, acc, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
-							WBUFW(buf,0) = 0x2731;
-							WBUFL(buf,2) = auth_dat[i].account_id;
-							WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
-							WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment
-							charif_sendallwos(-1, buf, 11);
-							ARR_FIND( 0, AUTH_FIFO_SIZE, j, auth_fifo[j].account_id == acc );
-							if( j < AUTH_FIFO_SIZE )
-								auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication)
-						}
-						auth_dat[i].ban_until_time = timestamp;
-						// Save
-						mmo_auth_sync();
-					}
+					unsigned char buf[16];
+					char tmpstr[2048];
+					strftime(tmpstr, 24, login_config.date_format, localtime(&timestamp));
+					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);
+					WBUFW(buf,0) = 0x2731;
+					WBUFL(buf,2) = auth_dat[i].account_id;
+					WBUFB(buf,6) = 1; // 0: change of status, 1: ban
+					WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment
+					charif_sendallwos(-1, buf, 11);
+					ARR_FIND( 0, AUTH_FIFO_SIZE, j, auth_fifo[j].account_id == account_id );
+					if( j < AUTH_FIFO_SIZE )
+						auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication)
+
+					auth_dat[i].ban_until_time = timestamp;
+					// Save
+					mmo_auth_sync();
 				}
 			}
-
-			RFIFOSKIP(fd,18);
-			return 0;
 		}
+		break;
 
 		case 0x2727: // Change of sex (sex is reversed)
 			if( RFIFOREST(fd) < 6 )
 				return 0;
 		{
-			uint8 sex;
-			int acc = RFIFOL(fd,2);
-			for(i = 0; i < auth_num; i++) {
-				if (auth_dat[i].account_id == acc) {
-					if (auth_dat[i].sex == 2)
-						ShowNotice("Char-server '%s': Error of sex change - Server account (suggested account: %d, actual sex %d (Server), ip: %s).\n", server[id].name, acc, auth_dat[i].sex, ip);
-					else {
-						unsigned char buf[16];
-						if (auth_dat[i].sex == 0)
-							sex = 1;
-						else
-							sex = 0;
-						ShowNotice("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", server[id].name, acc, (sex == 2) ? 'S' : (sex == 1 ? 'M' : 'F'), ip);
-						for(j = 0; j < AUTH_FIFO_SIZE; j++)
-							if (auth_fifo[j].account_id == acc)
-								auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication)
-						auth_dat[i].sex = sex;
-						WBUFW(buf,0) = 0x2723;
-						WBUFL(buf,2) = acc;
-						WBUFB(buf,6) = sex;
-						charif_sendallwos(-1, buf, 7);
-						// Save
-						mmo_auth_sync();
-					}
-					break;
-				}
-			}
-			if (i == auth_num)
-				ShowNotice("Char-server '%s': Error of sex change (account: %d not found, sex would be reversed, ip: %s).\n", server[id].name, acc, ip);
-
+			int account_id = RFIFOL(fd,2);
 			RFIFOSKIP(fd,6);
-			return 0;
+
+			ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id );
+			if( i == auth_num )
+				ShowNotice("Char-server '%s': Error of sex change (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
+			else
+			if( auth_dat[i].sex == 2 )
+				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);
+			else
+			{
+				unsigned char buf[7];
+				uint8 sex = ( auth_dat[i].sex == 0 ) ? 1 : 0; // invert sex
+				auth_dat[i].sex = sex;
+				ShowNotice("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", server[id].name, account_id, (sex == 1 ? 'M' : 'F'), ip);
+
+				ARR_FIND( 0, AUTH_FIFO_SIZE, j, auth_fifo[j].account_id == account_id );
+				if( j < AUTH_FIFO_SIZE )
+					auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication)
+
+				WBUFW(buf,0) = 0x2723;
+				WBUFL(buf,2) = account_id;
+				WBUFB(buf,6) = sex;
+				charif_sendallwos(-1, buf, 7);
+				// Save
+				mmo_auth_sync();
+			}
 		}
+		break;
 
 		case 0x2728:	// We receive account_reg2 from a char-server, and we send them to other map-servers.
-			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
+			if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
 				return 0;
+		{
+			int acc = RFIFOL(fd,4);
+
+			ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == acc );
+			if( i == auth_num )
+				ShowStatus("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", server[id].name, acc, ip);
+			else
 			{
+				int len;
 				int p;
-				int acc = RFIFOL(fd,4);
-				for(i = 0; i < auth_num; i++) {
-					if (auth_dat[i].account_id == acc) {
-						//unsigned char buf[rfifow(fd,2)+1];
-						uint8* buf;
-						int len;
-						CREATE(buf, uint8, RFIFOW(fd,2)+1);
-						ShowNotice("char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", server[id].name, acc, ip);
-						for(j=0,p=13;j<ACCOUNT_REG2_NUM && p<RFIFOW(fd,2);j++){
-							sscanf((char*)RFIFOP(fd,p), "%31c%n",auth_dat[i].account_reg2[j].str,&len);
-							auth_dat[i].account_reg2[j].str[len]='\0';
-							p +=len+1; //+1 to skip the '\0' between strings.
-							sscanf((char*)RFIFOP(fd,p), "%255c%n",auth_dat[i].account_reg2[j].value,&len);
-							auth_dat[i].account_reg2[j].value[len]='\0';
-							p +=len+1;
-							remove_control_chars(auth_dat[i].account_reg2[j].str);
-							remove_control_chars(auth_dat[i].account_reg2[j].value);
-						}
-						auth_dat[i].account_reg2_num = j;
-						// Sending information towards the other char-servers.
-						memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2));
-						WBUFW(buf,0) = 0x2729;
-						charif_sendallwos(fd, buf, WBUFW(buf,2));
-						// Save
-						mmo_auth_sync();
-						if (buf) aFree(buf);
-						break;
-					}
-				}
-				if (i == auth_num) {
-					ShowStatus("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", server[id].name, acc, ip);
+				ShowNotice("char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", server[id].name, acc, ip);
+				for(j=0,p=13;j<ACCOUNT_REG2_NUM && p<RFIFOW(fd,2);j++){
+					sscanf((char*)RFIFOP(fd,p), "%31c%n",auth_dat[i].account_reg2[j].str,&len);
+					auth_dat[i].account_reg2[j].str[len]='\0';
+					p +=len+1; //+1 to skip the '\0' between strings.
+					sscanf((char*)RFIFOP(fd,p), "%255c%n",auth_dat[i].account_reg2[j].value,&len);
+					auth_dat[i].account_reg2[j].value[len]='\0';
+					p +=len+1;
+					remove_control_chars(auth_dat[i].account_reg2[j].str);
+					remove_control_chars(auth_dat[i].account_reg2[j].value);
 				}
+				auth_dat[i].account_reg2_num = j;
+
+				// Sending information towards the other char-servers.
+				RFIFOW(fd,0) = 0x2729;// reusing read buffer
+				charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2));
+				RFIFOSKIP(fd,RFIFOW(fd,2));
+
+				// Save
+				mmo_auth_sync();
 			}
 
-			RFIFOSKIP(fd,RFIFOW(fd,2));
+		}
 		break;
 
 		case 0x272a:	// Receiving of map-server via char-server an unban request
 			if( RFIFOREST(fd) < 6 )
 				return 0;
 		{
-			int acc = RFIFOL(fd,2);
-			for(i = 0; i < auth_num; i++) {
-				if (auth_dat[i].account_id == acc) {
-					if (auth_dat[i].ban_until_time != 0) {
-						auth_dat[i].ban_until_time = 0;
-						ShowNotice("Char-server '%s': UnBan request (account: %d, ip: %s).\n", server[id].name, acc, ip);
-					} else {
-						ShowNotice("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n",
-						          server[id].name, acc, ip);
-					}
-					break;
-				}
-			}
-			if (i == auth_num)
-				ShowNotice("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n", server[id].name, acc, ip);
-
+			int account_id = RFIFOL(fd,2);
 			RFIFOSKIP(fd,6);
-			return 0;
+
+			ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id );
+			if( i == auth_num )
+				ShowNotice("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip);
+			else
+			if( auth_dat[i].ban_until_time == 0 )
+				ShowNotice("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n", server[id].name, account_id, ip);
+			else
+			{
+				auth_dat[i].ban_until_time = 0;
+				ShowNotice("Char-server '%s': UnBan request (account: %d, ip: %s).\n", server[id].name, account_id, ip);
+			}
 		}
+		break;
 
 		case 0x272b:    // Set account_id to online [Wizputer]
 			if( RFIFOREST(fd) < 6 )
@@ -1705,30 +1707,41 @@ int parse_fromchar(int fd)
 			if (RFIFOREST(fd) < 10)
 				return 0;
 		{
-			int account_id = RFIFOL(fd, 2);
-			int char_id = RFIFOL(fd, 6);
-			int p;
+			size_t off;
+
+			int account_id = RFIFOL(fd,2);
+			int char_id = RFIFOL(fd,6);
+			RFIFOSKIP(fd,10);
+
+			WFIFOHEAD(fd,10000);
 			WFIFOW(fd,0) = 0x2729;
 			WFIFOL(fd,4) = account_id;
 			WFIFOL(fd,8) = char_id;
 			WFIFOB(fd,12) = 1; //Type 1 for Account2 registry
-			for(i = 0; i < auth_num && auth_dat[i].account_id != account_id; i++);
-			if (i == auth_num) {
+
+			ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id );
+			if( i == auth_num )
+			{
 				//Account not found? Send at least empty data, map servers need a reply!
 				WFIFOW(fd,2) = 13;
 				WFIFOSET(fd,WFIFOW(fd,2));
 				break;
 			}
-			for(p = 13, j = 0; j < auth_dat[i].account_reg2_num; j++) {
-				if (auth_dat[i].account_reg2[j].str[0]) {
-					p+= sprintf((char*)WFIFOP(fd,p), "%s", auth_dat[i].account_reg2[j].str)+1; //We add 1 to consider the '\0' in place.
-					p+= sprintf((char*)WFIFOP(fd,p), "%s", auth_dat[i].account_reg2[j].value)+1;
+
+			for( off = 13, j = 0; j < auth_dat[i].account_reg2_num && off < 9000; j++ )
+			{
+				if( auth_dat[i].account_reg2[j].str[0] != '\0' )
+				{
+					off+= sprintf((char*)WFIFOP(fd,off), "%s", auth_dat[i].account_reg2[j].str)+1; //We add 1 to consider the '\0' in place.
+					off+= sprintf((char*)WFIFOP(fd,off), "%s", auth_dat[i].account_reg2[j].value)+1;
 				}
 			}
-			WFIFOW(fd,2) = (uint16) p;
-			WFIFOSET(fd,WFIFOW(fd,2));
 
-			RFIFOSKIP(fd,10);
+			if( off >= 9000 )
+				ShowWarning("Too many account2 registries for AID %d. Some registries were not sent.\n", account_id);
+
+			WFIFOW(fd,2) = (uint16)off;
+			WFIFOSET(fd,WFIFOW(fd,2));
 		}
 		break;
 
@@ -1834,6 +1847,7 @@ int parse_login(int fd)
 
 		switch( command )
 		{
+
 		case 0x0200:		// New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
 			if (RFIFOREST(fd) < 26)
 				return 0;
@@ -1879,18 +1893,16 @@ int parse_login(int fd)
 
 			memset(&account, 0, sizeof(account));
 			account.version = RFIFOL(fd,2);
-			if( !account.version )
-				account.version = 1; //Force some version...
-			memcpy(account.userid,RFIFOP(fd,6),NAME_LENGTH); account.userid[23] = '\0';
-			remove_control_chars(account.userid);
+			safestrncpy(account.userid, (char*)RFIFOP(fd,6), NAME_LENGTH); remove_control_chars(account.userid);
 			if (command != 0x01dd) {
 				ShowStatus("Request for connection (non encryption mode) of %s (ip: %s).\n", account.userid, ip);
-				memcpy(account.passwd, RFIFOP(fd,30), NAME_LENGTH); account.passwd[23] = '\0';
-				remove_control_chars(account.passwd);
+				safestrncpy(account.passwd, (char*)RFIFOP(fd,30), NAME_LENGTH); remove_control_chars(account.passwd);
 			} else {
 				ShowStatus("Request for connection (encryption mode) of %s (ip: %s).\n", account.userid, ip);
-				memcpy(account.passwd, RFIFOP(fd,30), 16); account.passwd[16] = '\0'; // binary data here
+				memcpy(account.passwd, RFIFOP(fd,30), 16); account.passwd[16] = '\0'; // raw binary data here!
 			}
+			RFIFOSKIP(fd,packet_len);
+
 			account.passwdenc = (command == 0x01dd) ? PASSWORDENC : 0;
 
 			result = mmo_auth(&account, fd);
@@ -1986,13 +1998,12 @@ int parse_login(int fd)
 				}
 				WFIFOSET(fd,23);
 			}
-
-			RFIFOSKIP(fd,packet_len);
 		}
 		break;
 
 		case 0x01db:	// Sending request of the coding key
 		case 0x791a:	// Sending request of the coding key (administration packet)
+			RFIFOSKIP(fd,2);
 		{
 			struct login_session_data* ld;
 			if( session[fd]->session_data )
@@ -2016,8 +2027,6 @@ int parse_login(int fd)
 			WFIFOW(fd,2) = 4 + ld->md5keylen;
 			memcpy(WFIFOP(fd,4), ld->md5key, ld->md5keylen);
 			WFIFOSET(fd,WFIFOW(fd,2));
-
-			RFIFOSKIP(fd,2);
 		}
 		break;
 
@@ -2025,17 +2034,22 @@ int parse_login(int fd)
 			if (RFIFOREST(fd) < 86)
 				return 0;
 		{
-			char* server_name;
+			char server_name[20];
 			uint32 server_ip;
 			uint16 server_port;
+			uint16 maintenance;
+			uint16 new_;
 
 			memset(&account, 0, sizeof(account));
+			account.passwdenc = 0;
 			safestrncpy(account.userid, (char*)RFIFOP(fd,2), NAME_LENGTH); remove_control_chars(account.userid);
 			safestrncpy(account.passwd, (char*)RFIFOP(fd,26), NAME_LENGTH); remove_control_chars(account.passwd);
-			account.passwdenc = 0;
-			server_name = (char*)RFIFOP(fd,60); server_name[20] = '\0'; remove_control_chars(server_name);
-			server_ip = ntohl(RFIFOL(fd, 54));
-			server_port = ntohs(RFIFOW(fd, 58));
+			server_ip = ntohl(RFIFOL(fd,54));
+			server_port = ntohs(RFIFOW(fd,58));
+			safestrncpy(server_name, (char*)RFIFOP(fd,60), 20); remove_control_chars(server_name);
+			maintenance = RFIFOW(fd,82);
+			new_ = RFIFOW(fd,84);
+			RFIFOSKIP(fd,86);
 
 			ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (account: '%s', pass: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, account.userid, account.passwd, ip);
 
@@ -2043,25 +2057,26 @@ int parse_login(int fd)
 			if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server[account.account_id].fd == -1 )
 			{
 				ShowStatus("Connection of the char-server '%s' accepted.\n", server_name);
-				memset(&server[account.account_id], 0, sizeof(struct mmo_char_server));
-				server[account.account_id].ip = ntohl(RFIFOL(fd,54));
-				server[account.account_id].port = ntohs(RFIFOW(fd,58));
 				safestrncpy(server[account.account_id].name, server_name, sizeof(server[account.account_id].name));
-				server[account.account_id].users = 0;
-				server[account.account_id].maintenance = RFIFOW(fd,82);
-				server[account.account_id].new_ = RFIFOW(fd,84);
 				server[account.account_id].fd = fd;
+				server[account.account_id].ip = server_ip;
+				server[account.account_id].port = server_port;
+				server[account.account_id].users = 0;
+				server[account.account_id].maintenance = maintenance;
+				server[account.account_id].new_ = new_;
+
+				session[fd]->func_parse = parse_fromchar;
+				session[fd]->flag.server = 1;
+				realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
 
+				// send connection success
 				WFIFOHEAD(fd,3);
 				WFIFOW(fd,0) = 0x2711;
 				WFIFOB(fd,2) = 0;
 				WFIFOSET(fd,3);
 
-				session[fd]->func_parse = parse_fromchar;
-				session[fd]->flag.server = 1;
-				realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
-
-				send_GM_accounts(fd); // send GM account to char-server
+				// send GM account to char-server
+				send_GM_accounts(fd);
 			}
 			else
 			{
@@ -2072,12 +2087,11 @@ int parse_login(int fd)
 				WFIFOSET(fd,3);
 			}
 		}
-
-			RFIFOSKIP(fd,86);
-			return 0;
+		return 0; // processing will continue elsewhere
 
 		case 0x7530:	// Server version information request
 			ShowStatus("Sending server version information to ip: %s\n", ip);
+			RFIFOSKIP(fd,2);
 			WFIFOHEAD(fd,10);
 			WFIFOW(fd,0) = 0x7531;
 			WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
@@ -2088,15 +2102,8 @@ int parse_login(int fd)
 			WFIFOB(fd,7) = ATHENA_SERVER_LOGIN;
 			WFIFOW(fd,8) = ATHENA_MOD_VERSION;
 			WFIFOSET(fd,10);
-
-			RFIFOSKIP(fd,2);
 		break;
 
-		case 0x7532:	// Request to end connection
-			ShowStatus("End of connection (ip: %s)\n", ip);
-			set_eof(fd);
-			return 0;
-
 		case 0x7918:	// Request for administation login
 			if ((int)RFIFOREST(fd) < 4 || (int)RFIFOREST(fd) < ((RFIFOW(fd,2) == 0) ? 28 : 20))
 				return 0;
@@ -2283,11 +2290,6 @@ int login_lan_config_read(const char *lancfgName)
 			continue;
 		}
 
-		remove_control_chars(w1);
-		remove_control_chars(w2);
-		remove_control_chars(w3);
-		remove_control_chars(w4);
-
 		if( strcmpi(w1, "subnet") == 0 )
 		{
 			subnet[subnet_count].mask = str2ip(w2);
@@ -2330,9 +2332,6 @@ int login_config_read(const char* cfgName)
 		if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2)
 			continue;
 
-		remove_control_chars(w1);
-		remove_control_chars(w2);
-
 		if(!strcmpi(w1,"timestamp_format"))
 			strncpy(timestamp_format, w2, 20);
 		else if(!strcmpi(w1,"stdout_with_ansisequence"))

+ 139 - 169
src/login_sql/login.c

@@ -468,8 +468,7 @@ int mmo_auth(struct mmo_account* account, int fd)
 	}
 
 	//Client Version check
-	if( login_config.check_client_version && account->version != 0 &&
-		account->version != login_config.client_version_to_connect )
+	if( login_config.check_client_version && account->version != login_config.client_version_to_connect )
 		return 5;
 
 	len = strnlen(account->userid, NAME_LENGTH);
@@ -639,6 +638,7 @@ int parse_fromchar(int fd)
 		{
 
 		case 0x2709: // request from map-server via char-server to reload GM accounts
+			RFIFOSKIP(fd,2);
 			ShowStatus("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n", server[id].name, ip);
 			if( login_config.log_login )
 			{
@@ -648,7 +648,6 @@ int parse_fromchar(int fd)
 			read_gm_account();
 			// send GM accounts to all char-servers
 			send_GM_accounts(-1);
-			RFIFOSKIP(fd,2);
 		break;
 
 		case 0x2712: // request from char-server to authenticate an account
@@ -656,22 +655,40 @@ int parse_fromchar(int fd)
 				return 0;
 		{
 			int account_id = RFIFOL(fd,2);
+			int login_id1 = RFIFOL(fd,6);
+			int login_id2 = RFIFOL(fd,10);
+			char sex = RFIFOB(fd,14);
+			uint32 ip_ = ntohl(RFIFOL(fd,15));
+			RFIFOSKIP(fd,19);
+
 			ARR_FIND( 0, AUTH_FIFO_SIZE, i, 
-				auth_fifo[i].account_id == RFIFOL(fd,2) &&
-				auth_fifo[i].login_id1  == RFIFOL(fd,6) &&
-				auth_fifo[i].login_id2  == RFIFOL(fd,10) &&
-				auth_fifo[i].sex        == RFIFOB(fd,14) &&
-				auth_fifo[i].ip         == ntohl(RFIFOL(fd,15)) &&
+				auth_fifo[i].account_id == account_id &&
+				auth_fifo[i].login_id1  == login_id1 &&
+				auth_fifo[i].login_id2  == login_id2 &&
+				auth_fifo[i].sex        == sex &&
+				auth_fifo[i].ip         == ip_ &&
 				!auth_fifo[i].delflag );
 
-			if( i < AUTH_FIFO_SIZE )
-				auth_fifo[i].delflag = 1;
-
-			if( i < AUTH_FIFO_SIZE && account_id > 0 )
-			{// send ack 
+			if( i == AUTH_FIFO_SIZE || account_id <= 0 )
+			{// authentication not found
+				ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip);
+				WFIFOHEAD(fd,51);
+				WFIFOW(fd,0) = 0x2713;
+				WFIFOL(fd,2) = account_id;
+				WFIFOB(fd,6) = 1;
+				// It is unnecessary to send email
+				// It is unnecessary to send validity date of the account
+				WFIFOSET(fd,51);
+			}
+			else
+			{// found
 				uint32 connect_until_time;
 				char email[40];
 
+				// each auth entry can only be used once
+				auth_fifo[i].delflag = 1;
+
+				// retrieve email and account expiration time
 				if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id) )
 					Sql_ShowDebug(sql_handle);
 				if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
@@ -692,6 +709,7 @@ int parse_fromchar(int fd)
 					connect_until_time = 0;
 				}
 
+				// send ack
 				WFIFOHEAD(fd,51);
 				WFIFOW(fd,0) = 0x2713;
 				WFIFOL(fd,2) = account_id;
@@ -700,48 +718,37 @@ int parse_fromchar(int fd)
 				WFIFOL(fd,47) = connect_until_time;
 				WFIFOSET(fd,51);
 			}
-			else
-			{// authentication not found
-				ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip);
-				WFIFOHEAD(fd,51);
-				WFIFOW(fd,0) = 0x2713;
-				WFIFOL(fd,2) = account_id;
-				WFIFOB(fd,6) = 1;
-				// It is unnecessary to send email
-				// It is unnecessary to send validity date of the account
-				WFIFOSET(fd,51);
-			}
-
-			RFIFOSKIP(fd,19);
 		}
 		break;
 
 		case 0x2714:
 			if( RFIFOREST(fd) < 6 )
 				return 0;
+		{
+			int users = RFIFOL(fd,2);
+			RFIFOSKIP(fd,6);
 
 			// how many users on world? (update)
-			if( server[id].users != RFIFOL(fd,2) )
+			if( server[id].users != users )
 			{
-				ShowStatus("set users %s : %d\n", server[id].name, RFIFOL(fd,2));
+				ShowStatus("set users %s : %d\n", server[id].name, users);
 
-				server[id].users = RFIFOL(fd,2);
+				server[id].users = users;
 				if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `sstatus` SET `user` = '%d' WHERE `index` = '%d'", server[id].users, id) )
 					Sql_ShowDebug(sql_handle);
 			}
-			RFIFOSKIP(fd,6);
+		}
 		break;
 
 		case 0x2716: // received an e-mail/limited time request, because a player comes back from a map-server to the char-server
 			if( RFIFOREST(fd) < 6 )
 				return 0;
 		{
-			int account_id;
 			uint32 connect_until_time = 0;
-			char email[40];
+			char email[40] = "";
 
-			memset(email, 0, sizeof(email));
-			account_id = RFIFOL(fd,2);
+			int account_id = RFIFOL(fd,2);
+			RFIFOSKIP(fd,6);
 
 			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id) )
 				Sql_ShowDebug(sql_handle);
@@ -751,79 +758,70 @@ int parse_fromchar(int fd)
 				size_t len;
 
 				Sql_GetData(sql_handle, 0, &data, &len);
-				if( len > sizeof(email) )
-				{
-#if defined(DEBUG)
-					ShowDebug("parse_fromchar:0x2716: email is too long (len=%u,maxlen=%u)\n", len, sizeof(email));
-#endif
-					len = sizeof(email);
-				}
-				memcpy(email, data, len);
+				safestrncpy(email, data, sizeof(email));
 
 				Sql_GetData(sql_handle, 1, &data, NULL);
 				connect_until_time = (uint32)strtoul(data, NULL, 10);
 
 				Sql_FreeResult(sql_handle);
 			}
-			//printf("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, RFIFOL(fd,2));
+
 			WFIFOHEAD(fd,50);
 			WFIFOW(fd,0) = 0x2717;
-			WFIFOL(fd,2) = RFIFOL(fd,2);
-			memcpy(WFIFOP(fd, 6), email, 40);
+			WFIFOL(fd,2) = account_id;
+			safestrncpy((char*)WFIFOP(fd,6), email, 40);
 			WFIFOL(fd,46) = connect_until_time;
 			WFIFOSET(fd,50);
-
-			RFIFOSKIP(fd,6);
 		}
 		break;
 
 		case 0x2719: // ping request from charserver
 			if( RFIFOREST(fd) < 2 )
 				return 0;
+			RFIFOSKIP(fd,2);
 
 			WFIFOHEAD(fd,2);
 			WFIFOW(fd,0) = 0x2718;
 			WFIFOSET(fd,2);
-
-			RFIFOSKIP(fd,2);
 		break;
 
-		case 0x2720: // Request to become a GM (TXT only!)
-			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
+		case 0x2720: // Request to become a GM
+			if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
 				return 0;
-			//oldacc = RFIFOL(fd,4);
+		{
+			int acc = RFIFOL(fd,4);
+			RFIFOSKIP(fd, RFIFOW(fd,2));
+
 			ShowWarning("change GM isn't supported in this login server version.\n");
-			ShowError("change GM error 0 %s\n", RFIFOP(fd, 8));
+			ShowError("change GM error 0 %s\n", RFIFOP(fd,8));
 
+			// announce gm level update result
 			WFIFOHEAD(fd,10);
 			WFIFOW(fd,0) = 0x2721;
-			WFIFOL(fd,2) = RFIFOL(fd,4); // oldacc;
-			WFIFOL(fd,6) = 0; // newacc;
+			WFIFOL(fd,2) = acc;
+			WFIFOL(fd,6) = 0; // level
 			WFIFOSET(fd,10);
-
-			RFIFOSKIP(fd, RFIFOW(fd, 2));
-			return 0;
+		}
+		break;
 
 		// Map server send information to change an email of an account via char-server
 		case 0x2722:	// 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
 			if (RFIFOREST(fd) < 86)
 				return 0;
 		{
-			int account_id;
-			char actual_email[40], new_email[40];
+			char actual_email[40];
+			char new_email[40];
+			int account_id = RFIFOL(fd,2);
+			safestrncpy(actual_email, RFIFOP(fd,6), 40);
+			safestrncpy(new_email, RFIFOP(fd,46), 40);
+			RFIFOSKIP(fd, 86);
 
-			account_id = RFIFOL(fd,2);
-			memcpy(actual_email, RFIFOP(fd,6), 40);
-			memcpy(new_email, RFIFOP(fd,46), 40);
 			if( e_mail_check(actual_email) == 0 )
-				ShowWarning("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);
+				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);
 			else if( e_mail_check(new_email) == 0 )
-				ShowWarning("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);
+				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);
 			else if( strcmpi(new_email, "a@a.com") == 0 )
-				ShowWarning("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);
+				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);
 			else if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `%s`,`email` FROM `%s` WHERE `%s` = '%d'", login_db_userid, login_db, login_db_account_id, account_id) )
 				Sql_ShowDebug(sql_handle);
 			else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
@@ -832,38 +830,21 @@ int parse_fromchar(int fd)
 				size_t len;
 
 				Sql_GetData(sql_handle, 1, &data, &len);
-				if( len > sizeof(actual_email) )
-				{
-#if defined(DEBUG)
-					ShowDebug("parse_fromchar:0x2722: email is too long (len=%u,maxlen=%u)\n", len, sizeof(actual_email));
-#endif
-					len = sizeof(actual_email);
-				}
 				if( strncasecmp(data, actual_email, sizeof(actual_email)) == 0 )
 				{
 					char esc_user_id[NAME_LENGTH*2+1];
 					char esc_new_email[sizeof(new_email)*2+1];
 
 					Sql_GetData(sql_handle, 0, &data, &len);
-					if( len > NAME_LENGTH )
-					{
-#if defined(DEBUG)
-						ShowDebug("parse_fromchar:0x2722: userid is too long (len=%u,maxlen=%u)\n", len, NAME_LENGTH);
-#endif
-						len = NAME_LENGTH;
-					}
 					Sql_EscapeStringLen(sql_handle, esc_user_id, data, len);
 					Sql_EscapeStringLen(sql_handle, esc_new_email, new_email, strnlen(new_email, sizeof(new_email)));
 
 					if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `email` = '%s' WHERE `%s` = '%d'", login_db, esc_new_email, login_db_account_id, account_id) )
 						Sql_ShowDebug(sql_handle);
-					ShowInfo("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, esc_user_id, esc_new_email, ip);
+					ShowInfo("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, esc_user_id, esc_new_email, ip);
 				}
 				Sql_FreeResult(sql_handle);
 			}
-
-			RFIFOSKIP(fd, 86);
 		}
 		break;
 
@@ -873,6 +854,8 @@ int parse_fromchar(int fd)
 		{
 			int account_id = RFIFOL(fd,2);
 			int state = RFIFOL(fd,6);
+			RFIFOSKIP(fd,10);
+
 			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) )
 				Sql_ShowDebug(sql_handle);
 			else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
@@ -894,8 +877,6 @@ int parse_fromchar(int fd)
 
 			if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `state` = '%d' WHERE `%s` = '%d'", login_db, state, login_db_account_id, account_id) )
 				Sql_ShowDebug(sql_handle);
-
-			RFIFOSKIP(fd,10);
 		}
 		break;
 
@@ -903,12 +884,19 @@ int parse_fromchar(int fd)
 			if (RFIFOREST(fd) < 18)
 				return 0;
 		{
-			int account_id;
 			struct tm *tmtime;
 			time_t tmptime = 0;
 			time_t timestamp = time(NULL);
 
-			account_id = RFIFOL(fd,2);
+			int account_id = RFIFOL(fd,2);
+			int year = (short)RFIFOW(fd,6);
+			int month = (short)RFIFOW(fd,8);
+			int mday = (short)RFIFOW(fd,10);
+			int hour = (short)RFIFOW(fd,12);
+			int min = (short)RFIFOW(fd,14);
+			int sec = (short)RFIFOW(fd,16);
+			RFIFOSKIP(fd,18);
+
 			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) )
 				Sql_ShowDebug(sql_handle);
 			else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
@@ -921,12 +909,12 @@ int parse_fromchar(int fd)
 					timestamp = tmptime;
 			}
 			tmtime = localtime(&timestamp);
-			tmtime->tm_year = tmtime->tm_year + (int16)RFIFOW(fd,6);
-			tmtime->tm_mon  = tmtime->tm_mon  + (int16)RFIFOW(fd,8);
-			tmtime->tm_mday = tmtime->tm_mday + (int16)RFIFOW(fd,10);
-			tmtime->tm_hour = tmtime->tm_hour + (int16)RFIFOW(fd,12);
-			tmtime->tm_min  = tmtime->tm_min  + (int16)RFIFOW(fd,14);
-			tmtime->tm_sec  = tmtime->tm_sec  + (int16)RFIFOW(fd,16);
+			tmtime->tm_year = tmtime->tm_year + year;
+			tmtime->tm_mon  = tmtime->tm_mon  + month;
+			tmtime->tm_mday = tmtime->tm_mday + mday;
+			tmtime->tm_hour = tmtime->tm_hour + hour;
+			tmtime->tm_min  = tmtime->tm_min  + min;
+			tmtime->tm_sec  = tmtime->tm_sec  + sec;
 			timestamp = mktime(tmtime);
 			if( timestamp != (time_t)-1 )
 			{
@@ -948,8 +936,6 @@ int parse_fromchar(int fd)
 						Sql_ShowDebug(sql_handle);
 				}
 			}
-
-			RFIFOSKIP(fd,18);
 		}
 		break;
 
@@ -957,15 +943,15 @@ int parse_fromchar(int fd)
 			if( RFIFOREST(fd) < 6 )
 				return 0;
 		{
-			int account_id;
-			int sex;
-			uint8 buf[16];
+			int account_id = RFIFOL(fd,2);
+			RFIFOSKIP(fd,6);
 
-			account_id = RFIFOL(fd,2);
 			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `sex` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) )
 				Sql_ShowDebug(sql_handle);
 			else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
 			{
+				unsigned char buf[7];
+				int sex;
 				char* data;
 
 				Sql_GetData(sql_handle, 0, &data, NULL);
@@ -982,8 +968,6 @@ int parse_fromchar(int fd)
 				WBUFB(buf,6) = sex;
 				charif_sendallwos(-1, buf, 7);
 			}
-
-			RFIFOSKIP(fd,6);
 		}
 		break;
 
@@ -1028,28 +1012,20 @@ int parse_fromchar(int fd)
 				}
 				SqlStmt_Free(stmt);
 
-				{// Send to char
-					//uint8* buf;
-					//CREATE(buf, uint8, RFIFOW(fd,2));
-					//memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2));
-					//WBUFW(buf,0)=0x2729;
-					//charif_sendallwos(fd, buf, WBUFW(buf,2));
-					//aFree(buf);
-
-					RFIFOW(fd,0) = 0x2729;// reusing read buffer
-					charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2));
-				}
+				// Sending information towards the other char-servers.
+				RFIFOW(fd,0) = 0x2729;// reusing read buffer
+				charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2));
+				RFIFOSKIP(fd,RFIFOW(fd,2));
 			}
-			RFIFOSKIP(fd,RFIFOW(fd,2));
 		break;
 
 		case 0x272a:	// Receiving of map-server via char-server an unban request
 			if( RFIFOREST(fd) < 6 )
 				return 0;
 		{
-			int account_id;
+			int account_id = RFIFOL(fd,2);
+			RFIFOSKIP(fd,6);
 
-			account_id = RFIFOL(fd,2);
 			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) )
 				Sql_ShowDebug(sql_handle);
 			else if( Sql_NumRows(sql_handle) > 0 )
@@ -1057,10 +1033,8 @@ int parse_fromchar(int fd)
 				if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `ban_until` = '0' WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) )
 					Sql_ShowDebug(sql_handle);
 			}
-
-			RFIFOSKIP(fd,6);
-			return 0;
 		}
+		break;
 
 		case 0x272b:    // Set account_id to online [Wizputer]
 			if( RFIFOREST(fd) < 6 )
@@ -1104,18 +1078,21 @@ int parse_fromchar(int fd)
 			if (RFIFOREST(fd) < 10)
 				return 0;
 		{
-			int account_id = RFIFOL(fd, 2);
-			int char_id = RFIFOL(fd, 6);
 			size_t off;
 
-			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", reg_db, account_id) )
-				Sql_ShowDebug(sql_handle);
+			int account_id = RFIFOL(fd,2);
+			int char_id = RFIFOL(fd,6);
+			RFIFOSKIP(fd,10);
 
 			WFIFOHEAD(fd,10000);
 			WFIFOW(fd,0) = 0x2729;
 			WFIFOL(fd,4) = account_id;
 			WFIFOL(fd,8) = char_id;
 			WFIFOB(fd,12) = 1; //Type 1 for Account2 registry
+
+			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", reg_db, account_id) )
+				Sql_ShowDebug(sql_handle);
+
 			off = 13;
 			while( SQL_SUCCESS == Sql_NextRow(sql_handle) && off < 9000 )
 			{
@@ -1133,12 +1110,12 @@ int parse_fromchar(int fd)
 				}
 			}
 			Sql_FreeResult(sql_handle);
+
 			if( off >= 9000 )
 				ShowWarning("Too many account2 registries for AID %d. Some registries were not sent.\n", account_id);
+
 			WFIFOW(fd,2) = (uint16)off;
 			WFIFOSET(fd,WFIFOW(fd,2));
-
-			RFIFOSKIP(fd,10);
 		}
 		break;
 
@@ -1235,6 +1212,7 @@ int parse_login(int fd)
 
 		switch( command )
 		{
+
 		case 0x0200:		// New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
 			if (RFIFOREST(fd) < 26)
 				return 0;
@@ -1280,10 +1258,14 @@ int parse_login(int fd)
 
 			memset(&account, 0, sizeof(account));
 			account.version = RFIFOL(fd,2);
-			if( !account.version )
-				account.version = 1; //Force some version...
 			safestrncpy(account.userid, (char*)RFIFOP(fd,6), NAME_LENGTH);//## does it have to be nul-terminated?
-			safestrncpy(account.passwd, (char*)RFIFOP(fd,30), NAME_LENGTH);//## does it have to be nul-terminated?
+			if (command != 0x01dd) {
+				safestrncpy(account.passwd, (char*)RFIFOP(fd,30), NAME_LENGTH);//## does it have to be nul-terminated?
+			} else {
+				memcpy(account.passwd, RFIFOP(fd,30), 16); account.passwd[16] = '\0'; // raw binary data here!
+			}
+			RFIFOSKIP(fd,packet_len);
+
 			account.passwdenc = (command == 0x01dd) ? PASSWORDENC : 0;
 			Sql_EscapeStringLen(sql_handle, esc_userid, account.userid, strlen(account.userid));
 
@@ -1444,12 +1426,11 @@ int parse_login(int fd)
 				}
 				WFIFOSET(fd,23);
 			}
-
-			RFIFOSKIP(fd,packet_len);
 		}
 		break;
 
 		case 0x01db:	// Sending request of the coding key
+			RFIFOSKIP(fd,2);
 		{
 			struct login_session_data* ld;
 			if( session[fd]->session_data )
@@ -1473,8 +1454,6 @@ int parse_login(int fd)
 			WFIFOW(fd,2) = 4 + ld->md5keylen;
 			memcpy(WFIFOP(fd,4), ld->md5key, ld->md5keylen);
 			WFIFOSET(fd,WFIFOW(fd,2));
-
-			RFIFOSKIP(fd,2);
 		}
 		break;
 
@@ -1482,23 +1461,28 @@ int parse_login(int fd)
 			if (RFIFOREST(fd) < 86)
 				return 0;
 		{
+			char server_name[20];
 			char esc_server_name[20*2+1];
-			char* server_name;
 			uint32 server_ip;
 			uint16 server_port;
+			uint16 maintenance;
+			uint16 new_;
 
 			memset(&account, 0, sizeof(account));
+			account.passwdenc = 0;
 			safestrncpy(account.userid, (char*)RFIFOP(fd,2), NAME_LENGTH);
 			safestrncpy(account.passwd, (char*)RFIFOP(fd,26), NAME_LENGTH);
-			account.passwdenc = 0;
 			server_ip = ntohl(RFIFOL(fd,54));
 			server_port = ntohs(RFIFOW(fd,58));
-			server_name = (char*)RFIFOP(fd,60);
+			safestrncpy(server_name, (char*)RFIFOP(fd,60), 20);
+			maintenance = RFIFOW(fd,82);
+			new_ = RFIFOW(fd,84);
+			RFIFOSKIP(fd,86);
 
 			Sql_EscapeStringLen(sql_handle, esc_server_name, server_name, strnlen(server_name, 20));
 			Sql_EscapeStringLen(sql_handle, esc_userid, account.userid, strnlen(account.userid, NAME_LENGTH));
 
-			ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (account: '%s', pass: '%s', ip: '%s')\n", esc_server_name, CONVIP(server_ip), server_port, account.userid, account.passwd, ip);
+			ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (account: '%s', pass: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, account.userid, account.passwd, ip);
 
 			if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s@%s','100', 'charserver - %s@%u.%u.%u.%u:%d')",
 				loginlog_db, ipl, esc_userid, esc_server_name, esc_server_name, CONVIP(server_ip), server_port) )
@@ -1507,44 +1491,45 @@ int parse_login(int fd)
 			result = mmo_auth(&account, fd);
 			if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server[account.account_id].fd == -1 )
 			{
-				ShowStatus("Connection of the char-server '%s' accepted.\n", esc_server_name);
-				memset(&server[account.account_id], 0, sizeof(struct mmo_char_server));
-				server[account.account_id].ip = ntohl(RFIFOL(fd,54));
-				server[account.account_id].port = ntohs(RFIFOW(fd,58));
+				ShowStatus("Connection of the char-server '%s' accepted.\n", server_name);
 				safestrncpy(server[account.account_id].name, server_name, sizeof(server[account.account_id].name));
-				server[account.account_id].users = 0;
-				server[account.account_id].maintenance = RFIFOW(fd,82);
-				server[account.account_id].new_ = RFIFOW(fd,84);
 				server[account.account_id].fd = fd;
+				server[account.account_id].ip = server_ip;
+				server[account.account_id].port = server_port;
+				server[account.account_id].users = 0;
+				server[account.account_id].maintenance = maintenance;
+				server[account.account_id].new_ = new_;
+
+				session[fd]->func_parse = parse_fromchar;
+				session[fd]->flag.server = 1;
+				realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
 
+				// send connection success
 				WFIFOHEAD(fd,3);
 				WFIFOW(fd,0) = 0x2711;
 				WFIFOB(fd,2) = 0;
 				WFIFOSET(fd,3);
 
-				session[fd]->func_parse = parse_fromchar;
-				session[fd]->flag.server = 1;
-				realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
-
-				send_GM_accounts(fd); // send GM account to char-server
+				// send GM account to char-server
+				send_GM_accounts(fd);
 
 				if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%d', '%s', '%d')", account.account_id, esc_server_name, 0) )
 					Sql_ShowDebug(sql_handle);
 			}
 			else
 			{
-				ShowNotice("Connection of the char-server '%s' REFUSED.\n", esc_server_name);
+				ShowNotice("Connection of the char-server '%s' REFUSED.\n", server_name);
 				WFIFOHEAD(fd,3);
 				WFIFOW(fd,0) = 0x2711;
 				WFIFOB(fd,2) = 3;
 				WFIFOSET(fd,3);
 			}
 		}
-			RFIFOSKIP(fd,86);
-			return 0;
+		return 0; // processing will continue elsewhere
 
 		case 0x7530:	// Server version information request
 			ShowStatus("Sending server version information to ip: %s\n", ip);
+			RFIFOSKIP(fd,2);
 			WFIFOHEAD(fd,10);
 			WFIFOW(fd,0) = 0x7531;
 			WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
@@ -1555,13 +1540,6 @@ int parse_login(int fd)
 			WFIFOB(fd,7) = ATHENA_SERVER_LOGIN;
 			WFIFOW(fd,8) = ATHENA_MOD_VERSION;
 			WFIFOSET(fd,10);
-
-			RFIFOSKIP(fd,2);
-		break;
-
-		case 0x7532:	// Request to end connection
-			ShowStatus("End of connection (ip: %s)\n", ip);
-			set_eof(fd);
 		break;
 
 		default:
@@ -1654,11 +1632,6 @@ int login_lan_config_read(const char *lancfgName)
 			continue;
 		}
 
-		remove_control_chars(w1);
-		remove_control_chars(w2);
-		remove_control_chars(w3);
-		remove_control_chars(w4);
-
 		if( strcmpi(w1, "subnet") == 0 )
 		{
 			subnet[subnet_count].mask = str2ip(w2);
@@ -1712,9 +1685,6 @@ int login_config_read(const char* cfgName)
 		if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2)
 			continue;
 
-		remove_control_chars(w1);
-		remove_control_chars(w2);
-
 		if(!strcmpi(w1,"timestamp_format"))
 			strncpy(timestamp_format, w2, 20);
 		else if(!strcmpi(w1,"stdout_with_ansisequence"))

+ 3 - 7
src/map/itemdb.c

@@ -161,13 +161,9 @@ int itemdb_group_bonus(struct map_session_data* sd, int itemid)
 	for (i=0; i < MAX_ITEMGROUP; i++) {
 		if (!sd->itemgrouphealrate[i])
 			continue;
-		for (j=0; j < itemgroup_db[i].qty; j++) {
-			if (itemgroup_db[i].nameid[j] == itemid)
-			{
-				bonus += sd->itemgrouphealrate[i];
-				break;
-			}
-		}
+		ARR_FIND( 0, itemgroup_db[i].qty, j, itemgroup_db[i].nameid[j] == itemid );
+		if( j < itemgroup_db[i].qty )
+			bonus += sd->itemgrouphealrate[i];
 	}
 	return bonus;
 }

+ 1 - 0
src/map/itemdb.h

@@ -36,6 +36,7 @@ enum item_types {
 
 //The only item group required by the code to be known. See const.txt for the full list.
 #define IG_FINDINGORE 6
+#define IG_POTION 37
 //The max. item group count (increase this when needed).
 #define MAX_ITEMGROUP 40
 

+ 4 - 3
src/map/skill.c

@@ -4082,10 +4082,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 							sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100;
 					}
 				}
-				if (sd->itemgrouphealrate[37]>0)
+
+				if (sd->itemgrouphealrate[IG_POTION]>0)
 				{
-					hp += hp * sd->itemgrouphealrate[37] / 100;
-					sp += sp * sd->itemgrouphealrate[37] / 100;
+					hp += hp * sd->itemgrouphealrate[IG_POTION] / 100;
+					sp += sp * sd->itemgrouphealrate[IG_POTION] / 100;
 				}
 
 				if ((i = pc_skillheal_bonus(sd, skillid)))