From dbbfda0e96037da4f208ff8f00d181a5294484ae Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Sat, 22 Jun 2013 22:30:13 -0700 Subject: add new stuff stuff (with tests!), poison memcmp and strncpy --- src/char/char.cpp | 244 ++++++++-------- src/char/int_party.cpp | 124 ++++++--- src/char/int_storage.cpp | 2 +- src/char/inter.cpp | 4 +- src/common/dumb_ptr.hpp | 3 + src/common/md5calc.cpp | 3 +- src/common/mmo.hpp | 9 + src/common/socket.cpp | 2 +- src/common/socket.hpp | 16 +- src/common/strings.hpp | 537 ++++++++++++++++++++++++++++++++++++ src/common/strings_test.cpp | 99 +++++++ src/common/utils.hpp | 14 +- src/common/utils2.hpp | 21 ++ src/ladmin/ladmin.cpp | 236 ++++++++++------ src/login/login.cpp | 164 ++++++----- src/map/atcommand.cpp | 43 ++- src/map/chrif.cpp | 41 ++- src/map/clif.cpp | 93 +++---- src/map/clif.hpp | 5 +- src/map/intif.cpp | 52 ++-- src/map/magic-interpreter-base.cpp | 2 +- src/map/magic-interpreter-lexer.lpp | 14 +- src/map/map.hpp | 2 +- src/map/mob.cpp | 3 - src/map/npc.cpp | 9 +- src/map/party.cpp | 3 +- src/map/pc.cpp | 25 +- src/map/script.cpp | 4 +- src/map/tmw.cpp | 2 +- src/poison.hpp | 2 + src/tests/main.cpp | 7 + 31 files changed, 1310 insertions(+), 475 deletions(-) create mode 100644 src/common/strings.hpp create mode 100644 src/common/strings_test.cpp create mode 100644 src/tests/main.cpp (limited to 'src') diff --git a/src/char/char.cpp b/src/char/char.cpp index 02d89af..bb0550b 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -595,15 +595,13 @@ void remove_prefix_blanks(char *name) // Function to create a new character //----------------------------------- static -mmo_charstatus *make_new_char(int fd, const uint8_t *dat) +mmo_charstatus *make_new_char(int fd, char *name, const uint8_t (&stats)[6], uint8_t slot, uint16_t hair_color, uint16_t hair_style) { // ugh - char *cdat = reinterpret_cast(const_cast(dat)); char_session_data *sd = static_cast(session[fd]->session_data.get()); // remove control characters from the name - cdat[23] = '\0'; - if (remove_control_chars(cdat)) + if (remove_control_chars(name)) { CHAR_LOG("Make new char error (control char received in the name): (connection #%d, account: %d).\n", fd, sd->account_id); @@ -611,14 +609,14 @@ mmo_charstatus *make_new_char(int fd, const uint8_t *dat) } // Eliminate whitespace - remove_trailing_blanks(cdat); - remove_prefix_blanks(cdat); + remove_trailing_blanks(name); + remove_prefix_blanks(name); // check lenght of character name - if (strlen(cdat) < 4) + if (strlen(name) < 4) { CHAR_LOG("Make new char error (character name too small): (connection #%d, account: %d, name: '%s').\n", - fd, sd->account_id, cdat); + fd, sd->account_id, name); return nullptr; } @@ -626,86 +624,86 @@ mmo_charstatus *make_new_char(int fd, const uint8_t *dat) if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised - for (int i = 0; cdat[i]; i++) - if (strchr(char_name_letters, cdat[i]) == NULL) + for (int i = 0; name[i]; i++) + if (strchr(char_name_letters, name[i]) == NULL) { CHAR_LOG("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n", - fd, sd->account_id, cdat, cdat[i]); + fd, sd->account_id, name, name[i]); return nullptr; } } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden - for (int i = 0; cdat[i]; i++) - if (strchr(char_name_letters, cdat[i]) != NULL) + for (int i = 0; name[i]; i++) + if (strchr(char_name_letters, name[i]) != NULL) { CHAR_LOG("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n", - fd, sd->account_id, cdat, cdat[i]); + fd, sd->account_id, name, name[i]); return nullptr; } } // else, all letters/symbols are authorised (except control char removed before) // this is why it needs to be unsigned - if (dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29] != 5 * 6 || // stats - dat[30] >= 9 || // slots (dat[30] can not be negativ) - dat[33] >= 20 || // hair style - dat[31] >= 12) - { // hair color (dat[31] can not be negativ) + if (stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5] != 5 * 6 || // stats + slot >= 9 || + hair_style >= 20 || + hair_color >= 12) + { CHAR_LOG("Make new char error (invalid values): (connection #%d, account: %d) slot %d, name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d\n", - fd, sd->account_id, dat[30], dat, dat[24], dat[25], - dat[26], dat[27], dat[28], dat[29], - dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29], - dat[33], dat[31]); + fd, sd->account_id, slot, name, + stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], + stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], + hair_style, hair_color); return nullptr; } // check individual stat value - for (int i = 24; i <= 29; i++) + for (int i = 0; i < 6; i++) { - if (dat[i] < 1 || dat[i] > 9) + if (stats[i] < 1 || stats[i] > 9) { CHAR_LOG("Make new char error (invalid stat value: not between 1 to 9): (connection #%d, account: %d) slot %d, name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d\n", - fd, sd->account_id, dat[30], dat, dat[24], dat[25], - dat[26], dat[27], dat[28], dat[29], - dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29], - dat[33], dat[31]); + fd, sd->account_id, slot, name, + stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], + stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], + hair_style, hair_color); return nullptr; } } for (const mmo_charstatus& cd : char_data) { - if ((name_ignoring_case != 0 && strcmp(cd.name, cdat) == 0) + if ((name_ignoring_case != 0 && strcmp(cd.name, name) == 0) || (name_ignoring_case == 0 - && strcasecmp(cd.name, cdat) == 0)) + && strcasecmp(cd.name, name) == 0)) { CHAR_LOG("Make new char error (name already exists): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n", - fd, sd->account_id, dat[30], cdat, cd.name, - dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], - dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29], - dat[33], dat[31]); + fd, sd->account_id, slot, name, cd.name, + stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], + stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], + hair_style, hair_color); return nullptr; } if (cd.account_id == sd->account_id - && cd.char_num == dat[30]) + && cd.char_num == slot) { CHAR_LOG("Make new char error (slot already used): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n", - fd, sd->account_id, dat[30], cdat, cd.name, - dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], - dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29], - dat[33], dat[31]); + fd, sd->account_id, slot, name, cd.name, + stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], + stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], + hair_style, hair_color); return nullptr; } } - if (strcmp(wisp_server_name, cdat) == 0) + if (strcmp(wisp_server_name, name) == 0) { CHAR_LOG("Make new char error (name used is wisp name for server): (connection #%d, account: %d) slot %d, name: %s (actual name whisper server: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n", - fd, sd->account_id, dat[30], cdat, wisp_server_name, - dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], - dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29], - dat[33], dat[31]); + fd, sd->account_id, slot, name, wisp_server_name, + stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], + stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], + hair_style, hair_color); return nullptr; } @@ -715,29 +713,29 @@ mmo_charstatus *make_new_char(int fd, const uint8_t *dat) sin_addr[3]); CHAR_LOG("Creation of New Character: (connection #%d, account: %d) slot %d, character Name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d. [%s]\n", - fd, sd->account_id, dat[30], cdat, dat[24], dat[25], dat[26], - dat[27], dat[28], dat[29], - dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29], dat[33], - dat[31], ip); + fd, sd->account_id, slot, name, + stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], + stats[0] + stats[1] + stats[2] + stats[3] + stats[4] + stats[5], + hair_style, hair_color, ip); mmo_charstatus cd {}; cd.char_id = char_id_count++; cd.account_id = sd->account_id; - cd.char_num = dat[30]; - strcpy(cd.name, cdat); + cd.char_num = slot; + strcpy(cd.name, name); cd.species = 0; cd.base_level = 1; cd.job_level = 1; cd.base_exp = 0; cd.job_exp = 0; cd.zeny = start_zeny; - cd.attrs[ATTR::STR] = dat[24]; - cd.attrs[ATTR::AGI] = dat[25]; - cd.attrs[ATTR::VIT] = dat[26]; - cd.attrs[ATTR::INT] = dat[27]; - cd.attrs[ATTR::DEX] = dat[28]; - cd.attrs[ATTR::LUK] = dat[29]; + cd.attrs[ATTR::STR] = stats[0]; + cd.attrs[ATTR::AGI] = stats[1]; + cd.attrs[ATTR::VIT] = stats[2]; + cd.attrs[ATTR::INT] = stats[3]; + cd.attrs[ATTR::DEX] = stats[4]; + cd.attrs[ATTR::LUK] = stats[5]; cd.max_hp = 40 * (100 + cd.attrs[ATTR::VIT]) / 100; cd.max_sp = 11 * (100 + cd.attrs[ATTR::INT]) / 100; cd.hp = cd.max_hp; @@ -749,21 +747,11 @@ mmo_charstatus *make_new_char(int fd, const uint8_t *dat) cd.manner = 0; cd.party_id = 0; //cd.guild_id = 0; - cd.hair = dat[33]; - cd.hair_color = dat[31]; + cd.hair = hair_style; + cd.hair_color = hair_color; cd.clothes_color = 0; - // TODO: remove this - it's not used - cd.inventory[0].nameid = start_weapon; // Knife - cd.inventory[0].amount = 1; - cd.inventory[0].equip = EPOS::WEAPON; - cd.inventory[0].identify = 1; - cd.inventory[0].broken = 0; - cd.inventory[1].nameid = start_armor; // Cotton Shirt - cd.inventory[1].amount = 1; - cd.inventory[1].equip = EPOS::MISC1; - cd.inventory[1].identify = 1; - cd.inventory[1].broken = 0; - cd.weapon = ItemLook::BLADE; + // removed initial armor/weapon - unused and problematic + cd.weapon = ItemLook::NONE; cd.shield = 0; cd.head_top = 0; cd.head_mid = 0; @@ -1018,11 +1006,11 @@ int set_account_reg2(int acc, int num, struct global_reg *reg) { if (cd.account_id == acc) { - for (int i = 0; i < num; ++i) - cd.account_reg2[i] = reg[i]; + for (int i = 0; i < num; ++i) + cd.account_reg2[i] = reg[i]; cd.account_reg2_num = num; - for (int i = num; i < ACCOUNT_REG2_NUM; ++i) - cd.account_reg2[i] = global_reg{}; + for (int i = num; i < ACCOUNT_REG2_NUM; ++i) + cd.account_reg2[i] = global_reg{}; c++; } } @@ -1237,7 +1225,7 @@ void parse_tologin(int fd) { if (sd->account_id == RFIFOL(fd, 2)) { - RFIFO_STRING(fd, 6, sd->email, 40); + RFIFO_STRING(fd, 6, sd->email, 40); if (e_mail_check(sd->email) == 0) strzcpy(sd->email, "a@a.com", 40); // default e-mail sd->connect_until_time = static_cast(RFIFOL(fd, 46)); @@ -1319,9 +1307,9 @@ void parse_tologin(int fd) CHAR_LOG("'ladmin': Receiving a message for broadcast, but no map-server is online.\n"); else { - size_t len = RFIFOL(fd, 4); + size_t len = RFIFOL(fd, 4); char message[len]; - RFIFO_STRING(fd, 8, message, len); + RFIFO_STRING(fd, 8, message, len); remove_control_chars(message); // remove all first spaces char *p = message; @@ -1339,10 +1327,10 @@ void parse_tologin(int fd) message_ptr); } // send broadcast to all map-servers - uint8_t buf[4 + len]; + uint8_t buf[4 + len]; WBUFW(buf, 0) = 0x3800; WBUFW(buf, 2) = 4 + sizeof(message); - WBUF_STRING(buf, 4, message, sizeof(message)); + WBUF_STRING(buf, 4, message, sizeof(message)); mapif_sendall(buf, WBUFW(buf, 2)); } } @@ -1367,14 +1355,14 @@ void parse_tologin(int fd) } set_account_reg2(acc, j, reg); - size_t len = RFIFOW(fd, 2); + size_t len = RFIFOW(fd, 2); uint8_t buf[len]; RFIFO_BUF_CLONE(fd, buf, len); WBUFW(buf, 0) = 0x2b11; mapif_sendall(buf, len); // PRINTF("char: save_account_reg_reply\n"); } - RFIFOSKIP(fd, RFIFOW(fd, 2)); + RFIFOSKIP(fd, RFIFOW(fd, 2)); break; case 0x7924: @@ -1487,7 +1475,7 @@ void parse_tologin(int fd) if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd, 2)) return; { - size_t len = RFIFOW(fd, 2); + size_t len = RFIFOW(fd, 2); uint8_t buf[len]; gm_accounts.clear(); gm_accounts.reserve((len - 4) / 5); @@ -1501,7 +1489,7 @@ void parse_tologin(int fd) gm_accounts.size()); create_online_files(); // update online players files (perhaps some online players change of GM level) // send new gm acccounts level to map-servers - RFIFO_BUF_CLONE(fd, buf, len); + RFIFO_BUF_CLONE(fd, buf, len); WBUFW(buf, 0) = 0x2b15; mapif_sendall(buf, len); } @@ -1615,8 +1603,8 @@ void parse_frommap(int fd) if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd, 2)) return; { - for (char (&foo)[16] : server[id].maps) - strzcpy(foo, "", 16); + for (char (&foo)[16] : server[id].maps) + strzcpy(foo, "", 16); int j = 0; for (int i = 4; i < RFIFOW(fd, 2); i += 16) { @@ -1652,9 +1640,9 @@ void parse_frommap(int fd) WBUFW(buf, 2) = j * 16 + 10; WBUFL(buf, 4) = server[id].ip; WBUFW(buf, 8) = server[id].port; - // server[id].maps[i] = RFIFO_STRING(fd, 4 + i * 16) - for (int i = 0; i < j; ++i) - WBUF_STRING(buf, 10, server[id].maps[i], 16); + // server[id].maps[i] = RFIFO_STRING(fd, 4 + i * 16) + for (int i = 0; i < j; ++i) + WBUF_STRING(buf, 10, server[id].maps[i], 16); mapif_sendallwos(fd, buf, WBUFW(buf, 2)); } // Transmitting the maps of the other map-servers to the new map-server @@ -1717,7 +1705,7 @@ void parse_frommap(int fd) FPRINTF(stderr, "From queue index %zd: recalling packet version %d\n", (&afi - &auth_fifo.front()), afi.packet_tmw_version); - WFIFO_STRUCT(fd, 18, *cd); + WFIFO_STRUCT(fd, 18, *cd); WFIFOSET(fd, WFIFOW(fd, 2)); //PRINTF("auth_fifo search success (auth #%d, account %d, character: %d).\n", i, RFIFOL(fd,2), RFIFOL(fd,6)); goto x2afc_out; @@ -1776,7 +1764,7 @@ void parse_frommap(int fd) if (cd.account_id == RFIFOL(fd, 4) && cd.char_id == RFIFOL(fd, 8)) { - RFIFO_STRUCT(fd, 12, cd); + RFIFO_STRUCT(fd, 12, cd); break; } } @@ -1811,8 +1799,8 @@ void parse_frommap(int fd) if (auth_fifo_iter == auth_fifo.end()) auth_fifo_iter = auth_fifo.begin(); - RFIFO_WFIFO_CLONE(fd, fd, 44); - // overwrite + RFIFO_WFIFO_CLONE(fd, fd, 44); + // overwrite WFIFOW(fd, 0) = 0x2b06; auth_fifo_iter->account_id = RFIFOL(fd, 2); auth_fifo_iter->char_id = RFIFOL(fd, 14); @@ -1842,18 +1830,18 @@ void parse_frommap(int fd) if (RFIFOREST(fd) < 6) return; { - const char (*name)[24] = &unknown_char_name; + const char *name = unknown_char_name; for (const mmo_charstatus& cd : char_data) { if (cd.char_id == RFIFOL(fd, 2)) { - name = &cd.name; + name = cd.name; break; } } WFIFOW(fd, 0) = 0x2b09; WFIFOL(fd, 2) = RFIFOL(fd, 2); - WFIFO_STRING(fd, 6, *name, 24); + WFIFO_STRING(fd, 6, name, 24); WFIFOSET(fd, 30); } RFIFOSKIP(fd, 6); @@ -1863,10 +1851,9 @@ void parse_frommap(int fd) case 0x2b0a: if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd, 2)) return; -// PRINTF("parse_frommap: change gm -> login, account: %d, pass: '%s'.\n", RFIFOL(fd,4), RFIFOP(fd,8)); if (login_fd > 0) { // don't send request if no login-server - size_t len = RFIFOW(fd, 2); + size_t len = RFIFOW(fd, 2); RFIFO_WFIFO_CLONE(fd, login_fd, len); WFIFOW(login_fd, 0) = 0x2720; WFIFOSET(login_fd, len); @@ -1901,7 +1888,7 @@ void parse_frommap(int fd) { char character_name[24]; int acc = RFIFOL(fd, 2); // account_id of who ask (-1 if nobody) - strzcpy(character_name, static_cast(RFIFOP(fd, 6)), 24); + RFIFO_STRING(fd, 6, character_name, 24); // prepare answer WFIFOW(fd, 0) = 0x2b0f; // answer WFIFOL(fd, 2) = acc; // who want do operation @@ -2045,17 +2032,13 @@ void parse_frommap(int fd) set_account_reg2(acc, j, reg); // loginサーバーへ送る if (login_fd > 0) - { // don't send request if no login-server - RFIFO_WFIFO_CLONE(fd, login_fd, RFIFOW(fd, 2)); + { + // don't send request if no login-server + RFIFO_WFIFO_CLONE(fd, login_fd, RFIFOW(fd, 2)); WFIFOW(login_fd, 0) = 0x2728; WFIFOSET(login_fd, WFIFOW(login_fd, 2)); } - // ワールドへの同垢ログインがなければmapサーバーに送る必要はない - //memcpy(buf, RFIFOP(fd,0), RFIFOW(fd,2)); - //WBUFW(buf,0) = 0x2b11; - //mapif_sendall(buf, WBUFW(buf,2)); RFIFOSKIP(fd, RFIFOW(fd, 2)); -// PRINTF("char: save_account_reg (from map)\n"); break; } @@ -2259,12 +2242,12 @@ void parse_char(int fd) { WFIFOW(login_fd, 0) = 0x2740; WFIFOL(login_fd, 2) = sd->account_id; - char old_pass[24]; - RFIFO_STRING(fd, 2, old_pass, 24); - WFIFO_STRING(login_fd, 6, old_pass, 24); - char new_pass[24]; - RFIFO_STRING(fd, 26, new_pass, 24); - WFIFO_STRING(login_fd, 30, new_pass, 24); + char old_pass[24]; + RFIFO_STRING(fd, 2, old_pass, 24); + WFIFO_STRING(login_fd, 6, old_pass, 24); + char new_pass[24]; + RFIFO_STRING(fd, 26, new_pass, 24); + WFIFO_STRING(login_fd, 30, new_pass, 24); WFIFOSET(login_fd, 54); } RFIFOSKIP(fd, 50); @@ -2370,7 +2353,15 @@ void parse_char(int fd) if (!sd || RFIFOREST(fd) < 37) return; { - const struct mmo_charstatus *cd = make_new_char(fd, static_cast(RFIFOP(fd, 2))); + char name[24]; + RFIFO_STRING(fd, 2, name, 24); + uint8_t stats[6]; + for (int i = 0; i < 6; ++i) + stats[i] = RFIFOB(fd, 26 + i); + uint8_t slot = RFIFOB(fd, 32); + uint16_t hair_color = RFIFOW(fd, 33); + uint16_t hair_style = RFIFOW(fd, 35); + const struct mmo_charstatus *cd = make_new_char(fd, name, stats, slot, hair_color, hair_style); if (!cd) { WFIFOW(fd, 0) = 0x6e; @@ -2381,7 +2372,7 @@ void parse_char(int fd) } WFIFOW(fd, 0) = 0x6d; - WFIFO_ZERO(fd, 2, 106); + WFIFO_ZERO(fd, 2, 106); WFIFOL(fd, 2) = cd->char_id; WFIFOL(fd, 2 + 4) = cd->base_exp; @@ -2409,7 +2400,7 @@ void parse_char(int fd) WFIFOW(fd, 2 + 68) = cd->head_mid; WFIFOW(fd, 2 + 70) = cd->hair_color; - WFIFO_STRING(fd, 2 + 74, cd->name, 24); + WFIFO_STRING(fd, 2 + 74, cd->name, 24); WFIFOB(fd, 2 + 98) = min(cd->attrs[ATTR::STR], 255); WFIFOB(fd, 2 + 99) = min(cd->attrs[ATTR::AGI], 255); @@ -2427,7 +2418,7 @@ void parse_char(int fd) case 0x68: // delete char //Yor's Fix if (!sd || RFIFOREST(fd) < 46) return; - RFIFO_STRING(fd, 6, email, 40); + RFIFO_STRING(fd, 6, email, 40); if (e_mail_check(email) == 0) strzcpy(email, "a@a.com", 40); // default e-mail @@ -2480,8 +2471,12 @@ void parse_char(int fd) if (server_fd[i] < 0) break; } - if (i == MAX_MAP_SERVERS || strcmp(static_cast(RFIFOP(fd, 2)), userid) - || strcmp(static_cast(RFIFOP(fd, 26)), passwd)) + char userid_[24]; + RFIFO_STRING(fd, 2, userid_, 24); + char passwd_[24]; + RFIFO_STRING(fd, 26, passwd_, 24); + if (i == MAX_MAP_SERVERS || strcmp(userid_, userid) + || strcmp(passwd_, passwd)) { WFIFOB(fd, 2) = 3; WFIFOSET(fd, 3); @@ -2495,11 +2490,12 @@ void parse_char(int fd) server_fd[i] = fd; if (anti_freeze_enable) server_freezeflag[i] = 5; // Map anti-freeze system. Counter. 5 ok, 4...0 freezed + // ignore RFIFOL(fd, 50) server[i].ip = RFIFOL(fd, 54); server[i].port = RFIFOW(fd, 58); server[i].users = 0; - for (char (&mapi)[16] : server[i].maps) - strzcpy(mapi, "", 16); + for (char (&mapi)[16] : server[i].maps) + strzcpy(mapi, "", 16); WFIFOSET(fd, 3); RFIFOSKIP(fd, 60); realloc_fifo(fd, FIFOSIZE_SERVERLINK, @@ -2561,7 +2557,7 @@ int mapif_sendall(const uint8_t *buf, unsigned int len) int fd; if ((fd = server_fd[i]) >= 0) { - WFIFO_BUF_CLONE(fd, buf, len); + WFIFO_BUF_CLONE(fd, buf, len); WFIFOSET(fd, len); c++; } @@ -2580,7 +2576,7 @@ int mapif_sendallwos(int sfd, const uint8_t *buf, unsigned int len) int fd; if ((fd = server_fd[i]) >= 0 && fd != sfd) { - WFIFO_BUF_CLONE(fd, buf, len); + WFIFO_BUF_CLONE(fd, buf, len); WFIFOSET(fd, len); c++; } @@ -2599,7 +2595,7 @@ int mapif_send(int fd, const uint8_t *buf, unsigned int len) { if (fd == server_fd[i]) { - WFIFO_BUF_CLONE(fd, buf, len); + WFIFO_BUF_CLONE(fd, buf, len); WFIFOSET(fd, len); return 1; } @@ -2638,7 +2634,7 @@ void check_connect_login_server(TimerData *, tick_t) session[login_fd]->func_parse = parse_tologin; realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); WFIFOW(login_fd, 0) = 0x2710; - WFIFO_ZERO(login_fd, 2, 24); + WFIFO_ZERO(login_fd, 2, 24); WFIFO_STRING(login_fd, 2, userid, 24); WFIFO_STRING(login_fd, 26, passwd, 24); WFIFOL(login_fd, 50) = 0; diff --git a/src/char/int_party.cpp b/src/char/int_party.cpp index 688c05a..38edb9b 100644 --- a/src/char/int_party.cpp +++ b/src/char/int_party.cpp @@ -382,8 +382,9 @@ void mapif_party_broken(int party_id, int flag) // パーティ内発言 static -void mapif_party_message(int party_id, int account_id, const char *mes, int len) +void mapif_party_message(int party_id, int account_id, const char *mes) { + size_t len = strlen(mes); unsigned char buf[len + 12]; WBUFW(buf, 0) = 0x3827; @@ -575,10 +576,9 @@ void mapif_parse_BreakParty(int fd, int party_id) // パーティメッセージ送信 static -void mapif_parse_PartyMessage(int, int party_id, int account_id, const char *mes, - int len) +void mapif_parse_PartyMessage(int, int party_id, int account_id, const char *mes) { - mapif_party_message(party_id, account_id, mes, len); + mapif_party_message(party_id, account_id, mes); } // パーティチェック要求 @@ -598,60 +598,114 @@ int inter_party_parse_frommap(int fd) switch (RFIFOW(fd, 0)) { case 0x3020: + { + int account = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + char nick[24]; + RFIFO_STRING(fd, 30, nick, 24); + char map[16]; + RFIFO_STRING(fd, 54, map, 16); + uint16_t lv = RFIFOW(fd, 70); mapif_parse_CreateParty(fd, - RFIFOL(fd, 2), - static_cast(RFIFOP(fd, 6)), - static_cast(RFIFOP(fd, 30)), - static_cast(RFIFOP(fd, 54)), - RFIFOW(fd, 70)); + account, + name, + nick, + map, + lv); + } break; case 0x3021: - mapif_parse_PartyInfo(fd, RFIFOL(fd, 2)); + { + int party_id = RFIFOL(fd, 2); + mapif_parse_PartyInfo(fd, party_id); + } break; case 0x3022: + { + int party_id = RFIFOL(fd, 2); + int account_id = RFIFOL(fd, 6); + char nick[24]; + RFIFO_STRING(fd, 10, nick, 24); + char map[16]; + RFIFO_STRING(fd, 34, map, 16); + uint16_t lv = RFIFOW(fd, 50); mapif_parse_PartyAddMember(fd, - RFIFOL(fd, 2), - RFIFOL(fd, 6), - static_cast(RFIFOP(fd, 10)), - static_cast(RFIFOP(fd, 34)), - RFIFOW(fd, 50)); + party_id, + account_id, + nick, + map, + lv); + } break; case 0x3023: + { + int party_id = RFIFOL(fd, 2); + int account_id = RFIFOL(fd, 6); + uint16_t exp = RFIFOW(fd, 10); + uint16_t item = RFIFOW(fd, 12); mapif_parse_PartyChangeOption(fd, - RFIFOL(fd, 2), - RFIFOL(fd, 6), - RFIFOW(fd, 10), - RFIFOW(fd, 12)); + party_id, + account_id, + exp, + item); + } break; case 0x3024: + { + int party_id = RFIFOL(fd, 2); + int account_id = RFIFOL(fd, 6); mapif_parse_PartyLeave(fd, - RFIFOL(fd, 2), - RFIFOL(fd, 6)); + party_id, + account_id); + } break; case 0x3025: + { + int party_id = RFIFOL(fd, 2); + int account_id = RFIFOL(fd, 6); + char map[16]; + RFIFO_STRING(fd, 10, map, 16); + uint8_t online = RFIFOB(fd, 26); + uint16_t lv = RFIFOW(fd, 27); mapif_parse_PartyChangeMap(fd, - RFIFOL(fd, 2), - RFIFOL(fd, 6), - static_cast(RFIFOP(fd, 10)), - RFIFOB(fd, 26), - RFIFOW(fd, 27)); + party_id, + account_id, + map, + online, + lv); + } break; case 0x3026: - mapif_parse_BreakParty(fd, - RFIFOL(fd, 2)); + { + int party_id = RFIFOL(fd, 2); + mapif_parse_BreakParty(fd, party_id); + } break; case 0x3027: + { + size_t len = RFIFOW(fd, 2) - 12; + int party_id = RFIFOL(fd, 4); + int account_id = RFIFOL(fd, 8); + char mes[len]; + RFIFO_STRING(fd, 12, mes, len); mapif_parse_PartyMessage(fd, - RFIFOL(fd, 4), - RFIFOL(fd, 8), - static_cast(RFIFOP(fd, 12)), - RFIFOW(fd, 2) - 12); + party_id, + account_id, + mes); + } break; case 0x3028: + { + int party_id = RFIFOL(fd, 2); + int account_id = RFIFOL(fd, 6); + char nick[24]; + RFIFO_STRING(fd, 10, nick, 24); mapif_parse_PartyCheck(fd, - RFIFOL(fd, 2), - RFIFOL(fd, 6), - static_cast(RFIFOP(fd, 10))); + party_id, + account_id, + nick); + } break; default: return 0; diff --git a/src/char/int_storage.cpp b/src/char/int_storage.cpp index 4067490..09ce9d4 100644 --- a/src/char/int_storage.cpp +++ b/src/char/int_storage.cpp @@ -208,7 +208,7 @@ void mapif_parse_SaveStorage(int fd) else { s = account2storage(account_id); - RFIFO_STRUCT(fd, 8, *s); + RFIFO_STRUCT(fd, 8, *s); mapif_save_storage_ack(fd, account_id); } } diff --git a/src/char/inter.cpp b/src/char/inter.cpp index fab50d2..68d81e8 100644 --- a/src/char/inter.cpp +++ b/src/char/inter.cpp @@ -421,8 +421,8 @@ void mapif_parse_WisRequest(int fd) size_t len = RFIFOW(fd, 2) - 52; RFIFO_STRING(fd, 4, wd.src, 24); RFIFO_STRING(fd, 28, wd.dst, 24); - char tmpbuf[len]; - RFIFO_STRING(fd, 52, tmpbuf, len); + char tmpbuf[len]; + RFIFO_STRING(fd, 52, tmpbuf, len); wd.msg = std::string(tmpbuf); wd.tick = gettick(); wis_db.insert(wd.id, wd); diff --git a/src/common/dumb_ptr.hpp b/src/common/dumb_ptr.hpp index e10ca3a..ab98b57 100644 --- a/src/common/dumb_ptr.hpp +++ b/src/common/dumb_ptr.hpp @@ -26,6 +26,7 @@ #include #include "const_array.hpp" +#include "strings.hpp" // unmanaged new/delete-able pointer // should be replaced by std::unique_ptr @@ -261,6 +262,8 @@ struct dumb_string return !impl; } + operator ZString() { return ZString(ZString::really_construct_from_a_pointer, c_str()); } + #if 0 friend bool operator == (dumb_string l, dumb_string r) { diff --git a/src/common/md5calc.cpp b/src/common/md5calc.cpp index f773c9f..582c152 100644 --- a/src/common/md5calc.cpp +++ b/src/common/md5calc.cpp @@ -317,7 +317,8 @@ const char *make_salt(void) bool pass_ok(const char *password, const char *crypted) { char buf[40]; - strncpy(buf, crypted, 40); + strzcpy(buf, crypted, 40); + // crypted is like !salt$hash char *salt = buf + 1; *strchr(salt, '$') = '\0'; diff --git a/src/common/mmo.hpp b/src/common/mmo.hpp index 14b8bac..450aa61 100644 --- a/src/common/mmo.hpp +++ b/src/common/mmo.hpp @@ -92,6 +92,15 @@ struct skill_value { unsigned short lv; SkillFlags flags; + + friend bool operator == (const skill_value& l, const skill_value& r) + { + return l.lv == r.lv && l.flags == r.flags; + } + friend bool operator != (const skill_value& l, const skill_value& r) + { + return !(l == r); + } }; struct global_reg diff --git a/src/common/socket.cpp b/src/common/socket.cpp index c509825..214fb5a 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -38,7 +38,7 @@ std::array, FD_SETSIZE> session; inline void RFIFOFLUSH(int fd) { - really_memmove(&session[fd]->rdata[0], static_cast(RFIFOP(fd, 0)), RFIFOREST(fd)); + really_memmove(&session[fd]->rdata[0], &session[fd]->rdata[session[fd]->rdata_pos], RFIFOREST(fd)); session[fd]->rdata_size = RFIFOREST(fd); session[fd]->rdata_pos = 0; } diff --git a/src/common/socket.hpp b/src/common/socket.hpp index ef7b193..2366373 100644 --- a/src/common/socket.hpp +++ b/src/common/socket.hpp @@ -103,12 +103,18 @@ FILE *fopen_(const char *path, const char *mode); bool free_fds(void); template -uint8_t *pod_addressof(T& structure) +uint8_t *pod_addressof_m(T& structure) { static_assert(is_trivially_copyable::value, "Can only byte-copy POD-ish structs"); return &reinterpret_cast(structure); } +template +const uint8_t *pod_addressof_c(const T& structure) +{ + static_assert(is_trivially_copyable::value, "Can only byte-copy POD-ish structs"); + return &reinterpret_cast(structure); +} /// Check how much can be read @@ -141,7 +147,7 @@ uint32_t RFIFOL(int fd, size_t pos) template void RFIFO_STRUCT(int fd, size_t pos, T& structure) { - really_memcpy(pod_addressof(structure), static_cast(RFIFOP(fd, pos)), sizeof(T)); + really_memcpy(pod_addressof_m(structure), static_cast(RFIFOP(fd, pos)), sizeof(T)); } inline void RFIFO_STRING(int fd, size_t pos, char *out, size_t len) @@ -181,7 +187,7 @@ uint32_t RBUFL(const uint8_t *p, size_t pos) template void RBUF_STRUCT(const uint8_t *p, size_t pos, T& structure) { - really_memcpy(pod_addressof(structure), p + pos, sizeof(T)); + really_memcpy(pod_addressof_m(structure), p + pos, sizeof(T)); } inline void RBUF_STRING(const uint8_t *p, size_t pos, char *out, size_t len) @@ -220,7 +226,7 @@ uint32_t& WFIFOL(int fd, size_t pos) template void WFIFO_STRUCT(int fd, size_t pos, T& structure) { - really_memcpy(static_cast(WFIFOP(fd, pos)), pod_addressof(structure), sizeof(T)); + really_memcpy(static_cast(WFIFOP(fd, pos)), pod_addressof_c(structure), sizeof(T)); } inline void WFIFO_STRING(int fd, size_t pos, const char *s, size_t len) @@ -267,7 +273,7 @@ uint32_t& WBUFL(uint8_t *p, size_t pos) template void WBUF_STRUCT(uint8_t *p, size_t pos, T& structure) { - really_memcpy(p + pos, pod_addressof(structure), sizeof(T)); + really_memcpy(p + pos, pod_addressof_c(structure), sizeof(T)); } inline void WBUF_STRING(uint8_t *p, size_t pos, const char *s, size_t len) diff --git a/src/common/strings.hpp b/src/common/strings.hpp new file mode 100644 index 0000000..2d34d57 --- /dev/null +++ b/src/common/strings.hpp @@ -0,0 +1,537 @@ +#ifndef TMWA_COMMON_STRINGS_HPP +#define TMWA_COMMON_STRINGS_HPP +// strings.hpp - All the string classes you'll ever need. +// +// Copyright © 2013 Ben Longbons +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "sanity.hpp" + +#include +#include + +#include +#include + +// It is a common mistake to assume that one string class for everything. +// Because C++ and TMWA have a C legacy, there are a few more here +// than would probably be necessary in an ideal language. +namespace strings +{ + // owning + class MString; + class FString; + class TString; // C legacy version of SString + class SString; // is this one really worth it? + + // non-owning + class ZString; // C legacy version of XString + class XString; + + // semi-owning + template + class VString; + + // simple pointer-wrapping iterator that can be used to get distinct + // types for different containers. + template + class _iterator + { + typedef _iterator X; + + const char *_ptr; + public: + typedef ptrdiff_t difference_type; + typedef char value_type; + typedef const char *pointer; + typedef const char& reference; + typedef std::random_access_iterator_tag iterator_category; + + _iterator(const char *p=nullptr) : _ptr(p) {} + + // iterator + reference operator *() { return *_ptr; } + X& operator ++() { ++_ptr; return *this; } + // equality comparable + friend bool operator == (X l, X r) { return l._ptr == r._ptr; } + // input iterator + friend bool operator != (X l, X r) { return !(l == r); } + pointer operator->() { return _ptr; } + X operator++ (int) { X out = *this; ++*this; return out; } + // forward iterator is mostly semantical, and the ctor is above + // bidirectional iterator + X& operator --() { --_ptr; return *this; } + X operator-- (int) { X out = *this; --*this; return out; } + // random access iterator + X& operator += (difference_type n) { _ptr += n; return *this; } + friend X operator + (X a, difference_type n) { return a += n; } + friend X operator + (difference_type n, X a) { return a += n; } + X& operator -= (difference_type n) { _ptr -= n; return *this; } + friend X operator - (X a, difference_type n) { return a -= n; } + friend difference_type operator - (X b, X a) { return b._ptr - a._ptr; } + reference operator[](difference_type n) { return _ptr[n]; } + friend bool operator < (X a, X b) { return a._ptr - b._ptr; } + friend bool operator > (X a, X b) { return b < a; } + friend bool operator >= (X a, X b) { return !(a < b); } + friend bool operator <= (X a, X b) { return !(a > b); } + }; + + /// A helper class that implements all the interesting stuff that can + /// be done on any constant string, in terms of .begin() and .end(). + template + class _crtp_string + { + public: + // this will have to be changed if MString decides to join in. + typedef _iterator iterator; + typedef std::reverse_iterator reverse_iterator; + private: + const T& _ref() const { return static_cast(*this); } + iterator begin() const { return _ref().begin(); } + iterator end() const { return _ref().end(); } + public: + size_t size() const { return end() - begin(); } + reverse_iterator rbegin() const { return reverse_iterator(end()); } + reverse_iterator rend() const { return reverse_iterator(begin()); } + operator bool() { return size(); } + bool operator !() { return !size(); } + + + char operator[](size_t i) const { return begin()[i]; } + char front() const { return *begin(); } + char back() const { return end()[-1]; } + const char *data() { return &*begin(); } + + XString xslice_t(size_t o) const; + XString xslice_h(size_t o) const; + XString xrslice_t(size_t no) const; + XString xrslice_h(size_t no) const; + XString xlslice(size_t o, size_t l) const; + XString xpslice(size_t b, size_t e) const; + bool startswith(XString x) const; + bool endswith(XString x) const; + }; + + + /// An owning string that is still expected to change. + /// The storage might not be contiguous, but it still offers + /// random-access iterators. + /// TODO implement a special one, to avoid quirks of std::string. + class MString + { + public: + typedef char *iterator; + typedef _iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + private: + std::string _hack; + public: + template + MString(char (&s)[n]) = delete; + template + MString(const char (&s)[n]) : _hack(s) {} + template + MString(It b, It e) : _hack(b, e) {} + + iterator begin() { return &*_hack.begin(); } + iterator end() { return &*_hack.end(); } + const_iterator begin() const { return &*_hack.begin(); } + const_iterator end() const { return &*_hack.end(); } + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + }; + + /// An owning string that has reached its final contents. + /// The storage is NUL-terminated + /// TODO implement a special one, that guarantees refcounting. + class FString : public _crtp_string + { + const std::string _hack; + public: + FString() : _hack() {} + FString(const MString& s) : _hack(s.begin(), s.end()) {} + template + FString(char (&s)[n]) = delete; + template + FString(const char (&s)[n]) : _hack(s) {} + template + FString(It b, It e) : _hack(b, e) {} + + iterator begin() const { return &*_hack.begin(); } + iterator end() const { return &*_hack.end(); } + const char *c_str() const { return &*begin(); } + + TString oslice_t(size_t o) const; + SString oslice_h(size_t o) const; + TString orslice_t(size_t no) const; + SString orslice_h(size_t no) const; + SString olslice(size_t o, size_t l) const; + SString opslice(size_t b, size_t e) const; + }; + + /// An owning string that represents a tail slice of an FString. + /// Guaranteed to be NUL-terminated. + class TString : public _crtp_string + { + friend class SString; + FString _s; + size_t _o; + public: + TString() : _s(), _o() {} + TString(FString b, size_t i=0) : _s(std::move(b)), _o(i) {} + + iterator begin() const { return &_s.begin()[_o]; } + iterator end() const { return &*_s.end(); } + const char *c_str() const { return &*begin(); } + + TString oslice_t(size_t o) const; + SString oslice_h(size_t o) const; + TString orslice_t(size_t no) const; + SString orslice_h(size_t no) const; + SString olslice(size_t o, size_t l) const; + SString opslice(size_t b, size_t e) const; + + operator FString() + { if (_o) return FString(begin(), end()); else return _s; } + }; + + /// An owning string that represents a arbitrary slice of an FString. + /// Not guaranteed to be NUL-terminated. + class SString : public _crtp_string + { + FString _s; + size_t _b, _e; + public: + SString() : _s(), _b(), _e() {} + SString(FString f) : _s(std::move(f)), _b(), _e(_s.size()) {} + SString(TString t) : _s(t._s), _e(_s.size()) {} + SString(FString f, size_t b, size_t e) : _s(std::move(f)), _b(b), _e(e) {} + + iterator begin() const { return &_s.begin()[_b]; } + iterator end() const { return &_s.begin()[_e]; } + + SString oslice_t(size_t o) const; + SString oslice_h(size_t o) const; + SString orslice_t(size_t no) const; + SString orslice_h(size_t no) const; + SString olslice(size_t o, size_t l) const; + SString opslice(size_t b, size_t e) const; + + operator FString() + { if (_b == 0 && _e == _s.size()) return _s; else return FString(begin(), end()); } + operator TString() + { if (_e == _s.size()) return TString(_s, _b); else return FString(begin(), end()); } + }; + + /// A non-owning string that is guaranteed to be NUL-terminated. + /// This should be only used as a parameter. + class ZString : public _crtp_string + { + iterator _b, _e; + public: +#ifndef __clang__ + __attribute__((warning("This should be removed in the next diff"))) +#endif + ZString(const std::string& s) : _b(&*s.begin()), _e(&*s.end()) {} + enum { really_construct_from_a_pointer }; + ZString() { *this = ZString(""); } + // no MString + ZString(const FString& s) : _b(&*s.begin()), _e(&*s.end()) {} + ZString(const TString& s) : _b(&*s.begin()), _e(&*s.end()) {} + // no SString + ZString(decltype(really_construct_from_a_pointer), const char *s) : _b(s), _e(s + strlen(s)) {} + template + ZString(char (&s)[n]) = delete; + template + ZString(const char (&s)[n]) : _b(s), _e(s + strlen(s)) {} + + iterator begin() const { return _b; } + iterator end() const { return _e; } + const char *c_str() const { return &*begin(); } + + ZString oslice_t(size_t o) const; + XString oslice_h(size_t o) const; + ZString orslice_t(size_t no) const; + XString orslice_h(size_t no) const; + XString olslice(size_t o, size_t l) const; + XString opslice(size_t b, size_t e) const; + }; + + /// A non-owning string that is not guaranteed to be NUL-terminated. + /// This should be only used as a parameter. + class XString : public _crtp_string + { + iterator _b, _e; + public: + // do I really want this? + XString() : _b(nullptr), _e(nullptr) {} + XString(std::nullptr_t) = delete; + // no MString + XString(const FString& s) : _b(&*s.begin()), _e(&*s.end()) {} + XString(const TString& s) : _b(&*s.begin()), _e(&*s.end()) {} + XString(const SString& s) : _b(&*s.begin()), _e(&*s.end()) {} + XString(const ZString& s) : _b(&*s.begin()), _e(&*s.end()) {} + template + XString(char (&s)[n]) = delete; + template + XString(const char (&s)[n]) : _b(s), _e(s + strlen(s)) {} + // mostly internal + XString(const char *b, const char *e) : _b(b), _e(e) {} + + iterator begin() const { return _b; } + iterator end() const { return _e; } + + XString oslice_t(size_t o) const { return xslice_t(o); } + XString oslice_h(size_t o) const { return xslice_h(o); } + XString orslice_t(size_t no) const { return xrslice_t(no); } + XString orslice_h(size_t no) const { return xrslice_h(no); } + XString olslice(size_t o, size_t l) const { return xlslice(o, l); } + XString opslice(size_t b, size_t e) const { return xpslice(b, e); } + }; + + template + class VString : public _crtp_string> + { + char _data[n]; + unsigned char _special; + typedef typename _crtp_string>::iterator iterator; + public: + static_assert(n & 1, "Size should probably be odd."); + VString(XString x) : _data(), _special() + { + if (x.size() > n) + // we're hoping this doesn't happen + // hopefully there will be few enough users of this class + x = x.xslice_h(n); + char *e = std::copy(x.begin(), x.end(), std::begin(_data)); + _special = std::end(_data) - e; + assert (_special == n - x.size()); // 0 when it needs to be + } + // poor man's delegated constructors + // needed for gcc 4.6 compatibility + template + VString(char (&s)[m]) = delete; + template + VString(const char (&s)[m]) + { + static_assert(m <= n + 1, "string would truncate"); + *this = XString(s); + } + VString(decltype(ZString::really_construct_from_a_pointer) e, const char *s) + { + *this = XString(ZString(e, s)); + } + VString() + { + *this = XString(); + } + // hopefully this is obvious + iterator begin() const { return std::begin(_data); } + iterator end() const { return std::end(_data) - _special; } + const char *c_str() const { return &*begin(); } + + VString oslice_t(size_t o) const { return this->xslice_t(o); } + VString oslice_h(size_t o) const { return this->xslice_h(o); } + VString orslice_t(size_t no) const { return this->xrslice_t(no); } + VString orslice_h(size_t no) const { return this->xrslice_h(no); } + VString olslice(size_t o, size_t l) const { return this->xlslice(o, l); } + VString opslice(size_t b, size_t e) const { return this->xpslice(b, e); } + operator XString() const { return XString(&*begin(), &*end()); } + }; + + + // not really intended for public use + inline + int xstr_compare(XString l, XString r) + { + return std::lexicographical_compare( + l.begin(), l.end(), + r.begin(), r.end()); + } + + template + bool operator == (const L& l, const R& r) + { + return xstr_compare(l, r) == 0; + } + template + bool operator != (const L& l, const R& r) + { + return xstr_compare(l, r) != 0; + } + template + bool operator < (const L& l, const R& r) + { + return xstr_compare(l, r) < 0; + } + template + bool operator <= (const L& l, const R& r) + { + return xstr_compare(l, r) <= 0; + } + template + bool operator > (const L& l, const R& r) + { + return xstr_compare(l, r) > 0; + } + template + bool operator >= (const L& l, const R& r) + { + return xstr_compare(l, r) >= 0; + } + + + // sadness + typedef MString MS; + typedef FString FS; + typedef SString SS; + typedef TString TS; + typedef ZString ZS; + typedef XString XS; + + // _crtp_string + template + XS _crtp_string::xslice_t(size_t o) const + { return XS(&begin()[o], &*end()); } + template + XS _crtp_string::xslice_h(size_t o) const + { return XS(&*begin(), &begin()[o]); } + template + XS _crtp_string::xrslice_t(size_t no) const + { return XS(&end()[-no], &*end()); } + template + XS _crtp_string::xrslice_h(size_t no) const + { return XS(&*begin(), &end()[-no]); } + template + XS _crtp_string::xlslice(size_t o, size_t l) const + { return XS(&begin()[o], &begin()[o + l]); } + template + XS _crtp_string::xpslice(size_t b, size_t e) const + { return XS(&begin()[b], &begin()[e]); } + template + bool _crtp_string::startswith(XS x) const + { return size() > x.size() && xslice_h(x.size()) == x; } + template + bool _crtp_string::endswith(XS x) const + { return size() > x.size() && xrslice_t(x.size()) == x; } + + // FString + inline + TS FS::oslice_t(size_t o) const + { return TS(*this, o); } + inline + SS FS::oslice_h(size_t o) const + { return SS(*this, 0, o); } + inline + TS FS::orslice_t(size_t no) const + { return TS(*this, size() - no); } + inline + SS FS::orslice_h(size_t no) const + { return SS(*this, 0, size() - no); } + inline + SS FS::olslice(size_t o, size_t l) const + { return SS(*this, o, o + l); } + inline + SS FS::opslice(size_t b, size_t e) const + { return SS(*this, b, e); } + + // TString + inline + TS TS::oslice_t(size_t o) const + { return TS(_s, _o + o); } + inline + SS TS::oslice_h(size_t o) const + { return SS(_s, _o, _o + o); } + inline + TS TS::orslice_t(size_t no) const + { return TS(_s, _s.size() - no); } + inline + SS TS::orslice_h(size_t no) const + { return SS(_s, _o, _s.size() - no); } + inline + SS TS::olslice(size_t o, size_t l) const + { return SS(_s, _o + o, _o + o + l); } + inline + SS TS::opslice(size_t b, size_t e) const + { return SS(_s, _o + b, _o + e); } + + // SString + inline + SS SS::oslice_t(size_t o) const + { return SS(_s, _b + o, _e); } + inline + SS SS::oslice_h(size_t o) const + { return SS(_s, _b, _b + o); } + inline + SS SS::orslice_t(size_t no) const + { return SS(_s, _e - no, _e); } + inline + SS SS::orslice_h(size_t no) const + { return SS(_s, _b, _e - no); } + inline + SS SS::olslice(size_t o, size_t l) const + { return SS(_s, _b + o, _b + o + l); } + inline + SS SS::opslice(size_t b, size_t e) const + { return SS(_s, _b + b, _b + e); } + + // ZString + inline + ZS ZS::oslice_t(size_t o) const + { return ZS(really_construct_from_a_pointer, &begin()[o]); } + inline + XS ZS::oslice_h(size_t o) const + { return XS(&*begin(), &begin()[o]); } + inline + ZS ZS::orslice_t(size_t no) const + { return ZS(really_construct_from_a_pointer, &end()[-no]); } + inline + XS ZS::orslice_h(size_t no) const + { return XS(&*begin(), &end()[-no]); } + inline + XS ZS::olslice(size_t o, size_t l) const + { return XS(&begin()[o], &begin()[o + l]); } + inline + XS ZS::opslice(size_t b, size_t e) const + { return XS(&begin()[b], &begin()[e]); } + + + // cxxstdio helpers + // I think the conversion will happen automatically. TODO test this. + //const char *convert_for_printf(const FString& fs) { return fs.c_str(); } + //const char *convert_for_printf(const TString& ts) { return ts.c_str(); } + inline + const char *convert_for_printf(const ZString& zs) { return zs.c_str(); } +} // namespace strings + +// owning +using strings::MString; +using strings::FString; +using strings::SString; +using strings::TString; + +// non-owning +using strings::ZString; +using strings::XString; + +// semi-owning +using strings::VString; + +#endif // TMWA_COMMON_STRINGS_HPP diff --git a/src/common/strings_test.cpp b/src/common/strings_test.cpp new file mode 100644 index 0000000..e83d283 --- /dev/null +++ b/src/common/strings_test.cpp @@ -0,0 +1,99 @@ +#include "../../src/common/strings.hpp" + +#include + +template +class StringTest : public ::testing::Test +{ +}; +TYPED_TEST_CASE_P(StringTest); + +TYPED_TEST_P(StringTest, basic) +{ + TypeParam hi("Hello"); + EXPECT_EQ(5, hi.size()); + EXPECT_EQ(hi, hi); + const char hi2[] = "Hello\0random garbage"; + EXPECT_EQ(hi, hi2); + TypeParam hi0; + EXPECT_EQ(0, hi0.size()); +} + +TYPED_TEST_P(StringTest, iterators) +{ + TypeParam hi("Hello"); + EXPECT_EQ(hi.begin(), hi.begin()); + EXPECT_NE(hi.begin(), hi.end()); + EXPECT_EQ(5, std::distance(hi.begin(), hi.end())); + const char *hi2 = "Hello"; + EXPECT_TRUE(std::equal(hi.begin(), hi.end(), hi2)); +} + +TYPED_TEST_P(StringTest, xslice) +{ + TypeParam hi("Hello, World!"); + EXPECT_EQ(" World!", hi.xslice_t(6)); + EXPECT_EQ("Hello,", hi.xslice_h(6)); + EXPECT_EQ("World!", hi.xrslice_t(6)); + EXPECT_EQ("Hello, ", hi.xrslice_h(6)); + EXPECT_EQ("World", hi.xlslice(7, 5)); + EXPECT_EQ("World", hi.xpslice(7, 12)); + EXPECT_TRUE(hi.startswith("Hello")); + EXPECT_TRUE(hi.endswith("World!")); +} + +TYPED_TEST_P(StringTest, oslice) +{ + TypeParam hi("Hello, World!"); + EXPECT_EQ(" World!", hi.oslice_t(6)); + EXPECT_EQ("Hello,", hi.oslice_h(6)); + EXPECT_EQ("World!", hi.orslice_t(6)); + EXPECT_EQ("Hello, ", hi.orslice_h(6)); + EXPECT_EQ("World", hi.olslice(7, 5)); + EXPECT_EQ("World", hi.opslice(7, 12)); +} + +REGISTER_TYPED_TEST_CASE_P(StringTest, + basic, iterators, xslice, oslice); + +typedef ::testing::Types< + FString, TString, SString, ZString, XString, VString<255> +> MostStringTypes; +INSTANTIATE_TYPED_TEST_CASE_P(StringStuff, StringTest, MostStringTypes); + +TEST(VStringTest, basic) +{ + VString<5> hi = "Hello"; + EXPECT_EQ(5, hi.size()); + EXPECT_EQ(hi, hi); + // truncation + VString<5> hi2(ZString::really_construct_from_a_pointer, "Hello, world!"); + EXPECT_EQ(5, hi2.size()); + EXPECT_EQ(hi, hi2); + // short + hi = "hi"; + EXPECT_EQ(2, hi.size()); + VString<5> hi0; + EXPECT_EQ(0, hi0.size()); +} + +template +class NulStringTest : public ::testing::Test +{ +}; +TYPED_TEST_CASE_P(NulStringTest); + +TYPED_TEST_P(NulStringTest, basic) +{ + TypeParam hi("hello"); + EXPECT_EQ(hi.size(), strlen(hi.c_str())); + EXPECT_STREQ("hello", hi.c_str()); +} + +REGISTER_TYPED_TEST_CASE_P(NulStringTest, + basic); + +typedef ::testing::Types< + FString, TString, ZString, VString<255> +> NulStringTypes; +INSTANTIATE_TYPED_TEST_CASE_P(NulStringStuff, NulStringTest, NulStringTypes); diff --git a/src/common/utils.hpp b/src/common/utils.hpp index cd45aa1..ab32948 100644 --- a/src/common/utils.hpp +++ b/src/common/utils.hpp @@ -34,7 +34,8 @@ void strzcpy(char *dest, const char *src, size_t n) { if (n) { - strncpy(dest, src, n); + // hmph + strncpy(dest, src, n - 1); dest[n - 1] = '\0'; } } @@ -50,6 +51,11 @@ void really_memmove(uint8_t *dest, const uint8_t *src, size_t n) { memmove(dest, src, n); } +inline +bool really_memequal(const uint8_t *a, const uint8_t *b, size_t n) +{ + return memcmp(a, b, n) == 0; +} inline void really_memset0(uint8_t *dest, size_t n) @@ -140,4 +146,10 @@ static_assert(sizeof(TIMESTAMP_DUMMY) == sizeof(timestamp_seconds_buffer), &t \ ) +template +const T& const_(T& t) +{ + return t; +} + #endif //UTILS_HPP diff --git a/src/common/utils2.hpp b/src/common/utils2.hpp index 2218625..d7d6f8a 100644 --- a/src/common/utils2.hpp +++ b/src/common/utils2.hpp @@ -3,6 +3,7 @@ #include "sanity.hpp" +#include #include #include #include @@ -39,6 +40,26 @@ struct earray { return _data + size_t(max); } + + const T *begin() const + { + return _data; + } + + const T *end() const + { + return _data + size_t(max); + } + + friend bool operator == (const earray& l, const earray& r) + { + return std::equal(l.begin(), l.end(), r.begin()); + } + + friend bool operator != (const earray& l, const earray& r) + { + return !(l == r); + } }; template diff --git a/src/ladmin/ladmin.cpp b/src/ladmin/ladmin.cpp index c5a98fd..5f3ef7b 100644 --- a/src/ladmin/ladmin.cpp +++ b/src/ladmin/ladmin.cpp @@ -1392,7 +1392,7 @@ int delaccount(const char *param) { PRINTF("\033[1;36m ** Are you really sure to DELETE account [%s]? (y/n) > \033[0m", name); fflush(stdout); - strzcpy(confirm, "", sizeof(confirm)); + strzcpy(confirm, "", sizeof(confirm)); i = 0; while ((letter = getchar()) != '\n') confirm[i++] = letter; @@ -2709,7 +2709,7 @@ void parse_fromlogin(int fd) char md5str[64] = ""; size_t key_len = RFIFOW(fd, 2) - 4; uint8_t md5bin[32]; - char md5key[key_len]; + char md5key[key_len]; RFIFO_STRING(fd, 4, md5key, key_len); if (passenc == 1) { @@ -2878,84 +2878,104 @@ void parse_fromlogin(int fd) case 0x7931: // Answer of login-server about an account creation if (RFIFOREST(fd) < 30) return; - if (RFIFOL(fd, 2) == -1) + { + int accid = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (accid == -1) { PRINTF("Account [%s] creation failed. Same account already exists.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("Account [%s] creation failed. Same account already exists.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { PRINTF("Account [%s] is successfully created [id: %d].\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, accid); LADMIN_LOG("Account [%s] is successfully created [id: %d].\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, accid); } bytes_to_read = 0; + } RFIFOSKIP(fd, 30); break; case 0x7933: // Answer of login-server about an account deletion if (RFIFOREST(fd) < 30) return; - if (RFIFOL(fd, 2) == -1) + { + int accid = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (accid == -1) { PRINTF("Account [%s] deletion failed. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("Account [%s] deletion failed. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { PRINTF("Account [%s][id: %d] is successfully DELETED.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, accid); LADMIN_LOG("Account [%s][id: %d] is successfully DELETED.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, accid); } bytes_to_read = 0; + } RFIFOSKIP(fd, 30); break; case 0x7935: // answer of the change of an account password if (RFIFOREST(fd) < 30) return; - if (RFIFOL(fd, 2) == -1) + { + int accid = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (accid == -1) { PRINTF("Account [%s] password changing failed.\n", - static_cast(RFIFOP(fd, 6))); + name); PRINTF("Account [%s] doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("Account password changing failed. The compte [%s] doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { PRINTF("Account [%s][id: %d] password successfully changed.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, accid); LADMIN_LOG("Account [%s][id: %d] password successfully changed.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, accid); } bytes_to_read = 0; + } RFIFOSKIP(fd, 30); break; case 0x7937: // answer of the change of an account state if (RFIFOREST(fd) < 34) return; - if (RFIFOL(fd, 2) == -1) + { + int accid = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + int state = RFIFOL(fd, 30); + if (accid == -1) { PRINTF("Account [%s] state changing failed. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("Account [%s] state changing failed. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { std::string tmpstr = STRPRINTF( "Account [%s] state successfully changed in [", - static_cast(RFIFOP(fd, 6))); - switch (RFIFOL(fd, 30)) + name); + switch (state) { case 0: tmpstr += "0: Account OK"; @@ -2996,6 +3016,7 @@ void parse_fromlogin(int fd) LADMIN_LOG("%s\n", tmpstr); } bytes_to_read = 0; + } RFIFOSKIP(fd, 34); break; @@ -3016,7 +3037,7 @@ void parse_fromlogin(int fd) // Displaying of result for (int i = 4; i < RFIFOW(fd, 2); i += 32) { - char name[20]; + char name[20]; RFIFO_STRING(fd, i + 6, name, 20); PRINTF(" %-20s : %5d\n", name, RFIFOW(fd, i + 26)); @@ -3030,167 +3051,205 @@ void parse_fromlogin(int fd) case 0x793b: // answer of the check of a password if (RFIFOREST(fd) < 30) return; - if (RFIFOL(fd, 2) == -1) + { + int account_id = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (account_id == -1) { PRINTF("The account [%s] doesn't exist or the password is incorrect.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("The account [%s] doesn't exist or the password is incorrect.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { PRINTF("The proposed password is correct for the account [%s][id: %d].\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); LADMIN_LOG("The proposed password is correct for the account [%s][id: %d].\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); } bytes_to_read = 0; + } RFIFOSKIP(fd, 30); break; case 0x793d: // answer of the change of an account sex if (RFIFOREST(fd) < 30) return; - if (RFIFOL(fd, 2) == -1) + { + int account_id = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (account_id == -1) { PRINTF("Account [%s] sex changing failed.\n", - static_cast(RFIFOP(fd, 6))); + name); PRINTF("Account [%s] doesn't exist or the sex is already the good sex.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("Account sex changing failed. The compte [%s] doesn't exist or the sex is already the good sex.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { PRINTF("Account [%s][id: %d] sex successfully changed.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); LADMIN_LOG("Account [%s][id: %d] sex successfully changed.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); } bytes_to_read = 0; + } RFIFOSKIP(fd, 30); break; case 0x793f: // answer of the change of an account GM level if (RFIFOREST(fd) < 30) return; - if (RFIFOL(fd, 2) == -1) + { + int account_id = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (account_id == -1) { PRINTF("Account [%s] GM level changing failed.\n", - static_cast(RFIFOP(fd, 6))); + name); PRINTF("Account [%s] doesn't exist, the GM level is already the good GM level\n", - static_cast(RFIFOP(fd, 6))); + name); PRINTF("or it's impossible to modify the GM accounts file.\n"); LADMIN_LOG("Account GM level changing failed. The compte [%s] doesn't exist, the GM level is already the good sex or it's impossible to modify the GM accounts file.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { PRINTF("Account [%s][id: %d] GM level successfully changed.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); LADMIN_LOG("Account [%s][id: %d] GM level successfully changed.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); } bytes_to_read = 0; + } RFIFOSKIP(fd, 30); break; case 0x7941: // answer of the change of an account email if (RFIFOREST(fd) < 30) return; - if (RFIFOL(fd, 2) == -1) + { + int account_id = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (account_id == -1) { PRINTF("Account [%s] e-mail changing failed.\n", - static_cast(RFIFOP(fd, 6))); + name); PRINTF("Account [%s] doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("Account e-mail changing failed. The compte [%s] doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { PRINTF("Account [%s][id: %d] e-mail successfully changed.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); LADMIN_LOG("Account [%s][id: %d] e-mail successfully changed.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); } bytes_to_read = 0; + } RFIFOSKIP(fd, 30); break; case 0x7943: // answer of the change of an account memo if (RFIFOREST(fd) < 30) return; - if (RFIFOL(fd, 2) == -1) + { + int account_id = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (account_id == -1) { PRINTF("Account [%s] memo changing failed. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("Account [%s] memo changing failed. Account doesn't exist.\n", - - static_cast(RFIFOP(fd, 6))); + name); } else { PRINTF("Account [%s][id: %d] memo successfully changed.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); LADMIN_LOG("Account [%s][id: %d] memo successfully changed.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); } bytes_to_read = 0; + } RFIFOSKIP(fd, 30); break; case 0x7945: // answer of an account id search if (RFIFOREST(fd) < 30) return; - if (RFIFOL(fd, 2) == -1) + { + int account_id = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (account_id == -1) { PRINTF("Unable to find the account [%s] id. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("Unable to find the account [%s] id. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { PRINTF("The account [%s] have the id: %d.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); LADMIN_LOG("The account [%s] have the id: %d.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); } bytes_to_read = 0; + } RFIFOSKIP(fd, 30); break; case 0x7947: // answer of an account name search if (RFIFOREST(fd) < 30) return; - if (strcmp(static_cast(RFIFOP(fd, 6)), "") == 0) + { + int account_id = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (strcmp(name, "") == 0) { PRINTF("Unable to find the account [%d] name. Account doesn't exist.\n", - RFIFOL(fd, 2)); + account_id); LADMIN_LOG("Unable to find the account [%d] name. Account doesn't exist.\n", - RFIFOL(fd, 2)); + account_id); } else { PRINTF("The account [id: %d] have the name: %s.\n", - RFIFOL(fd, 2), static_cast(RFIFOP(fd, 6))); + account_id, name); LADMIN_LOG("The account [id: %d] have the name: %s.\n", - RFIFOL(fd, 2), static_cast(RFIFOP(fd, 6))); + account_id, name); } bytes_to_read = 0; + } RFIFOSKIP(fd, 30); break; case 0x7949: // answer of an account validity limit set if (RFIFOREST(fd) < 34) return; + { + int account_id = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); if (RFIFOL(fd, 2) == -1) { PRINTF("Account [%s] validity limit changing failed. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("Account [%s] validity limit changing failed. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { @@ -3198,34 +3257,39 @@ void parse_fromlogin(int fd) if (!timestamp) { PRINTF("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); LADMIN_LOG("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); } else { timestamp_seconds_buffer tmpstr; stamp_time(tmpstr, ×tamp); PRINTF("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2), tmpstr); + name, account_id, tmpstr); LADMIN_LOG("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2), + name, account_id, tmpstr); } } bytes_to_read = 0; + } RFIFOSKIP(fd, 34); break; case 0x794b: // answer of an account ban set if (RFIFOREST(fd) < 34) return; - if (RFIFOL(fd, 2) == -1) + { + int account_id = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (account_id == -1) { PRINTF("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { @@ -3233,34 +3297,39 @@ void parse_fromlogin(int fd) if (!timestamp) { PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); } else { timestamp_seconds_buffer tmpstr; stamp_time(tmpstr, ×tamp); PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2), tmpstr); + name, RFIFOL(fd, 2), tmpstr); LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2), + name, RFIFOL(fd, 2), tmpstr); } } bytes_to_read = 0; + } RFIFOSKIP(fd, 34); break; case 0x794d: // answer of an account ban date/time changing if (RFIFOREST(fd) < 34) return; - if (RFIFOL(fd, 2) == -1) + { + int account_id = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + if (account_id == -1) { PRINTF("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); LADMIN_LOG("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", - static_cast(RFIFOP(fd, 6))); + name); } else { @@ -3268,23 +3337,24 @@ void parse_fromlogin(int fd) if (!timestamp) { PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2)); + name, account_id); } else { timestamp_seconds_buffer tmpstr; stamp_time(tmpstr, ×tamp); PRINTF("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2), + name, account_id, tmpstr); LADMIN_LOG("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", - static_cast(RFIFOP(fd, 6)), RFIFOL(fd, 2), + name, account_id, tmpstr); } } bytes_to_read = 0; + } RFIFOSKIP(fd, 34); break; diff --git a/src/login/login.cpp b/src/login/login.cpp index df271ef..d72bf61 100644 --- a/src/login/login.cpp +++ b/src/login/login.cpp @@ -391,7 +391,8 @@ bool check_ip(struct in_addr ip) for (const AccessEntry& ae : access_allow) { const char *p = ae.data(); - if (memcmp(p, buf, strlen(p)) == 0 || check_ipmask(ip, p)) +#warning "TODO remove the strncmp part and use an IPAddress4 class" + if (strncmp(p, buf, strlen(p)) == 0 || check_ipmask(ip, p)) { flag = ACF::ALLOW; if (access_order == ACO::ALLOW_DENY) @@ -404,7 +405,7 @@ bool check_ip(struct in_addr ip) for (const AccessEntry& ae : access_deny) { const char *p = ae.data(); - if (memcmp(p, buf, strlen(p)) == 0 || check_ipmask(ip, p)) + if (strncmp(p, buf, strlen(p)) == 0 || check_ipmask(ip, p)) { flag = ACF::DENY; return 0; @@ -443,7 +444,7 @@ bool check_ladminip(struct in_addr ip) for (const AccessEntry& ae : access_ladmin) { const char *p = ae.data(); - if (memcmp(p, buf, strlen(p)) == 0 || check_ipmask(ip, p)) + if (strncmp(p, buf, strlen(p)) == 0 || check_ipmask(ip, p)) return true; } @@ -1151,7 +1152,6 @@ void parse_fromchar(int fd) acc = RFIFOL(fd, 2); // speed up RFIFO_STRING(fd, 6, email, 40); remove_control_chars(email); - //PRINTF("parse_fromchar: an e-mail creation of an account with a default e-mail: server '%s', account: %d, e-mail: '%s'.\n", server[id].name, acc, RFIFOP(fd,6)); if (e_mail_check(email) == 0) LOGIN_LOG("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); @@ -1214,7 +1214,11 @@ void parse_fromchar(int fd) WBUFW(buf, 0) = 0x2721; WBUFL(buf, 2) = acc; WBUFL(buf, 6) = 0; - if (strcmp(static_cast(RFIFOP(fd, 8)), gm_pass) == 0) + size_t len = RFIFOW(fd, 2) - 8; + char pass[len]; + RFIFO_STRING(fd, 8, pass, len); + + if (strcmp(pass, gm_pass) == 0) { // only non-GM can become GM if (isGM(acc) == 0) @@ -1511,7 +1515,7 @@ void parse_fromchar(int fd) { LOGIN_LOG("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", server[id].name, acc, ip); - size_t len = RFIFOW(fd, 2); + size_t len = RFIFOW(fd, 2); int j; for (p = 8, j = 0; p < len && j < ACCOUNT_REG2_NUM; @@ -1524,7 +1528,7 @@ void parse_fromchar(int fd) ad.account_reg2_num = j; // Sending information towards the other char-servers. uint8_t buf[len]; - RFIFO_BUF_CLONE(fd, buf, len); + RFIFO_BUF_CLONE(fd, buf, len); WBUFW(buf, 0) = 0x2729; charif_sendallwos(fd, buf, WBUFW(buf, 2)); // PRINTF("parse_fromchar: receiving (from the char-server) of account_reg2 (account id: %d).\n", acc); @@ -1578,7 +1582,7 @@ void parse_fromchar(int fd) acc = RFIFOL(fd, 2); RFIFO_STRING(fd, 6, actual_pass, 24); remove_control_chars(actual_pass); - RFIFO_STRING(fd, 30, new_pass, 24); + RFIFO_STRING(fd, 30, new_pass, 24); remove_control_chars(new_pass); int status = 0; @@ -1637,7 +1641,7 @@ void parse_fromchar(int fd) FPRINTF(logfp, "Detail (in hex):\n"); FPRINTF(logfp, "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F\n"); - char tmpstr[16 + 1] {}; + char tmpstr[16 + 1] {}; int i; for (i = 0; i < RFIFOREST(fd); i++) { @@ -1653,7 +1657,7 @@ void parse_fromchar(int fd) else if ((i + 1) % 16 == 0) { FPRINTF(logfp, " %s\n", tmpstr); - strzcpy(tmpstr, "", 16 + 1); + strzcpy(tmpstr, "", 16 + 1); } } if (i % 16 != 0) @@ -1774,7 +1778,7 @@ void parse_admin(int fd) if (RFIFOREST(fd) < 10) return; uint8_t buf[10]; - RFIFO_BUF_CLONE(fd, buf, 10); + RFIFO_BUF_CLONE(fd, buf, 10); // forward package to char servers charif_sendallwos(-1, buf, 10); RFIFOSKIP(fd, 10); @@ -1826,7 +1830,7 @@ void parse_admin(int fd) { int new_id; char email[40]; - strzcpy(email, static_cast(RFIFOP(fd, 51)), 40); + RFIFO_STRING(fd, 51, email, 40); remove_control_chars(email); new_id = mmo_auth_new(&ma, ma.sex, email); LOGIN_LOG("'ladmin': Account creation (account: %s (id: %d), sex: %c, email: %s, ip: %s)\n", @@ -1847,13 +1851,12 @@ void parse_admin(int fd) { WFIFOW(fd, 0) = 0x7933; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); AuthData *ad = search_account(account_name); if (ad) { // TODO rename so I don't need anti-shadow braces - { // Char-server is notified of deletion (for characters deletion). uint8_t buf[6]; WBUFW(buf, 0) = 0x2730; @@ -1866,13 +1869,12 @@ void parse_admin(int fd) LOGIN_LOG("'ladmin': Account deletion (account: %s, id: %d, ip: %s) - saved in next line:\n", ad->userid, ad->account_id, ip); - } { - std::string buf = mmo_auth_tostr(ad); - LOGIN_LOG("%s\n", buf); + std::string buf2 = mmo_auth_tostr(ad); + LOGIN_LOG("%s\n", buf2); } // delete account - strzcpy(ad->userid, "", 24); + strzcpy(ad->userid, "", 24); ad->account_id = -1; } else @@ -1892,13 +1894,15 @@ void parse_admin(int fd) { WFIFOW(fd, 0) = 0x7935; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); AuthData *ad = search_account(account_name); if (ad) { WFIFO_STRING(fd, 6, ad->userid, 24); - strzcpy(ad->pass, MD5_saltcrypt(static_cast(RFIFOP(fd, 26)), make_salt()), 40); + char plain[24]; + RFIFO_STRING(fd, 26, plain, 24); + strzcpy(ad->pass, MD5_saltcrypt(plain, make_salt()), 40); WFIFOL(fd, 2) = ad->account_id; LOGIN_LOG("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n", ad->userid, ad->pass, ip); @@ -1922,10 +1926,10 @@ void parse_admin(int fd) int statut; WFIFOW(fd, 0) = 0x7937; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); statut = RFIFOL(fd, 26); - strzcpy(error_message, static_cast(RFIFOP(fd, 30)), 20); + RFIFO_STRING(fd, 30, error_message, 20); remove_control_chars(error_message); if (statut != 7 || error_message[0] == '\0') { // 7: // 6 = Your are Prohibited to log in until %s @@ -2006,14 +2010,14 @@ void parse_admin(int fd) { WFIFOW(fd, 0) = 0x793b; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); const AuthData *ad = search_account(account_name); if (ad) { WFIFO_STRING(fd, 6, ad->userid, 24); char pass[24]; - strzcpy(pass, static_cast(RFIFOP(fd, 26)), 24); + RFIFO_STRING(fd, 26, pass, 24); if (pass_ok(pass, ad->pass)) { WFIFOL(fd, 2) = ad->account_id; @@ -2044,7 +2048,7 @@ void parse_admin(int fd) return; WFIFOW(fd, 0) = 0x793d; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); WFIFO_STRING(fd, 6, account_name, 24); { @@ -2107,7 +2111,7 @@ void parse_admin(int fd) return; WFIFOW(fd, 0) = 0x793f; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); WFIFO_STRING(fd, 6, account_name, 24); { @@ -2253,12 +2257,12 @@ void parse_admin(int fd) return; WFIFOW(fd, 0) = 0x7941; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); WFIFO_STRING(fd, 6, account_name, 24); { char email[40]; - strzcpy(email, static_cast(RFIFOP(fd, 26)), 40); + RFIFO_STRING(fd, 26, email, 40); if (e_mail_check(email) == 0) { LOGIN_LOG("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)\n", @@ -2294,23 +2298,23 @@ void parse_admin(int fd) { WFIFOW(fd, 0) = 0x7943; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); AuthData *ad = search_account(account_name); if (ad) { size_t size_of_memo = sizeof(ad->memo); WFIFO_STRING(fd, 6, ad->userid, 24); - strzcpy(ad->memo, "", size_of_memo); + strzcpy(ad->memo, "", size_of_memo); if (RFIFOW(fd, 26) == 0) { strzcpy(ad->memo, "!", size_of_memo); } else { - size_t len = RFIFOW(fd, 26); - if (len > size_of_memo) - len = size_of_memo; + size_t len = RFIFOW(fd, 26); + if (len > size_of_memo) + len = size_of_memo; RFIFO_STRING(fd, 28, ad->memo, len); } ad->memo[size_of_memo - 1] = '\0'; @@ -2336,7 +2340,7 @@ void parse_admin(int fd) { WFIFOW(fd, 0) = 0x7945; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); const AuthData *ad = search_account(account_name); if (ad) @@ -2363,12 +2367,12 @@ void parse_admin(int fd) return; WFIFOW(fd, 0) = 0x7947; WFIFOL(fd, 2) = RFIFOL(fd, 2); - WFIFO_ZERO(fd, 6, 24); + WFIFO_ZERO(fd, 6, 24); for (const AuthData& ad : auth_data) { if (ad.account_id == RFIFOL(fd, 2)) { - strncpy(static_cast(WFIFOP(fd, 6)), ad.userid, 24); + WFIFO_STRING(fd, 6, ad.userid, 24); LOGIN_LOG("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)\n", ad.userid, RFIFOL(fd, 2), ip); goto x7946_out; @@ -2376,7 +2380,7 @@ void parse_admin(int fd) } LOGIN_LOG("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)\n", RFIFOL(fd, 2), ip); - strncpy(static_cast(WFIFOP(fd, 6)), "", 24); + WFIFO_STRING(fd, 6, "", 24); x7946_out: WFIFOSET(fd, 30); RFIFOSKIP(fd, 6); @@ -2388,7 +2392,7 @@ void parse_admin(int fd) { WFIFOW(fd, 0) = 0x7949; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); TimeT timestamp = static_cast(RFIFOL(fd, 26)); timestamp_seconds_buffer tmpstr = "unlimited"; @@ -2427,7 +2431,7 @@ void parse_admin(int fd) { WFIFOW(fd, 0) = 0x794b; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); TimeT timestamp = static_cast(RFIFOL(fd, 26)); if (timestamp <= TimeT::now()) @@ -2482,7 +2486,7 @@ void parse_admin(int fd) { WFIFOW(fd, 0) = 0x794d; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); AuthData *ad = search_account(account_name); if (ad) @@ -2587,22 +2591,28 @@ void parse_admin(int fd) goto x794e_have_no_server; { x794e_have_server: - // overwrite the -1 + // overwrite the -1 WFIFOW(fd, 2) = 0; - size_t len = RFIFOL(fd, 4); - char message[len]; - RFIFO_STRING(fd, 8, message, len); + size_t len = RFIFOL(fd, 4); + char message[len]; + RFIFO_STRING(fd, 8, message, len); remove_control_chars(message); - const char *message_ptr = message; - LOGIN_LOG("'ladmin': Receiving a message for broadcast (message: %s, ip: %s)\n", - message_ptr, ip); + const char *message_ptr = message; + LOGIN_LOG("'ladmin': Receiving a message for broadcast (message: %s, ip: %s)\n", + message_ptr, ip); // send same message to all char-servers (no answer) uint8_t buf[len + 8]; - RFIFO_BUF_CLONE(fd, buf, 8 + len); + RFIFO_BUF_CLONE(fd, buf, 8 + len); WBUFW(buf, 0) = 0x2726; charif_sendallwos(-1, buf, 8 + len); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuninitialized" // work around a gcc bug +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" } +#pragma GCC diagnostic pop } x794e_have_no_server: WFIFOSET(fd, 4); @@ -2615,7 +2625,7 @@ void parse_admin(int fd) { WFIFOW(fd, 0) = 0x7951; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); AuthData *ad = search_account(account_name); if (ad) @@ -2704,7 +2714,7 @@ void parse_admin(int fd) { WFIFOW(fd, 0) = 0x7953; WFIFOL(fd, 2) = -1; - strzcpy(account_name, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account_name, 24); remove_control_chars(account_name); const AuthData *ad = search_account(account_name); if (ad) @@ -2721,9 +2731,9 @@ void parse_admin(int fd) WFIFO_STRING(fd, 100, ad->email, 40); WFIFOL(fd, 140) = static_cast(ad->connect_until_time); WFIFOL(fd, 144) = static_cast(ad->ban_until_time); - size_t len = strlen(ad->memo) + 1; + size_t len = strlen(ad->memo) + 1; WFIFOW(fd, 148) = len; - WFIFO_STRING(fd, 150, ad->memo, len); + WFIFO_STRING(fd, 150, ad->memo, len); LOGIN_LOG("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n", ad->userid, ad->account_id, ip); @@ -2764,9 +2774,9 @@ void parse_admin(int fd) WFIFO_STRING(fd, 100, ad.email, 40); WFIFOL(fd, 140) = static_cast(ad.connect_until_time); WFIFOL(fd, 144) = static_cast(ad.ban_until_time); - size_t len = strlen(ad.memo) + 1; + size_t len = strlen(ad.memo) + 1; WFIFOW(fd, 148) = len; - WFIFO_STRING(fd, 150, ad.memo, len); + WFIFO_STRING(fd, 150, ad.memo, len); WFIFOSET(fd, 150 + len); goto x7954_out; } @@ -2774,7 +2784,7 @@ void parse_admin(int fd) { LOGIN_LOG("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)\n", RFIFOL(fd, 2), ip); - strncpy(static_cast(WFIFOP(fd, 7)), "", 24); + WFIFO_STRING(fd, 7, "", 24); WFIFOW(fd, 148) = 0; WFIFOSET(fd, 150); } @@ -2798,7 +2808,7 @@ void parse_admin(int fd) if (logfp) { timestamp_milliseconds_buffer timestr; - stamp_time(timestr); + stamp_time(timestr); FPRINTF(logfp, "%s: receiving of an unknown packet -> disconnection\n", timestr); @@ -2808,7 +2818,7 @@ void parse_admin(int fd) FPRINTF(logfp, "Detail (in hex):\n"); FPRINTF(logfp, "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F\n"); - char tmpstr[16 + 1] {}; + char tmpstr[16 + 1] {}; int i; for (i = 0; i < RFIFOREST(fd); i++) { @@ -2905,16 +2915,24 @@ void parse_login(int fd) if (RFIFOW(fd, 0) == 0x64 || RFIFOW(fd, 0) == 0x01dd) { if (RFIFOREST(fd) >= ((RFIFOW(fd, 0) == 0x64) ? 55 : 47)) + { + char account_name[24]; + RFIFO_STRING(fd, 6, account_name, 24); PRINTF("parse_login: connection #%d, packet: 0x%x (with being read: %zu), account: %s.\n", fd, RFIFOW(fd, 0), RFIFOREST(fd), - static_cast(RFIFOP(fd, 6))); + account_name); + } } else if (RFIFOW(fd, 0) == 0x2710) { if (RFIFOREST(fd) >= 86) + { + char server_name[16]; + RFIFO_STRING(fd, 60, server_name, 16); PRINTF("parse_login: connection #%d, packet: 0x%x (with being read: %zu), server: %s.\n", fd, RFIFOW(fd, 0), RFIFOREST(fd), - static_cast(RFIFOP(fd, 60))); + server_name); + } } else PRINTF("parse_login: connection #%d, packet: 0x%x (with being read: %zu).\n", @@ -2939,9 +2957,9 @@ void parse_login(int fd) if (RFIFOREST(fd) < 55) return; - strzcpy(account.userid, static_cast(RFIFOP(fd, 6)), 24); + RFIFO_STRING(fd, 6, account.userid, 24); remove_control_chars(account.userid); - strzcpy(account.passwd, static_cast(RFIFOP(fd, 30)), 24); + RFIFO_STRING(fd, 30, account.passwd, 24); remove_control_chars(account.passwd); account.passwdenc = 0; @@ -3007,7 +3025,7 @@ void parse_login(int fd) size_t host_len = strlen(update_host); if (host_len > 0) { - host_len++; + host_len++; WFIFOW(fd, 0) = 0x63; WFIFOW(fd, 2) = 4 + host_len; WFIFO_STRING(fd, 4, update_host, host_len); @@ -3073,7 +3091,7 @@ void parse_login(int fd) } else { - WFIFO_ZERO(fd, 0, 23); + WFIFO_ZERO(fd, 0, 23); WFIFOW(fd, 0) = 0x6a; WFIFOB(fd, 2) = result; if (result == 6) @@ -3143,12 +3161,12 @@ void parse_login(int fd) { int len; char server_name[20]; - strzcpy(account.userid, static_cast(RFIFOP(fd, 2)), 24); + RFIFO_STRING(fd, 2, account.userid, 24); remove_control_chars(account.userid); - strzcpy(account.passwd, static_cast(RFIFOP(fd, 26)), 24); + RFIFO_STRING(fd, 26, account.passwd, 24); remove_control_chars(account.passwd); account.passwdenc = 0; - strzcpy(server_name, static_cast(RFIFOP(fd, 60)), 20); + RFIFO_STRING(fd, 60, server_name, 20); remove_control_chars(server_name); LOGIN_LOG("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)\n", server_name, RFIFOB(fd, 54), RFIFOB(fd, 55), @@ -3265,7 +3283,7 @@ void parse_login(int fd) { // non encrypted password char password[24]; - strzcpy(password, static_cast(RFIFOP(fd, 4)), 24); + RFIFO_STRING(fd, 4, password, 24); remove_control_chars(password); // If remote administration is enabled and password sent by client matches password read from login server configuration file if ((admin_state == 1) @@ -3294,18 +3312,18 @@ void parse_login(int fd) uint8_t md5bin[32]; if (RFIFOW(fd, 2) == 1) { - strncpy(md5str, ld->md5key, sizeof(ld->md5key)); // 20 + strcpy(md5str, ld->md5key); // 20 strcat(md5str, admin_pass); // 24 } else if (RFIFOW(fd, 2) == 2) { - strncpy(md5str, admin_pass, sizeof(admin_pass)); // 24 + strcpy(md5str, admin_pass); // 24 strcat(md5str, ld->md5key); // 20 } MD5_to_bin(MD5_from_cstring(md5str), md5bin); // If remote administration is enabled and password hash sent by client matches hash of password read from login server configuration file if ((admin_state == 1) - && (memcmp(md5bin, RFIFOP(fd, 4), 16) == 0)) + && really_memequal(md5bin, static_cast(RFIFOP(fd, 4)), 16)) { LOGIN_LOG("'ladmin'-login: Connection in administration mode accepted (encrypted password, ip: %s)\n", ip); @@ -3346,7 +3364,7 @@ void parse_login(int fd) FPRINTF(logfp, "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F\n"); - char tmpstr[16 + 1] {}; + char tmpstr[16 + 1] {}; int i; for (i = 0; i < RFIFOREST(fd); i++) @@ -3363,7 +3381,7 @@ void parse_login(int fd) else if ((i + 1) % 16 == 0) { FPRINTF(logfp, " %s\n", tmpstr); - strzcpy(tmpstr, "", 16 + 1); + strzcpy(tmpstr, "", 16 + 1); } } if (i % 16 != 0) @@ -3397,7 +3415,7 @@ int login_lan_config_read(const char *lancfgName) struct hostent *h = NULL; // set default configuration - strncpy(lan_char_ip, "127.0.0.1", sizeof(lan_char_ip)); + strcpy(lan_char_ip, "127.0.0.1"); subneti[0] = 127; subneti[1] = 0; subneti[2] = 0; diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 8e29f86..f893c2e 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include "../common/core.hpp" #include "../common/cxxstdio.hpp" #include "../common/mmo.hpp" @@ -432,14 +434,15 @@ bool is_atcommand(const int fd, dumb_ptr sd, } { - char command[100] {}; const char *str = message; const char *p = message; + // split the first word while (*p && !isspace(*p)) p++; - if (p - str >= sizeof(command)) // too long - return true; - strncpy(command, str, p - str); + size_t len = p - str; + char command[len + 1]; + strzcpy(command, str, len + 1); + // skip the spaces; pass as argv while (isspace(*p)) p++; @@ -447,7 +450,8 @@ bool is_atcommand(const int fd, dumb_ptr sd, if (info->proc(fd, sd, command, p) != 0) { // Command can not be executed - std::string output = STRPRINTF("%s failed.", command); + const char *command_ = command; + std::string output = STRPRINTF("%s failed.", command_); clif_displaymessage(fd, output); } else @@ -1773,33 +1777,20 @@ int atcommand_joblevelup(const int fd, dumb_ptr sd, int atcommand_help(const int fd, dumb_ptr sd, const char *, const char *) { - char buf[2048] {}; - int i, gm_level; - FILE *fp; - - if ((fp = fopen_(help_txt, "r")) != NULL) + std::ifstream in(help_txt); + if (in.is_open()) { clif_displaymessage(fd, "Help commands:"); - gm_level = pc_isGM(sd); - while (fgets(buf, sizeof(buf) - 1, fp) != NULL) + int gm_level = pc_isGM(sd); + std::string line; + while (std::getline(in, line)) { - if (buf[0] == '/' && buf[1] == '/') + std::string w1, w2; + if (!split_key_value(line, &w1, &w2)) continue; - for (i = 0; buf[i] != '\0'; i++) - { - if (buf[i] == '\r' || buf[i] == '\n') - { - buf[i] = '\0'; - break; - } - } - char w1[2048], w2[2048]; - if (sscanf(buf, "%2047[^:]:%2047[^\n]", w1, w2) < 2) - clif_displaymessage(fd, buf); - else if (gm_level >= atoi(w1)) + if (gm_level >= atoi(w1.c_str())) clif_displaymessage(fd, w2); } - fclose_(fp); } else { diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp index f2d5ec7..a1e0f55 100644 --- a/src/map/chrif.cpp +++ b/src/map/chrif.cpp @@ -22,7 +22,8 @@ #include "../poison.hpp" static -const int packet_len_table[0x20] = { +const int packet_len_table[0x20] = +{ 60, 3, 10, 27, 22, -1, 6, -1, // 2af8-2aff 6, -1, 18, 7, -1, 49, 44, 0, // 2b00-2b07 6, 30, -1, 10, 86, 7, 44, 34, // 2b08-2b0f @@ -179,9 +180,9 @@ int chrif_recvmap(int fd) port = RFIFOW(fd, 8); for (i = 10, j = 0; i < RFIFOW(fd, 2); i += 16, j++) { - map_setipport(static_cast(RFIFOP(fd, i)), ip, port); -// if (battle_config.etc_log) -// PRINTF("recv map %d %s\n", j, RFIFOP(fd,i)); + char map[16]; + RFIFO_STRING(fd, i, map, 16); + map_setipport(map, ip, port); } if (battle_config.etc_log) PRINTF("recv map on %s:%d (%d maps)\n", ip2str(ip), port, j); @@ -244,8 +245,13 @@ int chrif_changemapserverack(int fd) pc_authfail(sd->fd); return 0; } - clif_changemapserver(sd, static_cast(RFIFOP(fd, 18)), RFIFOW(fd, 34), - RFIFOW(fd, 36), in_addr{RFIFOL(fd, 38)}, RFIFOW(fd, 42)); + char mapname[16]; + RFIFO_STRING(fd, 18, mapname, 16); + uint16_t x = RFIFOW(fd, 34); + uint16_t y = RFIFOW(fd, 36); + auto ip = in_addr{RFIFOL(fd, 38)}; + uint16_t port = RFIFOW(fd, 42); + clif_changemapserver(sd, mapname, x, y, ip, port); return 0; } @@ -887,7 +893,7 @@ int chrif_accountban(int fd) TimeT timestamp = static_cast(RFIFOL(fd, 7)); // status or final date of a banishment char tmpstr[] = WITH_TIMESTAMP("Your account has been banished until "); REPLACE_TIMESTAMP(tmpstr, timestamp); - clif_displaymessage(sd->fd, tmpstr); + clif_displaymessage(sd->fd, const_(tmpstr)); } clif_setwaitclose(sd->fd); // forced to disconnect for the change } @@ -1097,9 +1103,17 @@ void chrif_parse(int fd) chrif_sendmapack(fd); break; case 0x2afd: - pc_authok(RFIFOL(fd, 4), RFIFOL(fd, 8), - static_cast(RFIFOL(fd, 12)), RFIFOW(fd, 16), - static_cast(RFIFOP(fd, 18))); + { + int id = RFIFOL(fd, 4); + int login_id2 = RFIFOL(fd, 8); + TimeT connect_until_time = static_cast(RFIFOL(fd, 12)); + short tmw_version = RFIFOW(fd, 16); + struct mmo_charstatus st {}; + RFIFO_STRUCT(fd, 18, st); + pc_authok(id, login_id2, + connect_until_time, tmw_version, + &st); + } break; case 0x2afe: pc_authfail(RFIFOL(fd, 2)); @@ -1117,7 +1131,12 @@ void chrif_parse(int fd) chrif_changemapserverack(fd); break; case 0x2b09: - map_addchariddb(RFIFOL(fd, 2), static_cast(RFIFOP(fd, 6))); + { + int charid = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + map_addchariddb(charid, name); + } break; case 0x2b0b: chrif_changedgm(fd); diff --git a/src/map/clif.cpp b/src/map/clif.cpp index c37916b..fab8932 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -248,15 +248,6 @@ void clif_send_sub(dumb_ptr bl, const unsigned char *buf, int len, if (session[sd->fd] != NULL) { - if (WFIFOP(sd->fd, 0) == buf) - { - PRINTF("WARNING: Invalid use of clif_send function\n"); - PRINTF(" Packet x%4x use a WFIFO of a player instead of to use a buffer.\n", - RBUFW(buf, 0)); - PRINTF(" Please correct your code.\n"); - // don't send to not move the pointer of the packet for next sessions in the loop - } - else { if (clif_parse_func_table[RBUFW(buf, 0)].len) { @@ -1261,15 +1252,15 @@ int clif_selllist(dumb_ptr sd) */ int clif_scriptmes(dumb_ptr sd, int npcid, const char *mes) { - int fd; - nullpo_ret(sd); - fd = sd->fd; + int fd = sd->fd; + + size_t len = strlen(mes) + 1; WFIFOW(fd, 0) = 0xb4; - WFIFOW(fd, 2) = strlen(mes) + 9; + WFIFOW(fd, 2) = len + 8; WFIFOL(fd, 4) = npcid; - strcpy(static_cast(WFIFOP(fd, 8)), mes); + WFIFO_STRING(fd, 8, mes, len); WFIFOSET(fd, WFIFOW(fd, 2)); return 0; @@ -1317,15 +1308,14 @@ int clif_scriptclose(dumb_ptr sd, int npcid) */ int clif_scriptmenu(dumb_ptr sd, int npcid, const char *mes) { - int fd; - nullpo_ret(sd); - fd = sd->fd; + int fd = sd->fd; + size_t len = strlen(mes) + 1; WFIFOW(fd, 0) = 0xb7; - WFIFOW(fd, 2) = strlen(mes) + 8; + WFIFOW(fd, 2) = len + 8; WFIFOL(fd, 4) = npcid; - strcpy(static_cast(WFIFOP(fd, 8)), mes); + WFIFO_STRING(fd, 8, mes, len); WFIFOSET(fd, WFIFOW(fd, 2)); return 0; @@ -2275,13 +2265,11 @@ int clif_useitemack(dumb_ptr sd, int index, int amount, */ int clif_traderequest(dumb_ptr sd, const char *name) { - int fd; - nullpo_ret(sd); - fd = sd->fd; + int fd = sd->fd; WFIFOW(fd, 0) = 0xe5; - strcpy(static_cast(WFIFOP(fd, 2)), name); + WFIFO_STRING(fd, 2, name, 24); WFIFOSET(fd, clif_parse_func_table[0xe5].len); return 0; @@ -2608,16 +2596,17 @@ void clif_getareachar_pc(dumb_ptr sd, nullpo_retv(sd); nullpo_retv(dstsd); + uint8_t buf[256]; if (dstsd->walktimer) { - len = clif_set007b(dstsd, static_cast(WFIFOP(sd->fd, 0))); - WFIFOSET(sd->fd, len); + len = clif_set007b(dstsd, buf); } else { - len = clif_set0078(dstsd, static_cast(WFIFOP(sd->fd, 0))); - WFIFOSET(sd->fd, len); + len = clif_set0078(dstsd, buf); } + WFIFO_BUF_CLONE(sd->fd, buf, len); + WFIFOSET(sd->fd, len); if (battle_config.save_clothcolor == 1 && dstsd->status.clothes_color > 0) clif_changelook(dstsd, LOOK::CLOTHES_COLOR, @@ -3137,7 +3126,7 @@ int clif_status_change(dumb_ptr bl, StatusChange type, int flag) * Send message (modified by [Yor]) *------------------------------------------ */ -void clif_displaymessage(int fd, const_string mes) +void clif_displaymessage(int fd, ZString mes) { if (mes) { @@ -3145,7 +3134,7 @@ void clif_displaymessage(int fd, const_string mes) WFIFOW(fd, 0) = 0x8e; size_t str_len = mes.size() + 1; // NUL (might not be NUL yet) WFIFOW(fd, 2) = 4 + str_len; - WFIFO_STRING(fd, 4, mes.data(), str_len); + WFIFO_STRING(fd, 4, mes.c_str(), str_len); WFIFOSET(fd, 4 + str_len); } } @@ -3154,14 +3143,14 @@ void clif_displaymessage(int fd, const_string mes) * 天の声を送信する *------------------------------------------ */ -void clif_GMmessage(dumb_ptr bl, const_string mes, int flag) +void clif_GMmessage(dumb_ptr bl, ZString mes, int flag) { size_t str_len = mes.size() + 1; unsigned char buf[str_len + 4]; WBUFW(buf, 0) = 0x9a; WBUFW(buf, 2) = str_len + 4; - WBUF_STRING(buf, 4, mes.data(), str_len); + WBUF_STRING(buf, 4, mes.c_str(), str_len); flag &= 0x07; clif_send(buf, WBUFW(buf, 2), bl, (flag == 1) ? SendWho::ALL_SAMEMAP : @@ -4689,16 +4678,9 @@ void clif_parse_NpcStringInput(int fd, dumb_ptr sd) */ if (len < 0) return; - - if (len >= sizeof(sd->npc_str) - 1) - { - PRINTF("clif_parse_NpcStringInput(): Input string too long!\n"); - len = sizeof(sd->npc_str) - 1; - } - - if (len > 0) - strncpy(sd->npc_str, static_cast(RFIFOP(fd, 8)), len); - sd->npc_str[len] = '\0'; + char buf[len]; + RFIFO_STRING(fd, 8, buf, len); + sd->npc_str = buf; map_scriptcont(sd, RFIFOL(fd, 4)); } @@ -4783,7 +4765,9 @@ void clif_parse_CreateParty(int fd, dumb_ptr sd) if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, SkillID::NV_PARTY) >= 2) { - party_create(sd, static_cast(RFIFOP(fd, 2))); + char name[24]; + RFIFO_STRING(fd, 2, name, 24); + party_create(sd, name); } else clif_skill_fail(sd, SkillID::ONE, 0, 4); @@ -4841,7 +4825,10 @@ void clif_parse_LeaveParty(int, dumb_ptr sd) static void clif_parse_RemovePartyMember(int fd, dumb_ptr sd) { - party_removemember(sd, RFIFOL(fd, 2), static_cast(RFIFOP(fd, 6))); + int account_id = RFIFOL(fd, 2); + char name[24]; + RFIFO_STRING(fd, 6, name, 24); + party_removemember(sd, account_id, name); } /*========================================== @@ -5584,14 +5571,16 @@ std::string clif_validate_chat(dumb_ptr sd, ChatType type) return std::string(); } - const char *p = static_cast(RFIFOP(fd, 4)); + size_t pstart = 4; size_t buf_len = msg_len; if (type == ChatType::Whisper) { - p += 24; + pstart += 24; buf_len -= 24; } - const char *pend = p + buf_len; + char pbuf[buf_len + 1]; + // I had to change strzcpy for this :( + RFIFO_STRING(fd, pstart, pbuf, buf_len + 1); /* * The client attempted to exceed the maximum message length. @@ -5608,8 +5597,8 @@ std::string clif_validate_chat(dumb_ptr sd, ChatType type) if (type == ChatType::Global) { - const char *pos = strstr(p, " : "); - if (!pos || pos != p + name_len || memcmp(p, sd->status.name, name_len)) + XString p = ZString(ZString::really_construct_from_a_pointer, pbuf); + if (!(p.startswith(const_(sd->status.name)) && p.xslice_t(name_len).startswith(" : "))) { /* Disallow malformed/spoofed messages. */ clif_setwaitclose(fd); @@ -5617,12 +5606,10 @@ std::string clif_validate_chat(dumb_ptr sd, ChatType type) return std::string(); } /* Step beyond the separator. */ - p = pos + 3; + XString xs = p.xslice_t(name_len + 3); + return std::string(xs.begin(), xs.end()); } - - std::string buf(p, pend); - - return buf; + return pbuf; } /*========================================== diff --git a/src/map/clif.hpp b/src/map/clif.hpp index 5d48bc5..b9e2233 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -6,6 +6,7 @@ #include #include "../common/const_array.hpp" +#include "../common/strings.hpp" #include "../common/timer.t.hpp" #include "battle.t.hpp" @@ -146,8 +147,8 @@ int clif_party_xy(struct party *p, dumb_ptr sd); int clif_party_hp(struct party *p, dumb_ptr sd); // atcommand -void clif_displaymessage(int fd, const_string mes); -void clif_GMmessage(dumb_ptr bl, const_string mes, int flag); +void clif_displaymessage(int fd, ZString mes); +void clif_GMmessage(dumb_ptr bl, ZString mes, int flag); void clif_resurrection(dumb_ptr bl, int type); int clif_specialeffect(dumb_ptr bl, int type, int flag); // special effects [Valaris] diff --git a/src/map/intif.cpp b/src/map/intif.cpp index 9e9d2e1..311c661 100644 --- a/src/map/intif.cpp +++ b/src/map/intif.cpp @@ -286,13 +286,16 @@ int intif_parse_WisEnd(int fd) { dumb_ptr sd; + char name[24]; + RFIFO_STRING(fd, 2, name, 24); + uint8_t flag = RFIFOB(fd, 26); if (battle_config.etc_log) // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target PRINTF("intif_parse_wisend: player: %s, flag: %d\n", - static_cast(RFIFOP(fd, 2)), RFIFOB(fd, 26)); - sd = map_nick2sd(static_cast(RFIFOP(fd, 2))); + name, flag); + sd = map_nick2sd(name); if (sd != NULL) - clif_wis_end(sd->fd, RFIFOB(fd, 26)); + clif_wis_end(sd->fd, flag); return 0; } @@ -414,8 +417,12 @@ void intif_parse_PartyCreated(int fd) { if (battle_config.etc_log) PRINTF("intif: party created\n"); - party_created(RFIFOL(fd, 2), RFIFOB(fd, 6), RFIFOL(fd, 7), - static_cast(RFIFOP(fd, 11))); + int account_id = RFIFOL(fd, 2); + int fail = RFIFOB(fd, 6); + int party_id = RFIFOL(fd, 7); + char name[24]; + RFIFO_STRING(fd, 11, name, 24); + party_created(account_id, fail, party_id, name); } // パーティ情報 @@ -438,7 +445,9 @@ void intif_parse_PartyInfo(int fd) RFIFOL(fd, 4), RFIFOW(fd, 2), sizeof(struct party) + 4); } - party_recv_info(static_cast(RFIFOP(fd, 4))); + party p {}; + RFIFO_STRUCT(fd, 4, p); + party_recv_info(&p); } // パーティ追加通知 @@ -463,10 +472,14 @@ void intif_parse_PartyOptionChanged(int fd) static void intif_parse_PartyMemberLeaved(int fd) { + int party_id = RFIFOL(fd, 2); + int account_id = RFIFOL(fd, 6); + char name[24]; + RFIFO_STRING(fd, 10, name, 24); if (battle_config.etc_log) - PRINTF("intif: party member leaved %d %d %s\n", RFIFOL(fd, 2), - RFIFOL(fd, 6), static_cast(RFIFOP(fd, 10))); - party_member_leaved(RFIFOL(fd, 2), RFIFOL(fd, 6), static_cast(RFIFOP(fd, 10))); + PRINTF("intif: party member leaved %d %d %s\n", + party_id, account_id, name); + party_member_leaved(party_id, account_id, name); } // パーティ解散通知 @@ -480,18 +493,19 @@ void intif_parse_PartyBroken(int fd) static void intif_parse_PartyMove(int fd) { -// if(battle_config.etc_log) -// PRINTF("intif: party move %d %d %s %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27)); - party_recv_movemap(RFIFOL(fd, 2), RFIFOL(fd, 6), static_cast(RFIFOP(fd, 10)), - RFIFOB(fd, 26), RFIFOW(fd, 27)); + int party_id = RFIFOL(fd, 2); + int account_id = RFIFOL(fd, 6); + char map[16]; + RFIFO_STRING(fd, 10, map, 16); + uint8_t online = RFIFOB(fd, 26); + uint16_t lv = RFIFOW(fd, 27); + party_recv_movemap(party_id, account_id, map, online, lv); } // パーティメッセージ static void intif_parse_PartyMessage(int fd) { -// if(battle_config.etc_log) -// PRINTF("intif_parse_PartyMessage: %s\n",RFIFOP(fd,12)); size_t len = RFIFOW(fd, 2) - 12; char buf[len]; RFIFO_STRING(fd, 12, buf, len); @@ -532,9 +546,11 @@ int intif_parse(int fd) switch (cmd) { case 0x3800: - clif_GMmessage(NULL, - const_string(static_cast(RFIFOP(fd, 4)), - (packet_len - 4) - 1), 0); + { + char mes[packet_len - 4]; + RFIFO_STRING(fd, 4, mes, packet_len - 4); + clif_GMmessage(NULL, ZString(ZString::really_construct_from_a_pointer, mes), 0); + } break; case 0x3801: intif_parse_WisMessage(fd); diff --git a/src/map/magic-interpreter-base.cpp b/src/map/magic-interpreter-base.cpp index e6c1f37..3d0c853 100644 --- a/src/map/magic-interpreter-base.cpp +++ b/src/map/magic-interpreter-base.cpp @@ -137,7 +137,7 @@ void magic_free_env(dumb_ptr env) } dumb_ptr spell_create_env(magic_conf_t *conf, dumb_ptr spell, - dumb_ptr caster, int spellpower, const_string param) + dumb_ptr caster, int spellpower, const_string param) { dumb_ptr env = alloc_env(conf); diff --git a/src/map/magic-interpreter-lexer.lpp b/src/map/magic-interpreter-lexer.lpp index c0a554b..a7c25e5 100644 --- a/src/map/magic-interpreter-lexer.lpp +++ b/src/map/magic-interpreter-lexer.lpp @@ -113,13 +113,13 @@ char *dst = &string[0]; while (*src && *src != '"') { - if (*src == '\\') - { - *dst++ = src[1]; - src += 2; - } - else - *dst++ = *src++; + if (*src == '\\') + { + *dst++ = src[1]; + src += 2; + } + else + *dst++ = *src++; } *dst = '\0'; /* terminate */ magic_frontend_lval.s = string; diff --git a/src/map/map.hpp b/src/map/map.hpp index 968bf43..cf52173 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -161,7 +161,7 @@ struct map_session_data : block_list, SessionData // but one should probably be replaced with a ScriptPointer ??? const ScriptBuffer *npc_script, *npc_scriptroot; std::vector npc_stackbuf; - char npc_str[256]; + std::string npc_str; struct { unsigned storage:1; diff --git a/src/map/mob.cpp b/src/map/mob.cpp index ffeb619..345f5a6 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -2313,7 +2313,6 @@ int mob_damage(dumb_ptr src, dumb_ptr md, int damage, int max_hp; tick_t tick = gettick(); dumb_ptr mvp_sd = NULL, second_sd = NULL, third_sd = NULL; - double tdmg; nullpo_ret(md); //srcはNULLで呼ばれる場合もあるので、他でチェック @@ -2455,8 +2454,6 @@ int mob_damage(dumb_ptr src, dumb_ptr md, int damage, // map外に消えた人は計算から除くので // overkill分は無いけどsumはmax_hpとは違う - tdmg = 0; - // snip a prelude loop, now merged std::sort(md->dmglogv.begin(), md->dmglogv.end(), diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 91331cb..ab6892a 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -205,8 +205,7 @@ int npc_event_doall_l(const char *name, int rid, int argc, argrec_t *args) int c = 0; char buf[64] = "::"; - strncpy(buf + 2, name, sizeof(buf)-3); - buf[sizeof(buf)-1] = '\0'; + strzcpy(buf + 2, name, 62); for (auto& pair : ev_db) npc_event_doall_sub(pair.first, &pair.second, &c, buf, rid, argc, args); return c; @@ -1624,10 +1623,8 @@ dumb_ptr npc_spawn_text(map_local *m, int x, int y, retval->bl_type = BL::NPC; retval->npc_subtype = NpcSubtype::MESSAGE; - strncpy(retval->name, name, 23); - strncpy(retval->exname, name, 23); - retval->name[15] = 0; - retval->exname[15] = 0; + strzcpy(retval->name, name, 24); + strzcpy(retval->exname, name, 24); if (message) retval->message = message; diff --git a/src/map/party.cpp b/src/map/party.cpp index de655d7..62493c8 100644 --- a/src/map/party.cpp +++ b/src/map/party.cpp @@ -65,8 +65,7 @@ int party_create(dumb_ptr sd, const char *name) char pname[24]; nullpo_ret(sd); - strncpy(pname, name, 24); - pname[23] = '\0'; + strzcpy(pname, name, 24); tmw_TrimStr(pname); /* The party name is empty/invalid. */ diff --git a/src/map/pc.cpp b/src/map/pc.cpp index be59c0b..6759deb 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include "../common/cxxstdio.hpp" #include "../common/random.hpp" #include "../common/nullpo.hpp" @@ -732,25 +734,16 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time, PRINTF("Connection accepted: Character '%s' (account: %d).\n", sd->status.name, sd->status.account_id); - // Message of the Dayの送信 + // TODO fix this to cache and use inotify { - char buf[256]; - FILE *fp; - if ((fp = fopen_(motd_txt, "r")) != NULL) + std::ifstream in(motd_txt); + if (in.is_open()) { - while (fgets(buf, sizeof(buf) - 1, fp) != NULL) + std::string buf; + while (std::getline(in, buf)) { - for (int i = 0; buf[i]; i++) - { - if (buf[i] == '\r' || buf[i] == '\n') - { - buf[i] = 0; - break; - } - } clif_displaymessage(sd->fd, buf); } - fclose_(fp); } } @@ -1447,9 +1440,9 @@ int pc_calcstatus(dumb_ptr sd, int first) return 0; } - if (memcmp(&b_skill, &sd->status.skill, sizeof(sd->status.skill)) + if (b_skill != sd->status.skill || b_attackrange != sd->attackrange) - clif_skillinfoblock(sd); // スキル送信 + clif_skillinfoblock(sd); if (b_speed != sd->speed) clif_updatestatus(sd, SP::SPEED); diff --git a/src/map/script.cpp b/src/map/script.cpp index 0e95904..8ba2ebc 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -1563,7 +1563,7 @@ void builtin_input(ScriptState *st) sd->state.menu_or_input = 0; if (postfix == '$') { - set_reg(sd, type, num, dumb_string::fake(sd->npc_str)); + set_reg(sd, type, num, dumb_string::fake(sd->npc_str.c_str())); } else { @@ -2795,7 +2795,7 @@ void builtin_announce(ScriptState *st) static void builtin_mapannounce_sub(dumb_ptr bl, dumb_string str, int flag) { - clif_GMmessage(bl, str.c_str(), flag | 3); + clif_GMmessage(bl, str, flag | 3); } static diff --git a/src/map/tmw.cpp b/src/map/tmw.cpp index 9929e59..7afe3ca 100644 --- a/src/map/tmw.cpp +++ b/src/map/tmw.cpp @@ -63,7 +63,7 @@ int tmw_CheckChatSpam(dumb_ptr sd, const char *message) if (tmw_CheckChatLameness(sd, message)) sd->chat_lines_in += battle_config.chat_lame_penalty; - strncpy(sd->chat_lastmsg, message, battle_config.chat_maxline); + strzcpy(sd->chat_lastmsg, message, battle_config.chat_maxline); if (sd->chat_lines_in >= battle_config.chat_spam_flood || sd->chat_total_repeats >= battle_config.chat_spam_flood) diff --git a/src/poison.hpp b/src/poison.hpp index 2a82a72..0a7cc57 100644 --- a/src/poison.hpp +++ b/src/poison.hpp @@ -74,3 +74,5 @@ #pragma GCC poison memcpy #pragma GCC poison memmove #pragma GCC poison memset +#pragma GCC poison memcmp +#pragma GCC poison strncpy // in favor of strzcpy diff --git a/src/tests/main.cpp b/src/tests/main.cpp new file mode 100644 index 0000000..96d7200 --- /dev/null +++ b/src/tests/main.cpp @@ -0,0 +1,7 @@ +#include + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} -- cgit v1.2.3-70-g09d2