game: escape log query string fields
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 16:41:45 +02:00
parent 646e40eaf8
commit f4f2692ce3
2 changed files with 68 additions and 24 deletions

View File

@@ -8,8 +8,6 @@
#include "item.h" #include "item.h"
#include "locale_service.h" #include "locale_service.h"
static char __escape_hint[1024];
LogManager::LogManager() : m_bIsConnect(false) LogManager::LogManager() : m_bIsConnect(false)
{ {
} }
@@ -41,6 +39,18 @@ void LogManager::Query(const char * c_pszFormat, ...)
m_sql.AsyncQuery(szQuery); m_sql.AsyncQuery(szQuery);
} }
std::string LogManager::EscapeForQuery(const char* text)
{
if (!text || !*text)
return {};
const size_t text_length = strlen(text);
std::string escaped(text_length * 2 + 1, '\0');
const size_t escaped_length = m_sql.EscapeString(escaped.data(), escaped.size(), text, text_length);
escaped.resize(escaped_length);
return escaped;
}
bool LogManager::IsConnected() bool LogManager::IsConnected()
{ {
return m_bIsConnect; return m_bIsConnect;
@@ -48,10 +58,12 @@ bool LogManager::IsConnected()
void LogManager::ItemLog(DWORD dwPID, DWORD x, DWORD y, DWORD dwItemID, const char * c_pszText, const char * c_pszHint, const char * c_pszIP, DWORD dwVnum) void LogManager::ItemLog(DWORD dwPID, DWORD x, DWORD y, DWORD dwItemID, const char * c_pszText, const char * c_pszHint, const char * c_pszIP, DWORD dwVnum)
{ {
m_sql.EscapeString(__escape_hint, sizeof(__escape_hint), c_pszHint, strlen(c_pszHint)); const std::string how = EscapeForQuery(c_pszText);
const std::string hint = EscapeForQuery(c_pszHint);
const std::string ip = EscapeForQuery(c_pszIP);
Query("INSERT DELAYED INTO log%s (type, time, who, x, y, what, how, hint, ip, vnum) VALUES('ITEM', NOW(), %u, %u, %u, %u, '%s', '%s', '%s', %u)", Query("INSERT DELAYED INTO log%s (type, time, who, x, y, what, how, hint, ip, vnum) VALUES('ITEM', NOW(), %u, %u, %u, %u, '%s', '%s', '%s', %u)",
get_table_postfix(), dwPID, x, y, dwItemID, c_pszText, __escape_hint, c_pszIP, dwVnum); get_table_postfix(), dwPID, x, y, dwItemID, how.c_str(), hint.c_str(), ip.c_str(), dwVnum);
} }
void LogManager::ItemLog(LPCHARACTER ch, LPITEM item, const char * c_pszText, const char * c_pszHint) void LogManager::ItemLog(LPCHARACTER ch, LPITEM item, const char * c_pszText, const char * c_pszHint)
@@ -75,10 +87,12 @@ void LogManager::ItemLog(LPCHARACTER ch, int itemID, int itemVnum, const char *
void LogManager::CharLog(DWORD dwPID, DWORD x, DWORD y, DWORD dwValue, const char * c_pszText, const char * c_pszHint, const char * c_pszIP) void LogManager::CharLog(DWORD dwPID, DWORD x, DWORD y, DWORD dwValue, const char * c_pszText, const char * c_pszHint, const char * c_pszIP)
{ {
m_sql.EscapeString(__escape_hint, sizeof(__escape_hint), c_pszHint, strlen(c_pszHint)); const std::string how = EscapeForQuery(c_pszText);
const std::string hint = EscapeForQuery(c_pszHint);
const std::string ip = EscapeForQuery(c_pszIP);
Query("INSERT DELAYED INTO log%s (type, time, who, x, y, what, how, hint, ip) VALUES('CHARACTER', NOW(), %u, %u, %u, %u, '%s', '%s', '%s')", Query("INSERT DELAYED INTO log%s (type, time, who, x, y, what, how, hint, ip) VALUES('CHARACTER', NOW(), %u, %u, %u, %u, '%s', '%s', '%s')",
get_table_postfix(), dwPID, x, y, dwValue, c_pszText, __escape_hint, c_pszIP); get_table_postfix(), dwPID, x, y, dwValue, how.c_str(), hint.c_str(), ip.c_str());
} }
void LogManager::CharLog(LPCHARACTER ch, DWORD dw, const char * c_pszText, const char * c_pszHint) void LogManager::CharLog(LPCHARACTER ch, DWORD dw, const char * c_pszText, const char * c_pszHint)
@@ -108,9 +122,14 @@ void LogManager::MoneyLog(BYTE type, DWORD vnum, int gold)
void LogManager::HackLog(const char * c_pszHackName, const char * c_pszLogin, const char * c_pszName, const char * c_pszIP) void LogManager::HackLog(const char * c_pszHackName, const char * c_pszLogin, const char * c_pszName, const char * c_pszIP)
{ {
m_sql.EscapeString(__escape_hint, sizeof(__escape_hint), c_pszHackName, strlen(c_pszHackName)); const std::string why = EscapeForQuery(c_pszHackName);
const std::string login = EscapeForQuery(c_pszLogin);
const std::string name = EscapeForQuery(c_pszName);
const std::string ip = EscapeForQuery(c_pszIP);
const std::string server = EscapeForQuery(g_stHostname.c_str());
Query("INSERT INTO hack_log (time, login, name, ip, server, why) VALUES(NOW(), '%s', '%s', '%s', '%s', '%s')", c_pszLogin, c_pszName, c_pszIP, g_stHostname.c_str(), __escape_hint); Query("INSERT INTO hack_log (time, login, name, ip, server, why) VALUES(NOW(), '%s', '%s', '%s', '%s', '%s')",
login.c_str(), name.c_str(), ip.c_str(), server.c_str(), why.c_str());
} }
void LogManager::HackLog(const char * c_pszHackName, LPCHARACTER ch) void LogManager::HackLog(const char * c_pszHackName, LPCHARACTER ch)
@@ -126,7 +145,14 @@ void LogManager::HackLog(const char * c_pszHackName, LPCHARACTER ch)
void LogManager::HackCRCLog(const char * c_pszHackName, const char * c_pszLogin, const char * c_pszName, const char * c_pszIP, DWORD dwCRC) void LogManager::HackCRCLog(const char * c_pszHackName, const char * c_pszLogin, const char * c_pszName, const char * c_pszIP, DWORD dwCRC)
{ {
Query("INSERT INTO hack_crc_log (time, login, name, ip, server, why, crc) VALUES(NOW(), '%s', '%s', '%s', '%s', '%s', %u)", c_pszLogin, c_pszName, c_pszIP, g_stHostname.c_str(), c_pszHackName, dwCRC); const std::string why = EscapeForQuery(c_pszHackName);
const std::string login = EscapeForQuery(c_pszLogin);
const std::string name = EscapeForQuery(c_pszName);
const std::string ip = EscapeForQuery(c_pszIP);
const std::string server = EscapeForQuery(g_stHostname.c_str());
Query("INSERT INTO hack_crc_log (time, login, name, ip, server, why, crc) VALUES(NOW(), '%s', '%s', '%s', '%s', '%s', %u)",
login.c_str(), name.c_str(), ip.c_str(), server.c_str(), why.c_str(), dwCRC);
} }
void LogManager::GoldBarLog(DWORD dwPID, DWORD dwItemID, GOLDBAR_HOW eHow, const char* c_pszHint) void LogManager::GoldBarLog(DWORD dwPID, DWORD dwItemID, GOLDBAR_HOW eHow, const char* c_pszHint)
@@ -167,9 +193,11 @@ void LogManager::GoldBarLog(DWORD dwPID, DWORD dwItemID, GOLDBAR_HOW eHow, const
snprintf(szHow, sizeof(szHow), "''"); snprintf(szHow, sizeof(szHow), "''");
break; break;
} }
const std::string hint = EscapeForQuery(c_pszHint);
Query("INSERT DELAYED INTO goldlog%s (date, time, pid, what, how, hint) VALUES(CURDATE(), CURTIME(), %u, %u, %s, '%s')", Query("INSERT DELAYED INTO goldlog%s (date, time, pid, what, how, hint) VALUES(CURDATE(), CURTIME(), %u, %u, %s, '%s')",
get_table_postfix(), dwPID, dwItemID, szHow, c_pszHint); get_table_postfix(), dwPID, dwItemID, szHow, hint.c_str());
} }
void LogManager::CubeLog(DWORD dwPID, DWORD x, DWORD y, DWORD item_vnum, DWORD item_uid, int item_count, bool success) void LogManager::CubeLog(DWORD dwPID, DWORD x, DWORD y, DWORD item_vnum, DWORD item_uid, int item_count, bool success)
@@ -188,34 +216,41 @@ void LogManager::SpeedHackLog(DWORD pid, DWORD x, DWORD y, int hack_count)
void LogManager::ChangeNameLog(DWORD pid, const char *old_name, const char *new_name, const char *ip) void LogManager::ChangeNameLog(DWORD pid, const char *old_name, const char *new_name, const char *ip)
{ {
const std::string old_name_escaped = EscapeForQuery(old_name);
const std::string new_name_escaped = EscapeForQuery(new_name);
const std::string ip_escaped = EscapeForQuery(ip);
Query("INSERT DELAYED INTO change_name%s (pid, old_name, new_name, time, ip) " Query("INSERT DELAYED INTO change_name%s (pid, old_name, new_name, time, ip) "
"VALUES(%u, '%s', '%s', NOW(), '%s') ", "VALUES(%u, '%s', '%s', NOW(), '%s') ",
get_table_postfix(), pid, old_name, new_name, ip); get_table_postfix(), pid, old_name_escaped.c_str(), new_name_escaped.c_str(), ip_escaped.c_str());
} }
void LogManager::GMCommandLog(DWORD dwPID, const char* szName, const char* szIP, BYTE byChannel, const char* szCommand) void LogManager::GMCommandLog(DWORD dwPID, const char* szName, const char* szIP, BYTE byChannel, const char* szCommand)
{ {
m_sql.EscapeString(__escape_hint, sizeof(__escape_hint), szCommand, strlen(szCommand)); const std::string name = EscapeForQuery(szName);
const std::string ip = EscapeForQuery(szIP);
const std::string command = EscapeForQuery(szCommand);
Query("INSERT DELAYED INTO command_log%s (userid, server, ip, port, username, command, date ) " Query("INSERT DELAYED INTO command_log%s (userid, server, ip, port, username, command, date ) "
"VALUES(%u, 999, '%s', %u, '%s', '%s', NOW()) ", "VALUES(%u, 999, '%s', %u, '%s', '%s', NOW()) ",
get_table_postfix(), dwPID, szIP, byChannel, szName, __escape_hint); get_table_postfix(), dwPID, ip.c_str(), byChannel, name.c_str(), command.c_str());
} }
void LogManager::RefineLog(DWORD pid, const char* item_name, DWORD item_id, int item_refine_level, int is_success, const char* how) void LogManager::RefineLog(DWORD pid, const char* item_name, DWORD item_id, int item_refine_level, int is_success, const char* how)
{ {
m_sql.EscapeString(__escape_hint, sizeof(__escape_hint), item_name, strlen(item_name)); const std::string item_name_escaped = EscapeForQuery(item_name);
const std::string how_escaped = EscapeForQuery(how);
Query("INSERT INTO refinelog%s (pid, item_name, item_id, step, time, is_success, setType) VALUES(%u, '%s', %u, %d, NOW(), %d, '%s')", Query("INSERT INTO refinelog%s (pid, item_name, item_id, step, time, is_success, setType) VALUES(%u, '%s', %u, %d, NOW(), %d, '%s')",
get_table_postfix(), pid, __escape_hint, item_id, item_refine_level, is_success, how); get_table_postfix(), pid, item_name_escaped.c_str(), item_id, item_refine_level, is_success, how_escaped.c_str());
} }
void LogManager::ShoutLog(BYTE bChannel, BYTE bEmpire, const char * pszText) void LogManager::ShoutLog(BYTE bChannel, BYTE bEmpire, const char * pszText)
{ {
m_sql.EscapeString(__escape_hint, sizeof(__escape_hint), pszText, strlen(pszText)); const std::string text = EscapeForQuery(pszText);
Query("INSERT INTO shout_log%s VALUES(NOW(), %d, %d,'%s')", get_table_postfix(), bChannel, bEmpire, __escape_hint); Query("INSERT INTO shout_log%s VALUES(NOW(), %d, %d,'%s')", get_table_postfix(), bChannel, bEmpire, text.c_str());
} }
void LogManager::LevelLog(LPCHARACTER pChar, unsigned int level, unsigned int playhour) void LogManager::LevelLog(LPCHARACTER pChar, unsigned int level, unsigned int playhour)
@@ -229,20 +264,24 @@ void LogManager::LevelLog(LPCHARACTER pChar, unsigned int level, unsigned int pl
aid = pChar->GetDesc()->GetAccountTable().id; aid = pChar->GetDesc()->GetAccountTable().id;
} }
const std::string name = EscapeForQuery(pChar->GetName());
Query("REPLACE INTO levellog%s (name, level, time, account_id, pid, playtime) VALUES('%s', %u, NOW(), %u, %u, %d)", Query("REPLACE INTO levellog%s (name, level, time, account_id, pid, playtime) VALUES('%s', %u, NOW(), %u, %u, %d)",
get_table_postfix(), pChar->GetName(), level, aid, pChar->GetPlayerID(), playhour); get_table_postfix(), name.c_str(), level, aid, pChar->GetPlayerID(), playhour);
} }
else else
{ {
const std::string name = EscapeForQuery(pChar->GetName());
Query("REPLACE INTO levellog%s (name, level, time, playtime) VALUES('%s', %u, NOW(), %d)", Query("REPLACE INTO levellog%s (name, level, time, playtime) VALUES('%s', %u, NOW(), %d)",
get_table_postfix(), pChar->GetName(), level, playhour); get_table_postfix(), name.c_str(), level, playhour);
} }
} }
void LogManager::BootLog(const char * c_pszHostName, BYTE bChannel) void LogManager::BootLog(const char * c_pszHostName, BYTE bChannel)
{ {
const std::string host = EscapeForQuery(c_pszHostName);
Query("INSERT INTO bootlog (time, hostname, channel) VALUES(NOW(), '%s', %d)", Query("INSERT INTO bootlog (time, hostname, channel) VALUES(NOW(), '%s', %d)",
c_pszHostName, bChannel); host.c_str(), bChannel);
} }
void LogManager::FishLog(DWORD dwPID, int prob_idx, int fish_id, int fish_level, DWORD dwMiliseconds, DWORD dwVnum, DWORD dwValue) void LogManager::FishLog(DWORD dwPID, int prob_idx, int fish_id, int fish_level, DWORD dwMiliseconds, DWORD dwVnum, DWORD dwValue)
@@ -260,9 +299,11 @@ void LogManager::FishLog(DWORD dwPID, int prob_idx, int fish_id, int fish_level,
void LogManager::QuestRewardLog(const char * c_pszQuestName, DWORD dwPID, DWORD dwLevel, int iValue1, int iValue2) void LogManager::QuestRewardLog(const char * c_pszQuestName, DWORD dwPID, DWORD dwLevel, int iValue1, int iValue2)
{ {
const std::string quest_name = EscapeForQuery(c_pszQuestName);
Query("INSERT INTO quest_reward_log%s VALUES('%s',%u,%u,2,%u,%u,NOW())", Query("INSERT INTO quest_reward_log%s VALUES('%s',%u,%u,2,%u,%u,NOW())",
get_table_postfix(), get_table_postfix(),
c_pszQuestName, quest_name.c_str(),
dwPID, dwPID,
dwLevel, dwLevel,
iValue1, iValue1,
@@ -276,14 +317,17 @@ void LogManager::DetailLoginLog(bool isLogin, LPCHARACTER ch)
if (true == isLogin) if (true == isLogin)
{ {
const std::string ip = EscapeForQuery(ch->GetDesc()->GetHostName());
const std::string client_version = EscapeForQuery(ch->GetDesc()->GetClientVersion());
Query("INSERT INTO loginlog2(type, is_gm, login_time, channel, account_id, pid, ip, client_version) " Query("INSERT INTO loginlog2(type, is_gm, login_time, channel, account_id, pid, ip, client_version) "
"VALUES('INVALID', %s, NOW(), %d, %u, %u, inet_aton('%s'), '%s')", "VALUES('INVALID', %s, NOW(), %d, %u, %u, inet_aton('%s'), '%s')",
ch->IsGM() ? "'Y'" : "'N'", ch->IsGM() ? "'Y'" : "'N'",
g_bChannel, g_bChannel,
ch->GetDesc()->GetAccountTable().id, ch->GetDesc()->GetAccountTable().id,
ch->GetPlayerID(), ch->GetPlayerID(),
ch->GetDesc()->GetHostName(), ip.c_str(),
ch->GetDesc()->GetClientVersion()); client_version.c_str());
} }
else else
{ {
@@ -301,4 +345,3 @@ void LogManager::DragonSlayLog(DWORD dwGuildID, DWORD dwDragonVnum, DWORD dwStar
get_table_postfix(), get_table_postfix(),
dwGuildID, dwDragonVnum, dwStartTime, dwEndTime); dwGuildID, dwDragonVnum, dwStartTime, dwEndTime);
} }

View File

@@ -53,6 +53,7 @@ class LogManager : public singleton<LogManager>
private: private:
void Query(const char * c_pszFormat, ...); void Query(const char * c_pszFormat, ...);
std::string EscapeForQuery(const char* text);
CAsyncSQL m_sql; CAsyncSQL m_sql;
bool m_bIsConnect; bool m_bIsConnect;