diff options
-rw-r--r-- | Changelog-Trunk.txt | 9 | ||||
-rw-r--r-- | src/map/atcommand.c | 6 | ||||
-rw-r--r-- | src/map/clif.c | 175 | ||||
-rw-r--r-- | src/map/log.c | 84 | ||||
-rw-r--r-- | src/map/log.h | 2 | ||||
-rw-r--r-- | src/map/map.h | 13 | ||||
-rw-r--r-- | src/map/script.c | 40 | ||||
-rw-r--r-- | src/map/skill.c | 7 |
8 files changed, 164 insertions, 172 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 2ecc91c19..8c61484e8 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,6 +3,13 @@ Date Added AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. +2007/10/09 + * Corrected string lengths according to bugreport:198 [ultramage] + - CHATBOX_SIZE: 70 -> 70+1 + - removed some too aggressive checks in clif_parse_globalmessage() + - removed CHAT_SIZE define as it actually doesn't apply anywhere + - added CHAT_SIZE_MAX to serve as a custom limit to input string lengths + - added length/contents checks to /b and /lb (against fake names) 2007/10/08 * Delayed the check for required items when a skill is cast to when they are consumed. Now skills only fail due to lack of items after being cast. @@ -20,7 +27,7 @@ IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. * Removed that ridiculous spinner that displays during map/npc loading - and added a more informative progress indicator (idea from jA/eapp) * Removed loads of code that supported these functions - - -100b per npc => -1,5MB of wasted memory + - -230b per npc => -3MB of wasted memory * Fixed related npcs that erroneously used 'stoptimer' * Checked/fixed/removed some old script and npc commands + cmdothernpc diff --git a/src/map/atcommand.c b/src/map/atcommand.c index bfb20570a..1d05e915f 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -906,7 +906,7 @@ int atcommand_config_read(const char *cfgName) *------------------------------------------*/ int atcommand_commands(const int fd, struct map_session_data* sd, const char* command, const char* message) { - char cz_line_buff[CHATBOX_SIZE+1]; + char cz_line_buff[CHATBOX_SIZE]; register char *lpcz_cur = cz_line_buff; register unsigned int ui_slen; @@ -914,7 +914,7 @@ int atcommand_commands(const int fd, struct map_session_data* sd, const char* co int i_cur_cmd,gm_lvl = pc_isGM(sd), count = 0; memset(cz_line_buff,' ',CHATBOX_SIZE); - cz_line_buff[CHATBOX_SIZE] = 0; + cz_line_buff[CHATBOX_SIZE-1] = 0; clif_displaymessage(fd, msg_txt(273)); @@ -932,7 +932,7 @@ int atcommand_commands(const int fd, struct map_session_data* sd, const char* co clif_displaymessage(fd,(char*)cz_line_buff); lpcz_cur = cz_line_buff; memset(cz_line_buff,' ',CHATBOX_SIZE); - cz_line_buff[CHATBOX_SIZE] = 0; + cz_line_buff[CHATBOX_SIZE-1] = 0; } memcpy(lpcz_cur,atcommand_info[i_cur_cmd].command,ui_slen); diff --git a/src/map/clif.c b/src/map/clif.c index 3e7919159..379f2829b 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -6923,12 +6923,11 @@ void clif_emotion(struct block_list *bl,int type) void clif_talkiebox(struct block_list* bl, const char* talkie) { unsigned char buf[86]; - nullpo_retv(bl); - WBUFW(buf,0)=0x191; - WBUFL(buf,2)=bl->id; - memcpy(WBUFP(buf,6),talkie,MESSAGE_SIZE); + WBUFW(buf,0) = 0x191; + WBUFL(buf,2) = bl->id; + safestrncpy((char*)WBUFP(buf,6),talkie,MESSAGE_SIZE); clif_send(buf,packet_len(0x191),bl,AREA); } @@ -8212,7 +8211,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) /*========================================== * Validates and processes global messages - * S 008c/00f3 <packet len>.w <text>.?B (<name> : <message>) + * S 008c/00f3 <packet len>.w <text>.?B (<name> : <message>) 00 *------------------------------------------*/ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) { @@ -8223,12 +8222,12 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) // basic structure checks if( packetlen > RFIFOREST(fd) ) { // there has to be enough data to read - ShowWarning("clif_parse_GlobalMessage: Received malformed packet from player '%s' (length is incorrect)!", sd->status.name); + ShowWarning("clif_parse_GlobalMessage: Received malformed packet from player '%s' (length is incorrect)!\n", sd->status.name); return; } if( packetlen < 4 + 1 ) { // 4-byte header and at least an empty string is expected - ShowWarning("clif_parse_GlobalMessage: Received malformed packet from player '%s' (no message data)!", sd->status.name); + ShowWarning("clif_parse_GlobalMessage: Received malformed packet from player '%s' (no message data)!\n", sd->status.name); return; } @@ -8242,41 +8241,31 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) name[namelen] != ' ' || name[namelen+1] != ':' || name[namelen+2] != ' ' ) // followed by ' : ' { //Hacked message, or infamous "client desynch" issue where they pick one char while loading another. - ShowWarning("clif_parse_GlobalMessage: Player '%s' sent a message using an incorrect name! Forcing a relog...", sd->status.name); + ShowWarning("clif_parse_GlobalMessage: Player '%s' sent a message using an incorrect name! Forcing a relog...\n", sd->status.name); clif_setwaitclose(fd); // Just kick them out to correct it. return; } message = text + namelen + 3; - messagelen = textlen - namelen - 3 - 1; // this should be the message length + messagelen = textlen - namelen - 3; // this should be the message length (w/ zero byte included) // verify <message> part of the packet - if( message[messagelen] != '\0' ) + if( message[messagelen-1] != '\0' ) { // message must be zero-terminated - ShowWarning("clif_parse_GlobalMessage: Player '%s' sent an unterminated string!", sd->status.name); + ShowWarning("clif_parse_GlobalMessage: Player '%s' sent an unterminated string!\n", sd->status.name); return; } - if( messagelen != strnlen(message, messagelen+1) ) + if( messagelen != strnlen(message, messagelen)+1 ) { // the declared length must match real length - ShowWarning("clif_parse_GlobalMessage: Received malformed packet from player '%s' (length is incorrect)!", sd->status.name); + ShowWarning("clif_parse_GlobalMessage: Received malformed packet from player '%s' (length is incorrect)!\n", sd->status.name); return; } - if( messagelen > CHATBOX_SIZE ) + if( messagelen > CHAT_SIZE_MAX ) { // messages mustn't be too long - int i; - // special case here - allow some more freedom for frost joke & dazzler - // TODO:? You could use a state flag when FrostJoke/Scream is used, and unset it once the skill triggers. [Skotlex] - ARR_FIND( 0, MAX_SKILLTIMERSKILL, i, sd->ud.skilltimerskill[i] == 0 || sd->ud.skilltimerskill[i]->skill_id == BA_FROSTJOKE || sd->ud.skilltimerskill[i]->skill_id == DC_SCREAM ); - - if( i == MAX_SKILLTIMERSKILL || !sd->ud.skilltimerskill[i]) - { // normal message, too long - ShowWarning("clif_parse_GlobalMessage: Player '%s' sent a message too long ('%.*s')!", sd->status.name, CHATBOX_SIZE, message); - return; - } - if( messagelen > 255 ) - { // frost joke/dazzler, but still too long - ShowWarning("clif_parse_GlobalMessage: Player '%s' sent a message too long ('%.*s')!", sd->status.name, 255, message); - return; - } + // Normally you can only enter CHATBOX_SIZE-1 chars into the chat box, but Frost Joke / Dazzler's text can be longer. + // Neither the official client nor server place any restriction on the length of the text in the packet, + // but we'll only allow reasonably long strings here. This also makes sure all strings fit into the `chatlog` table. + ShowWarning("clif_parse_GlobalMessage: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHAT_SIZE_MAX, message); + return; } if( is_atcommand(fd, sd, text) != AtCommand_None || is_charcommand(fd, sd, text) != CharCommand_None ) @@ -8771,26 +8760,40 @@ void clif_parse_Wis(int fd, struct map_session_data* sd) /*========================================== * /b + * S 0099 <packet len>.w <text>.?B (<name>: <message>) 00 *------------------------------------------*/ -void clif_parse_GMmessage(int fd, struct map_session_data *sd) +void clif_parse_GMmessage(int fd, struct map_session_data* sd) { - char* mes; - int size, lv; + char *text, *name, *message; + unsigned int textlen, namelen, messagelen; + int lv; if (battle_config.atc_gmonly && !pc_isGM(sd)) return; if (pc_isGM(sd) < (lv=get_atcommand_level(AtCommand_Broadcast))) return; - size = RFIFOW(fd,2)-4; - mes = (char*)RFIFOP(fd,4); - mes_len_check(mes, size, CHAT_SIZE); + text = (char*)RFIFOP(fd,4); + textlen = RFIFOW(fd,2) - 4; + + name = text; + namelen = strnlen(sd->status.name, NAME_LENGTH - 1); + // verify <name> part of the packet + if( strncmp(name, sd->status.name, namelen) || // the text must start with the speaker's name + name[namelen] != ':' || name[namelen+1] != ' ' ) // followed by ': ' + return; + + // make sure the <message> part of the packet is safe to handle + message = text + namelen + 2; + messagelen = textlen - namelen - 2; // this should be the message length (w/ zero byte included) + mes_len_check(message, messagelen, CHATBOX_SIZE); + + intif_GMmessage(text, textlen, 0); - intif_GMmessage(mes, size, 0); if(log_config.gm && lv >= log_config.gm) { - char message[CHAT_SIZE+4]; - sprintf(message, "/b %s", mes); - log_atcommand(sd, message); + char msg[CHATBOX_SIZE+4]; + sprintf(msg, "/b %s", message); + log_atcommand(sd, msg); } } @@ -9468,8 +9471,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, int skilll return; } //You can't use Graffiti/TalkieBox AND have a vending open, so this is safe. - memcpy(sd->message, RFIFOP(fd,skillmoreinfo), MESSAGE_SIZE); - sd->message[MESSAGE_SIZE-1] = '\0'; //Overflow protection [Skotlex] + safestrncpy(sd->message, (char*)RFIFOP(fd,skillmoreinfo), MESSAGE_SIZE); } if (sd->ud.skilltimer != -1) @@ -9649,34 +9651,30 @@ void clif_parse_NpcNextClicked(int fd,struct map_session_data *sd) } /*========================================== - * + * Value entered into a NPC input box. + * S 0143 <npcID>.l <amount>.l *------------------------------------------*/ void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd) { - sd->npc_amount=(int)RFIFOL(fd,6); - npc_scriptcont(sd,RFIFOL(fd,2)); + int npcid = RFIFOL(fd,2); + int amount = (int)RFIFOL(fd,6); + + sd->npc_amount = amount; + npc_scriptcont(sd, npcid); } /*========================================== - * + * Text entered into a NPC input box. + * S 01d5 <len>.w <npcID>.l <input>.?B 00 *------------------------------------------*/ -void clif_parse_NpcStringInput(int fd,struct map_session_data *sd) +void clif_parse_NpcStringInput(int fd, struct map_session_data* sd) { - short message_len; - message_len = RFIFOW(fd,2)-7; - - if(message_len < 1) - return; //Blank message? - - if(message_len >= sizeof(sd->npc_str)){ - ShowWarning("clif: input string too long !\n"); - message_len = sizeof(sd->npc_str); - } + int message_len = RFIFOW(fd,2)-8; + int npcid = RFIFOL(fd,4); + const char* message = (char*)RFIFOP(fd,8); - // Exploit prevention if crafted packets (without null) is being sent. [Lance] - memcpy(sd->npc_str,RFIFOP(fd,8),message_len); - sd->npc_str[message_len-1]=0; - npc_scriptcont(sd,RFIFOL(fd,4)); + safestrncpy(sd->npc_str, message, min(message_len,CHATBOX_SIZE)); + npc_scriptcont(sd, npcid); } /*========================================== @@ -9775,31 +9773,46 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) } /*========================================== - * 019c /lb“™ + * /lb + * S 019c <packet len>.w <text>.?B (<name>: <message>) 00 *------------------------------------------*/ -void clif_parse_LGMmessage(int fd, struct map_session_data *sd) +void clif_parse_LGMmessage(int fd, struct map_session_data* sd) { - unsigned char buf[CHAT_SIZE+4]; - char *mes; - int len, lv; + char *text, *name, *message; + unsigned int textlen, namelen, messagelen; + + unsigned char buf[CHATBOX_SIZE+4]; + int lv; if (battle_config.atc_gmonly && !pc_isGM(sd)) return; if (pc_isGM(sd) < (lv=get_atcommand_level(AtCommand_LocalBroadcast))) return; - len = RFIFOW(fd,2) - 4; - mes = (char*)RFIFOP(fd,4); - mes_len_check(mes, len, CHAT_SIZE); + text = (char*)RFIFOP(fd,4); + textlen = RFIFOW(fd,2) - 4; + + name = text; + namelen = strnlen(sd->status.name, NAME_LENGTH - 1); + // verify <name> part of the packet + if( strncmp(name, sd->status.name, namelen) || // the text must start with the speaker's name + name[namelen] != ':' || name[namelen+1] != ' ' ) // followed by ': ' + return; + + // make sure the <message> part of the packet is safe to handle + message = text + namelen + 2; + messagelen = textlen - namelen - 2; // this should be the message length (w/ zero byte included) + mes_len_check(message, messagelen, CHATBOX_SIZE); WBUFW(buf,0) = 0x9a; - WBUFW(buf,2) = len+4; - memcpy(WBUFP(buf,4), mes, len); + WBUFW(buf,2) = textlen+4; + memcpy(WBUFP(buf,4), text, textlen); clif_send(buf, WBUFW(buf,2), &sd->bl, ALL_SAMEMAP); + if(log_config.gm && lv >= log_config.gm) { - char message[CHAT_SIZE+5]; - sprintf(message, "/lb %s", mes); - log_atcommand(sd, message); + char msg[CHATBOX_SIZE+5]; + sprintf(msg, "/lb %s", message); + log_atcommand(sd, msg); } } @@ -10040,12 +10053,10 @@ void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd) *------------------------------------------*/ void clif_parse_PartyMessage(int fd, struct map_session_data* sd) { - char* message; - int len; + int len = RFIFOW(fd,2) - 4; + char* message = (char*)RFIFOP(fd,4); - len = RFIFOW(fd,2) - 4; - message = (char*)RFIFOP(fd,4); - mes_len_check(message, len, CHAT_SIZE); + mes_len_check(message, len, CHATBOX_SIZE); if (is_charcommand(fd, sd, message) != CharCommand_None || is_atcommand(fd, sd, message) != AtCommand_None) return; @@ -10309,12 +10320,10 @@ void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) *------------------------------------------*/ void clif_parse_GuildMessage(int fd, struct map_session_data* sd) { - char* message; - int len; + int len = RFIFOW(fd,2) - 4; + char* message = (char*)RFIFOP(fd,4); - len = RFIFOW(fd,2) - 4; - message = (char*)RFIFOP(fd,4); - mes_len_check(message, len, CHAT_SIZE); + mes_len_check(message, len, CHATBOX_SIZE); if (is_charcommand(fd, sd, message) != CharCommand_None || is_atcommand(fd, sd, message) != AtCommand_None) return; diff --git a/src/map/log.c b/src/map/log.c index 97a802a0c..b50bcfb70 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -66,7 +66,7 @@ int log_branch(struct map_session_data *sd) nullpo_retr(0, sd); #ifndef TXT_ONLY - if(log_config.sql_logs > 0) + if( log_config.sql_logs ) { SqlStmt* stmt; stmt = SqlStmt_Malloc(logmysql_handle); @@ -104,18 +104,16 @@ int log_pick_pc(struct map_session_data *sd, const char *type, int nameid, int a return 0; //we skip logging this item set - it doesn't meet our logging conditions [Lupus] #ifndef TXT_ONLY - if(log_config.sql_logs > 0) + if( log_config.sql_logs ) { - if (itm == NULL) { - //We log common item + if( itm == NULL ) { //We log common item if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%s')", log_config.log_pick_db, sd->status.char_id, type, nameid, amount, mapindex_id2name(sd->mapindex)) ) { Sql_ShowDebug(logmysql_handle); return 0; } - } else { - //We log Extended item + } else { //We log Extended item if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", log_config.log_pick_db, sd->status.char_id, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapindex_id2name(sd->mapindex)) ) { @@ -134,15 +132,10 @@ int log_pick_pc(struct map_session_data *sd, const char *type, int nameid, int a time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - if (itm == NULL) { - //We log common item - fprintf(logfp,"%s - %d\t%s\t%d,%d,%s\n", - timestring, sd->status.char_id, type, nameid, amount, mapindex_id2name(sd->mapindex)); - - } else { - //We log Extended item - fprintf(logfp,"%s - %d\t%s\t%d,%d,%d,%d,%d,%d,%d,%s\n", - timestring, sd->status.char_id, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapindex_id2name(sd->mapindex)); + if( itm == NULL ) { //We log common item + fprintf(logfp,"%s - %d\t%s\t%d,%d,%s\n", timestring, sd->status.char_id, type, nameid, amount, mapindex_id2name(sd->mapindex)); + } else { //We log Extended item + fprintf(logfp,"%s - %d\t%s\t%d,%d,%d,%d,%d,%d,%d,%s\n", timestring, sd->status.char_id, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapindex_id2name(sd->mapindex)); } fclose(logfp); } @@ -166,18 +159,16 @@ int log_pick_mob(struct mob_data *md, const char *type, int nameid, int amount, mapname=""; #ifndef TXT_ONLY - if(log_config.sql_logs > 0) + if( log_config.sql_logs ) { - if (itm==NULL) { - //We log common item + if( itm == NULL ) { //We log common item if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%s')", log_config.log_pick_db, md->class_, type, nameid, amount, mapname) ) { Sql_ShowDebug(logmysql_handle); return 0; } - } else { - //We log Extended item + } else { //We log Extended item if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", log_config.log_pick_db, md->class_, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapname) ) { @@ -196,15 +187,10 @@ int log_pick_mob(struct mob_data *md, const char *type, int nameid, int amount, time(&curtime); strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - if (itm==NULL) { - //We log common item - fprintf(logfp,"%s - %d\t%s\t%d,%d,%s\n", - timestring, md->class_, type, nameid, amount, mapname); - - } else { - //We log Extended item - fprintf(logfp,"%s - %d\t%s\t%d,%d,%d,%d,%d,%d,%d,%s\n", - timestring, md->class_, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapname); + if( itm == NULL ) { //We log common item + fprintf(logfp,"%s - %d\t%s\t%d,%d,%s\n", timestring, md->class_, type, nameid, amount, mapname); + } else { //We log Extended item + fprintf(logfp,"%s - %d\t%s\t%d,%d,%d,%d,%d,%d,%d,%s\n", timestring, md->class_, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapname); } fclose(logfp); } @@ -220,7 +206,7 @@ int log_zeny(struct map_session_data *sd, char *type, struct map_session_data *s nullpo_retr(0, sd); #ifndef TXT_ONLY - if(log_config.sql_logs > 0) + if( log_config.sql_logs ) { if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%s')", log_config.log_zeny_db, sd->status.char_id, src_sd->status.char_id, type, amount, mapindex_id2name(sd->mapindex)) ) @@ -252,7 +238,7 @@ int log_mvpdrop(struct map_session_data *sd, int monster_id, int *log_mvp) nullpo_retr(0, sd); #ifndef TXT_ONLY - if(log_config.sql_logs > 0) + if( log_config.sql_logs ) { if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", log_config.log_mvpdrop_db, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)) ) @@ -285,16 +271,10 @@ int log_atcommand(struct map_session_data* sd, const char* message) nullpo_retr(0, sd); #ifndef TXT_ONLY - if(log_config.sql_logs > 0) + if( log_config.sql_logs ) { SqlStmt* stmt; - if (strlen(message) > CHAT_SIZE) { - if (battle_config.error_log) - ShowError("log atcommand: Received message too long from player %s (%d:%d)!\n", sd->status.name, sd->status.account_id, sd->status.char_id); - return 0; - } - stmt = SqlStmt_Malloc(logmysql_handle); if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT DELAYED INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", log_config.log_gm_db, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) @@ -330,7 +310,7 @@ int log_npc(struct map_session_data* sd, const char* message) nullpo_retr(0, sd); #ifndef TXT_ONLY - if(log_config.sql_logs > 0) + if( log_config.sql_logs ) { SqlStmt* stmt; stmt = SqlStmt_Malloc(logmysql_handle); @@ -380,20 +360,14 @@ int log_chat(const char* type, int type_id, int src_charid, int src_accid, const return 0; //Deactivated #ifndef TXT_ONLY - if(log_config.sql_logs > 0) + if( log_config.sql_logs ) { SqlStmt* stmt; - if (strlen(message) > CHAT_SIZE) { - if (battle_config.error_log) - ShowError("log chat: Received message too long from type %d (%d:%d)!\n", type_id, src_accid, src_charid); - return 0; - } - stmt = SqlStmt_Malloc(logmysql_handle); if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT DELAYED INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%s', '%d', '%d', '%d', '%s', '%d', '%d', ?, ?)", log_config.log_chat_db, type, type_id, src_charid, src_accid, map, x, y) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (char*)dst_charname, safestrnlen(dst_charname, NAME_LENGTH)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, CHAT_SIZE)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, CHAT_SIZE_MAX)) || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); @@ -456,7 +430,7 @@ int log_config_read(char *cfgName) if (log_config.enable_logs&1) //Log everything. log_config.enable_logs=0xFFFFFFFF; } else if(strcmpi(w1,"sql_logs") == 0) { - log_config.sql_logs = (atoi(w2)); + log_config.sql_logs = (bool)atoi(w2); //start of common filter settings } else if(strcmpi(w1,"rare_items_log") == 0) { log_config.rare_items_log = (atoi(w2)); @@ -517,31 +491,31 @@ int log_config_read(char *cfgName) else if(strcmpi(w1, "log_branch_file") == 0) { strcpy(log_config.log_branch, w2); - if(log_config.branch > 0 && log_config.sql_logs < 1) + if(log_config.branch > 0 && !log_config.sql_logs) ShowNotice("Logging Dead Branch Usage to file `%s`.txt\n", w2); } else if(strcmpi(w1, "log_pick_file") == 0) { strcpy(log_config.log_pick, w2); - if(log_config.filter > 0 && log_config.sql_logs < 1) + if(log_config.filter > 0 && !log_config.sql_logs) ShowNotice("Logging Item Picks to file `%s`.txt\n", w2); } else if(strcmpi(w1, "log_zeny_file") == 0) { strcpy(log_config.log_zeny, w2); - if(log_config.zeny > 0 && log_config.sql_logs < 1) + if(log_config.zeny > 0 && !log_config.sql_logs) ShowNotice("Logging Zeny to file `%s`.txt\n", w2); } else if(strcmpi(w1, "log_mvpdrop_file") == 0) { strcpy(log_config.log_mvpdrop, w2); - if(log_config.mvpdrop > 0 && log_config.sql_logs < 1) + if(log_config.mvpdrop > 0 && !log_config.sql_logs) ShowNotice("Logging MVP Drops to file `%s`.txt\n", w2); } else if(strcmpi(w1, "log_gm_file") == 0) { strcpy(log_config.log_gm, w2); - if(log_config.gm > 0 && log_config.sql_logs < 1) + if(log_config.gm > 0 && !log_config.sql_logs) ShowNotice("Logging GM Level %d Commands to file `%s`.txt\n", log_config.gm, w2); } else if(strcmpi(w1, "log_npc_file") == 0) { strcpy(log_config.log_npc, w2); - if(log_config.npc > 0 && log_config.sql_logs < 1) + if(log_config.npc > 0 && !log_config.sql_logs) ShowNotice("Logging NPC 'logmes' to file `%s`.txt\n", w2); } else if(strcmpi(w1, "log_chat_file") == 0) { strcpy(log_config.log_chat, w2); - if(log_config.chat > 0 && log_config.sql_logs < 1) + if(log_config.chat > 0 && !log_config.sql_logs) ShowNotice("Logging CHAT to file `%s`.txt\n", w2); //support the import command, just like any other config } else if(strcmpi(w1,"import") == 0) { diff --git a/src/map/log.h b/src/map/log.h index 0065b77c0..758bebd71 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -41,7 +41,7 @@ enum log_what { extern struct Log_Config { enum log_what enable_logs; int filter; - int sql_logs; + bool sql_logs; int rare_items_log,refine_items_log,price_items_log,amount_items_log; //for filter int branch, drop, mvpdrop, zeny, gm, npc, chat; char log_branch[64], log_pick[64], log_zeny[64], log_mvpdrop[64], log_gm[64], log_npc[64], log_chat[64]; diff --git a/src/map/map.h b/src/map/map.h index 6887098d9..679fd8529 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -163,16 +163,15 @@ enum { MAPID_BABY_SOUL_LINKER, }; -//Max size when inputting a string with those 'npc input boxes' -//(also used for Graffiti, Talkie Box, Vending, and Chatrooms) -#define MESSAGE_SIZE 80 +//Max size for inputs to Graffiti, Talkie Box and Vending text prompts +#define MESSAGE_SIZE (79 + 1) //String length you can write in the 'talking box' -#define CHATBOX_SIZE 70 -//Talk max size: <name> : <message of 70> [Skotlex] -#define CHAT_SIZE (NAME_LENGTH + 3 + CHATBOX_SIZE) +#define CHATBOX_SIZE (70 + 1) //Chatroom-related string sizes #define CHATROOM_TITLE_SIZE (36 + 1) #define CHATROOM_PASS_SIZE (8 + 1) +//Max allowed chat text length +#define CHAT_SIZE_MAX 150 #define DEFAULT_AUTOSAVE_INTERVAL 5*60*1000 @@ -610,7 +609,7 @@ struct map_session_data { int npc_menu; int npc_amount; struct script_state *st; - char npc_str[256]; + char npc_str[CHATBOX_SIZE]; // for passing npc input box text to script engine int npc_timer_id; //For player attached npc timers. [Skotlex] unsigned int chatID; time_t idletime; diff --git a/src/map/script.c b/src/map/script.c index 90ecbb82e..d229b95ef 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -5334,29 +5334,29 @@ BUILDIN_FUNC(input) return 1; } - if(sd->state.menu_or_input){ - sd->state.menu_or_input=0; - if( postfix=='$' ) + if( !sd->state.menu_or_input ) + { // first invocation, display npc input box + sd->state.menu_or_input = 1; + st->state = RERUNLINE; + if( postfix == '$' ) + clif_scriptinputstr(sd,st->oid); + else + clif_scriptinput(sd,st->oid); + } + else + { // take received text/value and store it in the designated variable + sd->state.menu_or_input = 0; + if( postfix == '$' ) { - set_reg(st,sd,num,name,(void*)sd->npc_str, - script_getref(st,2)); - return 0; + set_reg(st,sd,num,name,(void*)sd->npc_str,script_getref(st,2)); + } + else + { + // limit the input to a non-negative value smaller than 'vending_max_value' (for scripts that didn't check this) + sd->npc_amount = cap_value(sd->npc_amount, 0, battle_config.vending_max_value); + set_reg(st,sd,num,name,(void*)sd->npc_amount,script_getref(st,2)); } - // Yor, Lupus & Fritz have messed with this. - // Basicly it prevents negative input since most scripts do not account for them. - sd->npc_amount = cap_value(sd->npc_amount, 0, battle_config.vending_max_value); - - set_reg(st,sd,num,name,(void*)sd->npc_amount, - script_getref(st,2)); - return 0; } - //state.menu_or_input = 0 - st->state=RERUNLINE; - if( postfix=='$' ) - clif_scriptinputstr(sd,st->oid); - else - clif_scriptinput(sd,st->oid); - sd->state.menu_or_input=1; return 0; } diff --git a/src/map/skill.c b/src/map/skill.c index 421ceb6a8..21266e148 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -2729,8 +2729,8 @@ int skill_addtimerskill (struct block_list *src, unsigned int tick, int target, ud = unit_bl2ud(src); nullpo_retr(1, ud); - for(i=0;i<MAX_SKILLTIMERSKILL && ud->skilltimerskill[i]; i++); - if (i==MAX_SKILLTIMERSKILL) return 1; + ARR_FIND( 0, MAX_SKILLTIMERSKILL, i, ud->skilltimerskill[i] == 0 ); + if( i == MAX_SKILLTIMERSKILL ) return 1; ud->skilltimerskill[i] = ers_alloc(skill_timer_ers, struct skill_timerskill); ud->skilltimerskill[i]->timer = add_timer(tick, skill_timerskill, src->id, i); @@ -4393,7 +4393,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case DC_SCREAM: clif_skill_nodamage(src,bl,skillid,skilllv,1); skill_addtimerskill(src,tick+2000,bl->id,src->x,src->y,skillid,skilllv,0,flag); + if (md) { + // custom hack to make the mob display the skill, because these skills don't show the skill use text themselves + //NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches) char temp[128]; if (strlen(md->name) + strlen(skill_db[skillid].desc) > 120) break; //Message won't fit on buffer. [Skotlex] |