db: prepare safebox load bootstrap
Some checks failed
build / Linux asan (push) Has been cancelled
build / Linux release (push) Has been cancelled
build / FreeBSD build (push) Has been cancelled

This commit is contained in:
server
2026-04-14 11:47:33 +02:00
parent aa862d829d
commit 84ed35cbda

View File

@@ -40,6 +40,19 @@ int g_query_count[2];
namespace
{
bool PrepareClientPlayerStmt(CStmt& stmt, const char* query)
{
CAsyncSQL* sql = CDBManager::instance().GetDirectSQL(SQL_PLAYER);
if (!sql)
{
sys_err("player SQL handle is not initialized");
return false;
}
return stmt.Prepare(sql, query);
}
bool LoadSafeboxPasswordByAccountId(DWORD accountId, char* password, size_t passwordSize, bool* found)
{
char query[QUERY_MAX_LEN];
@@ -49,7 +62,7 @@ bool LoadSafeboxPasswordByAccountId(DWORD accountId, char* password, size_t pass
password[0] = '\0';
CStmt stmt;
if (!stmt.Prepare(CDBManager::instance().GetDirectSQL(SQL_PLAYER), query))
if (!PrepareClientPlayerStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_LONG, &accountId))
@@ -77,7 +90,7 @@ bool UpdateSafeboxPasswordByAccountId(DWORD accountId, const char* password)
snprintf(query, sizeof(query), "UPDATE safebox%s SET password = ? WHERE account_id = ?", GetTablePostfix());
CStmt stmt;
if (!stmt.Prepare(CDBManager::instance().GetDirectSQL(SQL_PLAYER), query))
if (!PrepareClientPlayerStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(password), SAFEBOX_PASSWORD_MAX_LEN))
@@ -97,6 +110,88 @@ bool MatchesSafeboxPassword(const char* storedPassword, const char* providedPass
return !strcmp("000000", providedPassword);
}
bool LoadSafeboxTableByAccountId(DWORD accountId, const char* providedPassword, bool isMall, TSafeboxTable* safebox, bool* wrongPassword)
{
char query[QUERY_MAX_LEN];
snprintf(query, sizeof(query), "SELECT account_id, size, password FROM safebox%s WHERE account_id = ?", GetTablePostfix());
DWORD loadedAccountId = 0;
DWORD loadedSize = 0;
char storedPassword[SAFEBOX_PASSWORD_MAX_LEN + 1] = {};
CStmt stmt;
if (!PrepareClientPlayerStmt(stmt, query))
return false;
*wrongPassword = false;
memset(safebox, 0, sizeof(TSafeboxTable));
if (!stmt.BindParam(MYSQL_TYPE_LONG, &accountId))
return false;
if (!stmt.BindResult(MYSQL_TYPE_LONG, &loadedAccountId))
return false;
if (!stmt.BindResult(MYSQL_TYPE_LONG, &loadedSize))
return false;
if (!stmt.BindResult(MYSQL_TYPE_STRING, storedPassword, sizeof(storedPassword)))
return false;
if (!stmt.Execute())
return false;
if (stmt.iRows == 0)
{
safebox->dwID = accountId;
*wrongPassword = strcmp("000000", providedPassword) != 0;
return true;
}
if (!stmt.Fetch())
return false;
if (((!storedPassword[0]) && strcmp("000000", providedPassword))
|| (storedPassword[0] && strcmp(storedPassword, providedPassword)))
{
*wrongPassword = true;
return true;
}
safebox->dwID = loadedAccountId == 0 ? accountId : loadedAccountId;
safebox->bSize = static_cast<BYTE>(loadedSize);
if (isMall)
{
safebox->bSize = 1;
sys_log(0, "MALL id[%u] size[%u]", safebox->dwID, safebox->bSize);
}
else
{
sys_log(0, "SAFEBOX id[%u] size[%u]", safebox->dwID, safebox->bSize);
}
return true;
}
void QueueSafeboxItemsLoad(CPeer* peer, CClientManager::ClientHandleInfo* info)
{
char query[512];
snprintf(query, sizeof(query),
"SELECT id, window+0, pos, count, vnum, socket0, socket1, socket2, "
"attrtype0, attrvalue0, "
"attrtype1, attrvalue1, "
"attrtype2, attrvalue2, "
"attrtype3, attrvalue3, "
"attrtype4, attrvalue4, "
"attrtype5, attrvalue5, "
"attrtype6, attrvalue6 "
"FROM item%s WHERE owner_id=%u AND window='%s'",
GetTablePostfix(), info->account_id, info->ip[0] == 0 ? "SAFEBOX" : "MALL");
CDBManager::instance().ReturnQuery(query, QID_SAFEBOX_LOAD, peer->GetHandle(), info);
}
void EncodeSafeboxPasswordChangeAnswer(CPeer* pkPeer, DWORD dwHandle, BYTE success)
{
pkPeer->EncodeHeader(DG::SAFEBOX_CHANGE_PASSWORD_ANSWER, dwHandle, sizeof(BYTE));
@@ -518,15 +613,29 @@ void CClientManager::QUERY_SAFEBOX_LOAD(CPeer * pkPeer, DWORD dwHandle, TSafebox
pi->ip[0] = bMall ? 1 : 0;
strlcpy(pi->login, packet->szLogin, sizeof(pi->login));
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery),
"SELECT account_id, size, password FROM safebox%s WHERE account_id=%u",
GetTablePostfix(), packet->dwID);
if (g_log)
sys_log(0, "GD::SAFEBOX_LOAD (handle: %d account.id %u is_mall %d)", dwHandle, packet->dwID, bMall ? 1 : 0);
CDBManager::instance().ReturnQuery(szQuery, QID_SAFEBOX_LOAD, pkPeer->GetHandle(), pi);
TSafeboxTable* safebox = new TSafeboxTable;
bool wrongPassword = false;
if (!LoadSafeboxTableByAccountId(packet->dwID, pi->safebox_password, bMall, safebox, &wrongPassword))
{
delete safebox;
delete pi;
return;
}
if (wrongPassword)
{
delete safebox;
delete pi;
pkPeer->EncodeHeader(DG::SAFEBOX_WRONG_PASSWORD, dwHandle, 0);
return;
}
pi->pSafebox = safebox;
QueueSafeboxItemsLoad(pkPeer, pi);
}
void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
@@ -534,94 +643,6 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * pi = (ClientHandleInfo *) qi->pvData;
DWORD dwHandle = pi->dwHandle;
// 여기에서 사용하는 account_index는 쿼리 순서를 말한다.
// 첫번째 패스워드 알아내기 위해 하는 쿼리가 0
// 두번째 실제 데이터를 얻어놓는 쿼리가 1
if (pi->account_index == 0)
{
char szSafeboxPassword[SAFEBOX_PASSWORD_MAX_LEN + 1];
strlcpy(szSafeboxPassword, pi->safebox_password, sizeof(szSafeboxPassword));
TSafeboxTable * pSafebox = new TSafeboxTable;
memset(pSafebox, 0, sizeof(TSafeboxTable));
SQLResult * res = msg->Get();
if (res->uiNumRows == 0)
{
if (strcmp("000000", szSafeboxPassword))
{
pkPeer->EncodeHeader(DG::SAFEBOX_WRONG_PASSWORD, dwHandle, 0);
delete pSafebox;
delete pi;
return;
}
}
else
{
MYSQL_ROW row = mysql_fetch_row(res->pSQLResult);
// 비밀번호가 틀리면..
if (((!row[2] || !*row[2]) && strcmp("000000", szSafeboxPassword)) ||
((row[2] && *row[2]) && strcmp(row[2], szSafeboxPassword)))
{
pkPeer->EncodeHeader(DG::SAFEBOX_WRONG_PASSWORD, dwHandle, 0);
delete pSafebox;
delete pi;
return;
}
if (!row[0])
pSafebox->dwID = 0;
else
str_to_number(pSafebox->dwID, row[0]);
if (!row[1])
pSafebox->bSize = 0;
else
str_to_number(pSafebox->bSize, row[1]);
/*
if (!row[3])
pSafebox->dwGold = 0;
else
pSafebox->dwGold = atoi(row[3]);
*/
if (pi->ip[0] == 1)
{
pSafebox->bSize = 1;
sys_log(0, "MALL id[%d] size[%d]", pSafebox->dwID, pSafebox->bSize);
}
else
sys_log(0, "SAFEBOX id[%d] size[%d]", pSafebox->dwID, pSafebox->bSize);
}
if (0 == pSafebox->dwID)
pSafebox->dwID = pi->account_id;
pi->pSafebox = pSafebox;
char szQuery[512];
snprintf(szQuery, sizeof(szQuery),
"SELECT id, window+0, pos, count, vnum, socket0, socket1, socket2, "
"attrtype0, attrvalue0, "
"attrtype1, attrvalue1, "
"attrtype2, attrvalue2, "
"attrtype3, attrvalue3, "
"attrtype4, attrvalue4, "
"attrtype5, attrvalue5, "
"attrtype6, attrvalue6 "
"FROM item%s WHERE owner_id=%d AND window='%s'",
GetTablePostfix(), pi->account_id, pi->ip[0] == 0 ? "SAFEBOX" : "MALL");
pi->account_index = 1;
CDBManager::instance().ReturnQuery(szQuery, QID_SAFEBOX_LOAD, pkPeer->GetHandle(), pi);
}
else
{
if (!pi->pSafebox)
{
sys_err("null safebox pointer!");
@@ -629,7 +650,6 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
return;
}
// 쿼리에 에러가 있었으므로 응답할 경우 창고가 비어있는 것 처럼
// 보이기 때문에 창고가 아얘 안열리는게 나음
if (!msg->Get()->pSQLResult)
@@ -848,7 +868,6 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
pkPeer->Encode(&s_items[0], sizeof(TPlayerItem) * s_items.size());
delete pi;
}
}
void CClientManager::QUERY_SAFEBOX_CHANGE_SIZE(CPeer * pkPeer, DWORD dwHandle, TSafeboxChangeSizePacket * p)