From e5a63561bba9d09e5a88636f4982cdb2cf57a569 Mon Sep 17 00:00:00 2001 From: Haru Date: Sun, 17 Sep 2017 19:59:35 +0200 Subject: Correct an issue in the RODEX when MAX_SLOTS or MAX_ITEM_OPTIONS have custom values --- src/char/int_rodex.c | 148 ++++++++++++++++++++++++++++----------------------- 1 file changed, 80 insertions(+), 68 deletions(-) diff --git a/src/char/int_rodex.c b/src/char/int_rodex.c index 9e102b54d..8e49da1b9 100644 --- a/src/char/int_rodex.c +++ b/src/char/int_rodex.c @@ -46,7 +46,6 @@ static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64 int i, count = 0; struct rodex_message msg = { 0 }; struct SqlStmt *stmt; - struct SqlStmt *stmt_items; nullpo_retr(-1, mails); @@ -128,93 +127,106 @@ static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64 return -1; } - stmt_items = SQL->StmtMalloc(inter->sql_handle); - if (stmt_items == NULL) { - SQL->StmtFreeResult(stmt); - SQL->StmtFree(stmt); - return -1; - } - - // Read mails - while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) { + { struct item it = { 0 }; + StringBuf buf; + struct SqlStmt *stmt_items = SQL->StmtMalloc(inter->sql_handle); + + if (stmt_items == NULL) { + SQL->StmtFreeResult(stmt); + SQL->StmtFree(stmt); + return -1; + } + + StrBuf->Init(&buf); - if (msg.type & MAIL_TYPE_ITEM) { - if (SQL_ERROR == SQL->StmtPrepare(stmt_items, "SELECT `nameid`, `amount`, `equip`, `identify`," - "`refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `opt_idx0`, `opt_val0`," - "`opt_idx1`, `opt_val1`, `opt_idx2`, `opt_val2`, `opt_idx3`, `opt_val3`, `opt_idx4`, `opt_val4`," - "`expire_time`, `bound`, `unique_id`" - "FROM `%s` WHERE mail_id = '%"PRId64"' ORDER BY `mail_id` ASC", rodex_item_db, msg.id) - || SQL_ERROR == SQL->StmtExecute(stmt_items) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 0, SQLDT_SHORT, &it.nameid, sizeof it.nameid, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 1, SQLDT_SHORT, &it.amount, sizeof it.amount, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 2, SQLDT_UINT, &it.equip, sizeof it.equip, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 3, SQLDT_CHAR, &it.identify, sizeof it.identify, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 4, SQLDT_CHAR, &it.refine, sizeof it.refine, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 5, SQLDT_CHAR, &it.attribute, sizeof it.attribute, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 6, SQLDT_SHORT, &it.card[0], sizeof it.card[0], NULL, NULL) // FIXME: Build dynamically - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 7, SQLDT_SHORT, &it.card[1], sizeof it.card[1], NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 8, SQLDT_SHORT, &it.card[2], sizeof it.card[2], NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 9, SQLDT_SHORT, &it.card[3], sizeof it.card[3], NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 10, SQLDT_INT16, &it.option[0].index, sizeof it.option[0].index, NULL, NULL) // FIXME: Build dynamically - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 11, SQLDT_INT16, &it.option[0].value, sizeof it.option[0].value, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 12, SQLDT_INT16, &it.option[1].index, sizeof it.option[1].index, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 13, SQLDT_INT16, &it.option[1].value, sizeof it.option[1].value, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 14, SQLDT_INT16, &it.option[2].index, sizeof it.option[2].index, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 15, SQLDT_INT16, &it.option[2].value, sizeof it.option[2].value, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 16, SQLDT_INT16, &it.option[3].index, sizeof it.option[3].index, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 17, SQLDT_INT16, &it.option[3].value, sizeof it.option[3].value, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 18, SQLDT_INT16, &it.option[4].index, sizeof it.option[4].index, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 19, SQLDT_INT16, &it.option[4].value, sizeof it.option[4].value, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 20, SQLDT_UINT, &it.expire_time, sizeof it.expire_time, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 21, SQLDT_UCHAR, &it.bound, sizeof it.bound, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 22, SQLDT_UINT64, &it.unique_id, sizeof it.unique_id, NULL, NULL) + StrBuf->AppendStr(&buf, "SELECT `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); + for (i = 0; i < MAX_SLOTS; i++) { + StrBuf->Printf(&buf, ", `card%d`", i); + } + for (i = 0; i < MAX_ITEM_OPTIONS; i++) { + StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", i, i); + } + StrBuf->Printf(&buf, "FROM `%s` WHERE mail_id = ? ORDER BY `mail_id` ASC", rodex_item_db); + + if (SQL_ERROR == SQL->StmtPrepareStr(stmt_items, StrBuf->Value(&buf)) + || SQL_ERROR == SQL->StmtBindParam(stmt_items, 0, SQLDT_INT64, &msg.id, sizeof msg.id) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 0, SQLDT_SHORT, &it.nameid, sizeof it.nameid, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 1, SQLDT_SHORT, &it.amount, sizeof it.amount, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 2, SQLDT_UINT, &it.equip, sizeof it.equip, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 3, SQLDT_CHAR, &it.identify, sizeof it.identify, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 4, SQLDT_CHAR, &it.refine, sizeof it.refine, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 5, SQLDT_CHAR, &it.attribute, sizeof it.attribute, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 6, SQLDT_UINT, &it.expire_time, sizeof it.expire_time, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 7, SQLDT_UCHAR, &it.bound, sizeof it.bound, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 8, SQLDT_UINT64, &it.unique_id, sizeof it.unique_id, NULL, NULL) + ) { + SqlStmt_ShowDebug(stmt_items); + } + for (i = 0; i < MAX_SLOTS; i++) { + if (SQL_ERROR == SQL->StmtBindColumn(stmt_items, 9 + i, SQLDT_SHORT, &it.card[i], sizeof it.card[i], NULL, NULL)) + SqlStmt_ShowDebug(stmt_items); + } + for (i = 0; i < MAX_ITEM_OPTIONS; i++) { + if (SQL_ERROR == SQL->StmtBindColumn(stmt_items, 9 + MAX_SLOTS + i * 2, SQLDT_INT16, &it.option[i].index, sizeof it.option[i].index, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 10 + MAX_SLOTS + i * 2, SQLDT_INT16, &it.option[i].value, sizeof it.option[i].value, NULL, NULL) ) { SqlStmt_ShowDebug(stmt_items); } + } + + // Read mails + while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) { - for (i = 0; i < RODEX_MAX_ITEM && SQL_SUCCESS == SQL->StmtNextRow(stmt_items); ++i) { - msg.items[i].item = it; - msg.items_count++; + if (msg.type & MAIL_TYPE_ITEM) { + if (SQL_ERROR == SQL->StmtExecute(stmt_items)) { + SqlStmt_ShowDebug(stmt_items); + } + + for (i = 0; i < RODEX_MAX_ITEM && SQL_SUCCESS == SQL->StmtNextRow(stmt_items); ++i) { + msg.items[i].item = it; + msg.items_count++; + } } - } - if (msg.items_count == 0) { - msg.type &= ~MAIL_TYPE_ITEM; - } + if (msg.items_count == 0) { + msg.type &= ~MAIL_TYPE_ITEM; + } - if (msg.zeny == 0) { - msg.type &= ~MAIL_TYPE_ZENY; - } + if (msg.zeny == 0) { + msg.type &= ~MAIL_TYPE_ZENY; + } #if PACKETVER >= 20170419 - if (opentype == RODEX_OPENTYPE_UNSET) { - if (msg.receiver_id != 0) - msg.opentype = RODEX_OPENTYPE_MAIL; - else - msg.opentype = RODEX_OPENTYPE_ACCOUNT; - } else { - msg.opentype = opentype; - } + if (opentype == RODEX_OPENTYPE_UNSET) { + if (msg.receiver_id != 0) + msg.opentype = RODEX_OPENTYPE_MAIL; + else + msg.opentype = RODEX_OPENTYPE_ACCOUNT; + } else { + msg.opentype = opentype; + } #else - msg.opentype = opentype; + msg.opentype = opentype; #endif #if PACKETVER < 20160601 - // NPC Message Type isn't supported in old clients - msg.type &= ~MAIL_TYPE_NPC; + // NPC Message Type isn't supported in old clients + msg.type &= ~MAIL_TYPE_NPC; #endif - ++count; - VECTOR_ENSURE(*mails, 1, 1); - VECTOR_PUSH(*mails, msg); - memset(&msg, 0, sizeof(struct rodex_message)); + ++count; + VECTOR_ENSURE(*mails, 1, 1); + VECTOR_PUSH(*mails, msg); + memset(&msg, 0, sizeof(struct rodex_message)); + + SQL->StmtFreeResult(stmt_items); + } + StrBuf->Destroy(&buf); + SQL->StmtFree(stmt_items); } SQL->StmtFreeResult(stmt); - SQL->StmtFreeResult(stmt_items); - SQL->StmtFree(stmt); - SQL->StmtFree(stmt_items); ShowInfo("rodex load complete from DB - id: %d (total: %d)\n", char_id, count); return count; -- cgit v1.2.3-70-g09d2