summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt7
-rw-r--r--sql-files/main.sql8
-rw-r--r--sql-files/upgrade_svn12043.sql5
-rw-r--r--src/char/char.c5
-rw-r--r--src/char_sql/char.c5
-rw-r--r--src/login/admin.c6
-rw-r--r--src/login/login.c499
-rw-r--r--src/login_sql/login.c308
-rw-r--r--src/map/itemdb.c10
-rw-r--r--src/map/itemdb.h1
-rw-r--r--src/map/skill.c7
11 files changed, 412 insertions, 449 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index dbabe4264..9129294c5 100644
--- a/Changelog-Trunk.txt
+++ b/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
diff --git a/sql-files/main.sql b/sql-files/main.sql
index e19b7567f..5c5a7a0e6 100644
--- a/sql-files/main.sql
+++ b/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`)
diff --git a/sql-files/upgrade_svn12043.sql b/sql-files/upgrade_svn12043.sql
new file mode 100644
index 000000000..c811bab91
--- /dev/null
+++ b/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 '';
diff --git a/src/char/char.c b/src/char/char.c
index 42f5b83b0..d853a72ba 100644
--- a/src/char/char.c
+++ b/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));
diff --git a/src/char_sql/char.c b/src/char_sql/char.c
index 8dd8738b2..30e33f011 100644
--- a/src/char_sql/char.c
+++ b/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));
diff --git a/src/login/admin.c b/src/login/admin.c
index 152c9e84d..32b89fc4d 100644
--- a/src/login/admin.c
+++ b/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;
diff --git a/src/login/login.c b/src/login/login.c
index 0fb728ff2..6ed9fdb6a 100644
--- a/src/login/login.c
+++ b/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"))
diff --git a/src/login_sql/login.c b/src/login_sql/login.c
index 45fc548c5..5a197ca43 100644
--- a/src/login_sql/login.c
+++ b/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"))
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index b27074866..fcd6c804d 100644
--- a/src/map/itemdb.c
+++ b/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;
}
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 507478196..865ceaf9d 100644
--- a/src/map/itemdb.h
+++ b/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
diff --git a/src/map/skill.c b/src/map/skill.c
index 33368da97..fe2fff2a5 100644
--- a/src/map/skill.c
+++ b/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)))