diff options
-rw-r--r-- | src/char/char.c | 95 | ||||
-rw-r--r-- | src/char/char.h | 3 | ||||
-rw-r--r-- | src/char/inter.c | 109 | ||||
-rw-r--r-- | src/char/inter.h | 13 | ||||
-rw-r--r-- | src/char/mapif.c | 3 | ||||
-rw-r--r-- | src/char/mapif.h | 2 |
6 files changed, 145 insertions, 80 deletions
diff --git a/src/char/char.c b/src/char/char.c index 3f55bd699..04db83eb9 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -1534,12 +1534,56 @@ int char_rename_char_sql(struct char_session_data *sd, int char_id) return 0; } -int char_check_char_name(char * name, char * esc_name) +/** + * Checks if the given name exists in the database. + * + * @param name The name to check. + * @param esc_name Escaped version of the name, optional for faster processing. + * @retval true if the character name already exists. + */ +bool char_name_exists(const char *name, const char *esc_name) +{ + char esc_name2[NAME_LENGTH * 2 + 1]; + + nullpo_retr(true, name); + + if (esc_name == NULL) { + SQL->EscapeStringLen(inter->sql_handle, esc_name2, name, strnlen(name, NAME_LENGTH)); + esc_name = esc_name2; + } + + if (name_ignoring_case) { + if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", char_db, esc_name)) { + Sql_ShowDebug(inter->sql_handle); + return true; + } + } else { + if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", char_db, esc_name)) { + Sql_ShowDebug(inter->sql_handle); + return true; + } + } + if (SQL->NumRows(inter->sql_handle) > 0) + return true; + + return false; +} + +/** + * Checks if the given name is valid for a new character. + * + * @param name The name to check. + * @param esc_name Escaped version of the name, optional for faster processing. + * @retval 0 if the name is valid. + * @retval -1 if the name already exists or is reserved + * @retval -2 if the name is too short or contains special characters. + * @retval -5 if the name contains forbidden characters. + */ +int char_check_char_name(const char *name, const char *esc_name) { int i; nullpo_retr(-2, name); - nullpo_retr(-2, esc_name); // check length of character name if (name[0] == '\0') @@ -1550,9 +1594,16 @@ int char_check_char_name(char * name, char * esc_name) **/ if( strlen( name ) < 4 ) return -2; - // check content of character name - if( remove_control_chars(name) ) - return -2; // control chars in name + + { + // check content of character name + char *name_copy = aStrdup(name); + if (remove_control_chars(name_copy)) { + aFree(name_copy); + return -2; // control chars in name + } + aFree(name_copy); + } // check for reserved names if( strcmpi(name, wisp_server_name) == 0 ) @@ -1571,19 +1622,9 @@ int char_check_char_name(char * name, char * esc_name) if( strchr(char_name_letters, name[i]) != NULL ) return -5; } - if( name_ignoring_case ) { - if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", char_db, esc_name) ) { - Sql_ShowDebug(inter->sql_handle); - return -2; - } - } else { - if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", char_db, esc_name) ) { - Sql_ShowDebug(inter->sql_handle); - return -2; - } - } - if( SQL->NumRows(inter->sql_handle) > 0 ) - return -1; // name already exists + + if (chr->name_exists(name, esc_name)) + return -1; return 0; } @@ -2550,14 +2591,14 @@ void char_parse_fromlogin_update_ip(int fd) void char_parse_fromlogin_accinfo2_failed(int fd) { - mapif->parse_accinfo2(false, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), + inter->accinfo2(false, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1, 0, 0); RFIFOSKIP(fd,18); } void char_parse_fromlogin_accinfo2_ok(int fd) { - mapif->parse_accinfo2(true, RFIFOL(fd,167), RFIFOL(fd,171), RFIFOL(fd,175), RFIFOL(fd,179), + inter->accinfo2(true, RFIFOL(fd,167), RFIFOL(fd,171), RFIFOL(fd,175), RFIFOL(fd,179), RFIFOP(fd,2), RFIFOP(fd,26), RFIFOP(fd,59), RFIFOP(fd,99), RFIFOP(fd,119), RFIFOP(fd,151), RFIFOP(fd,156), RFIFOL(fd,115), RFIFOL(fd,143), RFIFOL(fd,147)); RFIFOSKIP(fd,183); @@ -4727,7 +4768,6 @@ void char_parse_char_rename_char(int fd, struct char_session_data* sd) { int i, cid =RFIFOL(fd,2); char name[NAME_LENGTH]; - char esc_name[NAME_LENGTH*2+1]; safestrncpy(name, RFIFOP(fd,6), NAME_LENGTH); RFIFOSKIP(fd,30); @@ -4736,8 +4776,7 @@ void char_parse_char_rename_char(int fd, struct char_session_data* sd) return; normalize_name(name,TRIM_CHARS); - SQL->EscapeStringLen(inter->sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( !chr->check_char_name(name,esc_name) ) { + if (chr->check_char_name(name, NULL) == 0) { i = 1; safestrncpy(sd->new_name, name, NAME_LENGTH); } else { @@ -4752,7 +4791,6 @@ void char_parse_char_rename_char2(int fd, struct char_session_data* sd) { int i, aid = RFIFOL(fd,2), cid =RFIFOL(fd,6); char name[NAME_LENGTH]; - char esc_name[NAME_LENGTH*2+1]; safestrncpy(name, RFIFOP(fd,10), NAME_LENGTH); RFIFOSKIP(fd,34); @@ -4763,14 +4801,12 @@ void char_parse_char_rename_char2(int fd, struct char_session_data* sd) return; normalize_name(name,TRIM_CHARS); - SQL->EscapeStringLen(inter->sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( !chr->check_char_name(name,esc_name) ) - { + if (chr->check_char_name(name, NULL) == 0) { i = 1; safestrncpy(sd->new_name, name, NAME_LENGTH); - } - else + } else { i = 0; + } chr->allow_rename(fd, i); } @@ -6316,6 +6352,7 @@ void char_defaults(void) chr->mmo_char_sql_init = char_mmo_char_sql_init; chr->char_slotchange = char_char_slotchange; chr->rename_char_sql = char_rename_char_sql; + chr->name_exists = char_name_exists; chr->check_char_name = char_check_char_name; chr->make_new_char_sql = char_make_new_char_sql; chr->divorce_char_sql = char_divorce_char_sql; diff --git a/src/char/char.h b/src/char/char.h index a644f11ab..4d816583a 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -147,7 +147,8 @@ struct char_interface { int (*mmo_char_sql_init) (void); bool (*char_slotchange) (struct char_session_data *sd, int fd, unsigned short from, unsigned short to); int (*rename_char_sql) (struct char_session_data *sd, int char_id); - int (*check_char_name) (char * name, char * esc_name); + bool (*name_exists) (const char *name, const char *esc_name); + int (*check_char_name) (const char *name, const char *esc_name); int (*make_new_char_sql) (struct char_session_data *sd, const char *name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style, short starting_job, uint8 sex); int (*divorce_char_sql) (int partner_id1, int partner_id2); int (*count_users) (void); diff --git a/src/char/inter.c b/src/char/inter.c index cd363e8a2..1fdb61e70 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -81,11 +81,6 @@ int inter_recv_packet_length[] = { -1,10,-1, 6, 0, 20,10,11, -1,6 + NAME_LENGTH, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator], RoDEX packets }; -struct WisData { - int id, fd, count, len; - int64 tick; - unsigned char src[24], dst[24], msg[512]; -}; static struct DBMap *wis_db = NULL; // int wis_id -> struct WisData* static int wis_dellist[WISDELLIST_MAX], wis_delnum; @@ -446,15 +441,12 @@ void inter_msg_to_fd(int fd, int u_fd, int aid, char *msg, ...) } /* [Dekamaster/Nightroad] */ -void mapif_parse_accinfo(int fd) +void inter_accinfo(int u_fd, int aid, int castergroup, const char *query, int map_fd) { - int u_fd = RFIFOL(fd,2), aid = RFIFOL(fd,6), castergroup = RFIFOL(fd,10); - char query[NAME_LENGTH], query_esq[NAME_LENGTH*2+1]; + char query_esq[NAME_LENGTH*2+1]; int account_id; char *data; - safestrncpy(query, RFIFOP(fd,14), NAME_LENGTH); - SQL->EscapeString(inter->sql_handle, query_esq, query); account_id = atoi(query); @@ -464,10 +456,10 @@ void mapif_parse_accinfo(int fd) if ( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `%s` WHERE `name` LIKE '%s' LIMIT 10", char_db, query_esq) || SQL->NumRows(inter->sql_handle) == 0 ) { if( SQL->NumRows(inter->sql_handle) == 0 ) { - inter->msg_to_fd(fd, u_fd, aid, "No matches were found for your criteria, '%s'",query); + inter->msg_to_fd(map_fd, u_fd, aid, "No matches were found for your criteria, '%s'",query); } else { Sql_ShowDebug(inter->sql_handle); - inter->msg_to_fd(fd, u_fd, aid, "An error occurred, bother your admin about it."); + inter->msg_to_fd(map_fd, u_fd, aid, "An error occurred, bother your admin about it."); } SQL->FreeResult(inter->sql_handle); return; @@ -477,7 +469,7 @@ void mapif_parse_accinfo(int fd) SQL->GetData(inter->sql_handle, 0, &data, NULL); account_id = atoi(data); SQL->FreeResult(inter->sql_handle); } else {// more than one, listing... [Dekamaster/Nightroad] - inter->msg_to_fd(fd, u_fd, aid, "Your query returned the following %d results, please be more specific...",(int)SQL->NumRows(inter->sql_handle)); + inter->msg_to_fd(map_fd, u_fd, aid, "Your query returned the following %d results, please be more specific...",(int)SQL->NumRows(inter->sql_handle)); while ( SQL_SUCCESS == SQL->NextRow(inter->sql_handle) ) { int class; int base_level, job_level, online; @@ -490,7 +482,7 @@ void mapif_parse_accinfo(int fd) SQL->GetData(inter->sql_handle, 4, &data, NULL); job_level = atoi(data); SQL->GetData(inter->sql_handle, 5, &data, NULL); online = atoi(data); - inter->msg_to_fd(fd, u_fd, aid, "[AID: %d] %s | %s | Level: %d/%d | %s", account_id, name, inter->job_name(class), base_level, job_level, online?"Online":"Offline"); + inter->msg_to_fd(map_fd, u_fd, aid, "[AID: %d] %s | %s | Level: %d/%d | %s", account_id, name, inter->job_name(class), base_level, job_level, online?"Online":"Offline"); } SQL->FreeResult(inter->sql_handle); return; @@ -501,12 +493,23 @@ void mapif_parse_accinfo(int fd) /* it will only get here if we have a single match */ /* and we will send packet with account id to login server asking for account info */ if( account_id ) { - mapif->on_parse_accinfo(account_id, u_fd, aid, castergroup, fd); + mapif->on_parse_accinfo(account_id, u_fd, aid, castergroup, map_fd); } return; } -void mapif_parse_accinfo2(bool success, int map_fd, int u_fd, int u_aid, int account_id, const char *userid, const char *user_pass, + +void mapif_parse_accinfo(int fd) +{ + char query[NAME_LENGTH]; + int u_fd = RFIFOL(fd,2), aid = RFIFOL(fd,6), castergroup = RFIFOL(fd,10); + + safestrncpy(query, RFIFOP(fd,14), NAME_LENGTH); + + inter->accinfo(u_fd, aid, castergroup, query, fd); +} + +void inter_accinfo2(bool success, int map_fd, int u_fd, int u_aid, int account_id, const char *userid, const char *user_pass, const char *email, const char *last_ip, const char *lastlogin, const char *pin_code, const char *birthdate, int group_id, int logincount, int state) { @@ -1147,6 +1150,38 @@ int inter_check_ttl_wisdata(void) return 0; } +struct WisData *inter_add_wisdata(int fd, const unsigned char *src, const unsigned char *dst, const unsigned char *msg, int msg_len) +{ + static int wisid = 0; + struct WisData *wd; + + CREATE(wd, struct WisData, 1); + + // Whether the failure of previous wisp/page transmission (timeout) + inter->check_ttl_wisdata(); + + wd->id = ++wisid; + wd->fd = fd; + wd->len = msg_len; + memcpy(wd->src, src, NAME_LENGTH); + memcpy(wd->dst, dst, NAME_LENGTH); + memcpy(wd->msg, msg, wd->len); + wd->tick = timer->gettick(); + idb_put(wis_db, wd->id, wd); + + return wd; +} + +struct WisData *inter_get_wisdata(int id) +{ + return idb_get(wis_db, id); +} + +void inter_remove_wisdata(int id) +{ + idb_remove(wis_db, id); +} + //-------------------------------------------------------- // broadcast sending @@ -1162,7 +1197,6 @@ int mapif_parse_WisRequest(int fd) { struct WisData* wd; char name[NAME_LENGTH]; - char esc_name[NAME_LENGTH*2+1];// escaped name char* data; size_t len; @@ -1179,17 +1213,12 @@ int mapif_parse_WisRequest(int fd) safestrncpy(name, RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex] - SQL->EscapeStringLen(inter->sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, esc_name) ) - Sql_ShowDebug(inter->sql_handle); - // search if character exists before to ask all map-servers - if( SQL_SUCCESS != SQL->NextRow(inter->sql_handle) ) - { + if (!chr->name_exists(name, NULL)) { mapif->wis_response(fd, RFIFOP(fd, 4), 1); - } - else - {// Character exists. So, ask all map-servers + } else { + // Character exists. So, ask all map-servers + // to be sure of the correct name, rewrite it SQL->GetData(inter->sql_handle, 0, &data, &len); memset(name, 0, NAME_LENGTH); @@ -1197,23 +1226,8 @@ int mapif_parse_WisRequest(int fd) // if source is destination, don't ask other servers. if (strncmp(RFIFOP(fd,4), name, NAME_LENGTH) == 0) { mapif->wis_response(fd, RFIFOP(fd, 4), 1); - } - else - { - static int wisid = 0; - CREATE(wd, struct WisData, 1); - - // Whether the failure of previous wisp/page transmission (timeout) - inter->check_ttl_wisdata(); - - wd->id = ++wisid; - wd->fd = fd; - wd->len= RFIFOW(fd,2)-52; - memcpy(wd->src, RFIFOP(fd, 4), NAME_LENGTH); - memcpy(wd->dst, RFIFOP(fd,28), NAME_LENGTH); - memcpy(wd->msg, RFIFOP(fd,52), wd->len); - wd->tick = timer->gettick(); - idb_put(wis_db, wd->id, wd); + } else { + wd = inter->add_wisdata(fd, RFIFOP(fd, 4), RFIFOP(fd, 28), RFIFOP(fd, 52), RFIFOW(fd, 2) - 52); mapif->wis_message(wd); } } @@ -1231,13 +1245,13 @@ int mapif_parse_WisReply(int fd) id = RFIFOL(fd,2); flag = RFIFOB(fd,6); - wd = (struct WisData*)idb_get(wis_db, id); + wd = inter->get_wisdata(id); if (wd == NULL) return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server if ((--wd->count) <= 0 || flag != 1) { mapif->wis_end(wd, flag); // flag: 0: success to send whisper, 1: target character is not logged in?, 2: ignored by target - idb_remove(wis_db, id); + inter->remove_wisdata(id); } return 0; @@ -1461,4 +1475,9 @@ void inter_defaults(void) inter->final = inter_final; inter->config_read_log = inter_config_read_log; inter->config_read_connection = inter_config_read_connection; + inter->accinfo = inter_accinfo; + inter->accinfo2 = inter_accinfo2; + inter->add_wisdata = inter_add_wisdata; + inter->get_wisdata = inter_get_wisdata; + inter->remove_wisdata = inter_remove_wisdata; } diff --git a/src/char/inter.h b/src/char/inter.h index 7f901927c..94ee3ab60 100644 --- a/src/char/inter.h +++ b/src/char/inter.h @@ -30,6 +30,12 @@ struct Sql; // common/sql.h struct config_t; // common/conf.h +struct WisData { + int id, fd, count, len; + int64 tick; + unsigned char src[24], dst[24], msg[512]; +}; + /** * inter interface **/ @@ -56,6 +62,13 @@ struct inter_interface { bool (*config_read) (const char *filename, bool imported); bool (*config_read_log) (const char *filename, const struct config_t *config, bool imported); bool (*config_read_connection) (const char *filename, const struct config_t *config, bool imported); + void (*accinfo) (int u_fd, int aid, int castergroup, const char *query, int map_fd); + void (*accinfo2) (bool success, int map_fd, int u_fd, int u_aid, int account_id, const char *userid, const char *user_pass, + const char *email, const char *last_ip, const char *lastlogin, const char *pin_code, const char *birthdate, + int group_id, int logincount, int state); + struct WisData *(*add_wisdata) (int fd, const unsigned char *src, const unsigned char *dst, const unsigned char *msg, int msg_len); + struct WisData *(*get_wisdata) (int id); + void (*remove_wisdata) (int id); }; #ifdef HERCULES_CORE diff --git a/src/char/mapif.c b/src/char/mapif.c index 1dfa08b82..269bfc397 100644 --- a/src/char/mapif.c +++ b/src/char/mapif.c @@ -2013,8 +2013,6 @@ void mapif_parse_ItemBoundRetrieve(int fd) } void mapif_parse_accinfo(int fd); -void mapif_parse_accinfo2(bool success, int map_fd, int u_fd, int u_aid, int account_id, const char *userid, const char *user_pass, - const char *email, const char *last_ip, const char *lastlogin, const char *pin_code, const char *birthdate, int group_id, int logincount, int state); int mapif_broadcast(const unsigned char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd); int mapif_wis_message(struct WisData *wd); void mapif_wis_response(int fd, const unsigned char *src, int flag); @@ -2208,7 +2206,6 @@ void mapif_defaults(void) { mapif->itembound_ack = mapif_itembound_ack; mapif->parse_ItemBoundRetrieve = mapif_parse_ItemBoundRetrieve; mapif->parse_accinfo = mapif_parse_accinfo; - mapif->parse_accinfo2 = mapif_parse_accinfo2; mapif->broadcast = mapif_broadcast; mapif->wis_message = mapif_wis_message; mapif->wis_response = mapif_wis_response; diff --git a/src/char/mapif.h b/src/char/mapif.h index c5dd86f8f..d67ce1c79 100644 --- a/src/char/mapif.h +++ b/src/char/mapif.h @@ -174,8 +174,6 @@ struct mapif_interface { int (*itembound_ack) (int fd, int aid, int guild_id); void (*parse_ItemBoundRetrieve) (int fd); void (*parse_accinfo) (int fd); - void (*parse_accinfo2) (bool success, int map_fd, int u_fd, int u_aid, int account_id, const char *userid, const char *user_pass, - const char *email, const char *last_ip, const char *lastlogin, const char *pin_code, const char *birthdate, int group_id, int logincount, int state); int (*broadcast) (const unsigned char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd); int (*wis_message) (struct WisData *wd); void (*wis_response) (int fd, const unsigned char *src, int flag); |