fix(Core/Commands): limit .character deleted list results to 50 (#25779)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Andrew
2026-05-09 15:49:21 -03:00
committed by GitHub
parent c03fdf101a
commit 5df0282bae
5 changed files with 25 additions and 6 deletions

View File

@@ -404,7 +404,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_ONLINE, "SELECT name, account, map, zone FROM characters WHERE online > 0", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND deleteInfos_Name LIKE CONCAT('%%', ?, '%%')", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME_LIMIT, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND deleteInfos_Name LIKE CONCAT('%%', ?, '%%') LIMIT 51", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL LIMIT 51", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID, "SELECT guid FROM characters WHERE account = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_PINFO, "SELECT totaltime, level, money, account, race, class, map, zone, gender, health, playerFlags FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM character_banned WHERE guid = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH);

View File

@@ -332,6 +332,7 @@ enum CharacterDatabaseStatements : uint32
CHAR_SEL_CHAR_DEL_INFO_BY_GUID,
CHAR_SEL_CHAR_DEL_INFO_BY_NAME,
CHAR_SEL_CHAR_DEL_INFO_BY_NAME_LIMIT,
CHAR_SEL_CHAR_DEL_INFO,
CHAR_SEL_CHARS_BY_ACCOUNT_ID,

View File

@@ -1487,6 +1487,8 @@ enum AcoreStrings
// Pet delete command
LANG_PET_DELETE_NOT_FOUND = 35438,
LANG_PET_DELETE_SUCCESS = 35439
LANG_PET_DELETE_SUCCESS = 35439,
LANG_CHARACTER_DELETED_LIST_LIMIT = 35440
};
#endif

View File

@@ -99,14 +99,17 @@ public:
typedef std::list<DeletedInfo> DeletedInfoList;
static constexpr std::size_t MAX_DELETED_CHAR_RESULTS = 50;
/**
* Collects all GUIDs (and related info) from deleted characters which are still in the database.
*
* @param foundList a reference to an std::list which will be filled with info data
* @param searchString the search string which either contains a player GUID or a part fo the character-name
* @param searchString the search string which either contains a player GUID or a part of the character-name
* @param limitResults if true, caps results at MAX_DELETED_CHAR_RESULTS + 1 using a DB-level LIMIT
* @return returns false if there was a problem while selecting the characters (e.g. player name not normalizeable)
*/
static bool GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string searchString)
static bool GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string searchString, bool limitResults = false)
{
PreparedQueryResult result;
CharacterDatabasePreparedStatement* stmt = nullptr;
@@ -125,7 +128,8 @@ public:
if (!normalizePlayerName(searchString))
return false;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME);
CharacterDatabaseStatements nameStmt = limitResults ? CHAR_SEL_CHAR_DEL_INFO_BY_NAME_LIMIT : CHAR_SEL_CHAR_DEL_INFO_BY_NAME;
stmt = CharacterDatabase.GetPreparedStatement(nameStmt);
stmt->SetData(0, searchString);
result = CharacterDatabase.Query(stmt);
}
@@ -590,7 +594,7 @@ public:
if (needleStr)
needle.assign(*needleStr);
DeletedInfoList foundList;
if (!GetDeletedCharacterInfoList(foundList, needle))
if (!GetDeletedCharacterInfoList(foundList, needle, true))
return false;
// if no characters have been found, output a warning
@@ -600,8 +604,15 @@ public:
return false;
}
bool truncated = foundList.size() > MAX_DELETED_CHAR_RESULTS;
if (truncated)
foundList.resize(MAX_DELETED_CHAR_RESULTS);
HandleCharacterDeletedListHelper(foundList, handler);
if (truncated)
handler->SendSysMessage(LANG_CHARACTER_DELETED_LIST_LIMIT);
return true;
}