diff options
-rw-r--r-- | sql/base/world_database.sql | 1 | ||||
-rw-r--r-- | sql/updates/9136_world_trinity_string.sql | 3 | ||||
-rw-r--r-- | src/server/game/Chat/Commands/Level3.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/Language.h | 3 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Tools/PlayerDump.cpp | 62 | ||||
-rw-r--r-- | src/server/game/Tools/PlayerDump.h | 5 |
7 files changed, 60 insertions, 23 deletions
diff --git a/sql/base/world_database.sql b/sql/base/world_database.sql index 106851769ee..15166e61d77 100644 --- a/sql/base/world_database.sql +++ b/sql/base/world_database.sql @@ -15409,6 +15409,7 @@ INSERT INTO `trinity_string` (`entry`,`content_default`,`content_loc1`,`content_ (1127, 'Talents of %s''s pet reset.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), (1128, '%d - |cffffffff|Htaxinode:%u|h[%s %s]|h|r (Map:%u X:%f Y:%f Z:%f)', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), (1129, '%d - %s %s (Map:%u X:%f Y:%f Z:%f)', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), +(1130, 'Can''t dump deleted characters, aborting.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), (1200, 'You try to view cinemitic %u but it doesn''t exist.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), (1201, 'You try to view movie %u but it doesn''t exist.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), (1300, 'Alliance', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), diff --git a/sql/updates/9136_world_trinity_string.sql b/sql/updates/9136_world_trinity_string.sql new file mode 100644 index 00000000000..b37310ef60e --- /dev/null +++ b/sql/updates/9136_world_trinity_string.sql @@ -0,0 +1,3 @@ +DELETE FROM `trinity_string` WHERE `entry`=1130; +INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES +(1130, 'Can''t dump deleted characters, aborting.'); diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp index 0d54e4f77ae..860718d4908 100644 --- a/src/server/game/Chat/Commands/Level3.cpp +++ b/src/server/game/Chat/Commands/Level3.cpp @@ -6574,6 +6574,10 @@ bool ChatHandler::HandlePDumpWriteCommand(const char *args) PSendSysMessage(LANG_FILE_OPEN_FAIL,file); SetSentErrorMessage(true); return false; + case DUMP_CHARACTER_DELETED: + PSendSysMessage(LANG_COMMAND_EXPORT_DELETED_CHAR); + SetSentErrorMessage(true); + return false; default: PSendSysMessage(LANG_COMMAND_EXPORT_FAILED); SetSentErrorMessage(true); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 54140cb3cde..91cd6e29310 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -792,7 +792,8 @@ enum TrinityStrings LANG_RESET_PET_TALENTS_ONLINE = 1127, LANG_TAXINODE_ENTRY_LIST_CHAT = 1128, LANG_TAXINODE_ENTRY_LIST_CONSOLE = 1129, - // Room for more level 3 1130-1199 not used + LANG_COMMAND_EXPORT_DELETED_CHAR = 1130, + // Room for more level 3 1131-1199 not used // Debug commands LANG_CINEMATIC_NOT_EXIST = 1200, diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp index 66dc2ddb3f6..94afaee6f0f 100644 --- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp @@ -530,8 +530,9 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket & recv_data) if (sLog.IsOutCharDump()) // optimize GetPlayerDump call { - std::string dump = PlayerDumpWriter().GetDump(GUID_LOPART(guid)); - sLog.outCharDump(dump.c_str(),GetAccountId(),GUID_LOPART(guid),name.c_str()); + std::string dump; + if (PlayerDumpWriter().GetDump(GUID_LOPART(guid), dump)) + sLog.outCharDump(dump.c_str(),GetAccountId(),GUID_LOPART(guid),name.c_str()); } Player::DeleteFromDB(guid, GetAccountId()); diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index 79b2ae0b1ff..edd5b295f5c 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -264,7 +264,7 @@ void StoreGUID(QueryResult_AutoPtr result,uint32 data,uint32 field, std::set<uin } // Writing - High-level functions -void PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type) +bool PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type) { GUIDs const* guids = NULL; char const* fieldname = NULL; @@ -282,7 +282,7 @@ void PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl // for guid set stop if set is empty if (guids && guids->empty()) - return; // nothing to do + return true; // nothing to do // setup for guids case start position GUIDs::const_iterator guids_itr; @@ -300,7 +300,7 @@ void PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT * FROM %s WHERE %s", tableFrom, wherestr.c_str()); if (!result) - return; + return true; do { @@ -315,6 +315,14 @@ void PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl StoreGUID(result,0,mails); // mail id collection (mail.id) case DTT_MAIL_ITEM: StoreGUID(result,1,items); break; // item guid collection (mail_items.item_guid) + case DTT_CHARACTER: + { + if (result->GetFieldCount() <= 67) // avoid crashes on next check + return true; + if (result->Fetch()[67].GetUInt32()) // characters.deleteInfos_Account - if filled error + return false; + break; + } default: break; } @@ -324,22 +332,24 @@ void PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl while (result->NextRow()); } while (guids && guids_itr != guids->end()); // not set case iterate single time, set case iterate for all guids + return true; } -std::string PlayerDumpWriter::GetDump(uint32 guid) +bool PlayerDumpWriter::GetDump(uint32 guid, std::string &dump) { - std::string dump; + dump = ""; dump += "IMPORTANT NOTE: THIS DUMPFILE IS MADE FOR USE WITH THE 'PDUMP' COMMAND ONLY - EITHER THROUGH INGAME CHAT OR ON CONSOLE!\n"; dump += "IMPORTANT NOTE: DO NOT apply it directly - it will irreversibly DAMAGE and CORRUPT your database! You have been warned!\n\n"; for (int i = 0; i < DUMP_TABLE_COUNT; ++i) - DumpTable(dump, guid, dumpTables[i].name, dumpTables[i].name, dumpTables[i].type); + if (!DumpTable(dump, guid, dumpTables[i].name, dumpTables[i].name, dumpTables[i].type)) + return false; // TODO: Add instance/group.. // TODO: Add a dump level option to skip some non-important tables - return dump; + return true; } DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, uint32 guid) @@ -348,16 +358,30 @@ DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, uint32 guid) if (!fout) return DUMP_FILE_OPEN_ERROR; - std::string dump = GetDump(guid); + DumpReturn ret = DUMP_SUCCESS; + std::string dump; + if (!GetDump(guid, dump)) + ret = DUMP_CHARACTER_DELETED; - fprintf(fout,"%s\n",dump.c_str()); + fprintf(fout, "%s\n", dump.c_str()); fclose(fout); - return DUMP_SUCCESS; + return ret; } // Reading - High-level functions #define ROLLBACK(DR) {CharacterDatabase.RollbackTransaction(); fclose(fin); return (DR);} +void fixNULLfields(std::string &line) +{ + std::string nullString("'NULL'"); + size_t pos = line.find(nullString); + while (pos != std::string::npos) + { + line.replace(pos, nullString.length(), "NULL"); + pos = line.find(nullString); + } +} + DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid) { uint32 charcount = accmgr.GetCharactersCount(account); @@ -495,13 +519,20 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE name = '%s'", name.c_str()); if (result) { - if (!changenth(line, 36, "1")) // characters.at_login set to "rename on login" + if (!changenth(line, 37, "1")) // characters.at_login set to "rename on login" ROLLBACK(DUMP_FILE_BROKEN); } } else if (!changenth(line, 3, name.c_str())) // characters.name ROLLBACK(DUMP_FILE_BROKEN); + const char null[5] = "NULL"; + if (!changenth(line, 68, null)) // characters.deleteInfos_Account + ROLLBACK(DUMP_FILE_BROKEN); + if (!changenth(line, 69, null)) // characters.deleteInfos_Name + ROLLBACK(DUMP_FILE_BROKEN); + if (!changenth(line, 70, null)) // characters.deleteDate + ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_INVENTORY: @@ -522,13 +553,6 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update if (!changenth(line, 2, newguid)) // item_instance.owner_guid update ROLLBACK(DUMP_FILE_BROKEN); - std::string vals = getnth(line,3); // item_instance.data get - if (!changetokGuid(vals, OBJECT_FIELD_GUID+1, items, objmgr.m_hiItemGuid)) - ROLLBACK(DUMP_FILE_BROKEN); // item_instance.data.OBJECT_FIELD_GUID update - if (!changetoknth(vals, ITEM_FIELD_OWNER+1, newguid)) - ROLLBACK(DUMP_FILE_BROKEN); // item_instance.data.ITEM_FIELD_OWNER update - if (!changenth(line, 3, vals.c_str())) // item_instance.data update - ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_GIFT: @@ -603,6 +627,8 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s break; } + fixNULLfields(line); + if (!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); } diff --git a/src/server/game/Tools/PlayerDump.h b/src/server/game/Tools/PlayerDump.h index fb74ca266dc..cdcfecec155 100644 --- a/src/server/game/Tools/PlayerDump.h +++ b/src/server/game/Tools/PlayerDump.h @@ -61,6 +61,7 @@ enum DumpReturn DUMP_TOO_MANY_CHARS, DUMP_UNEXPECTED_END, DUMP_FILE_BROKEN, + DUMP_CHARACTER_DELETED }; class PlayerDump @@ -74,12 +75,12 @@ class PlayerDumpWriter : public PlayerDump public: PlayerDumpWriter() {} - std::string GetDump(uint32 guid); + bool GetDump(uint32 guid, std::string& dump); DumpReturn WriteDump(const std::string& file, uint32 guid); private: typedef std::set<uint32> GUIDs; - void DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type); + bool DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type); std::string GenerateWhereStr(char const* field, GUIDs const& guids, GUIDs::const_iterator& itr); std::string GenerateWhereStr(char const* field, uint32 guid); |