/* * Copyright (C) 2008-2012 TrinityCore * * Copyright (C) 2008-2016 TrinityCore * Copyright (C) 2005-2009 MaNGOS */ /* ScriptData Name: account_commandscript %Complete: 100 Comment: All account related commands Category: commandscripts EndScriptData */ #include "ScriptMgr.h" #include "AccountMgr.h" #include "Chat.h" #include "Language.h" class account_commandscript : public CommandScript { public: account_commandscript() : CommandScript("account_commandscript") { } ChatCommand* GetCommands() const { static ChatCommand accountSetCommandTable[] = { { "addon", SEC_ADMINISTRATOR, true, &HandleAccountSetAddonCommand, "", NULL }, { "gmlevel", SEC_CONSOLE, true, &HandleAccountSetGmLevelCommand, "", NULL }, { "password", SEC_CONSOLE, true, &HandleAccountSetPasswordCommand, "", NULL }, { NULL, SEC_PLAYER, false, NULL, "", NULL } }; static ChatCommand accountCommandTable[] = { { "addon", SEC_MODERATOR, false, &HandleAccountAddonCommand, "", NULL }, { "create", SEC_CONSOLE, true, &HandleAccountCreateCommand, "", NULL }, { "delete", SEC_CONSOLE, true, &HandleAccountDeleteCommand, "", NULL }, { "onlinelist", SEC_CONSOLE, true, &HandleAccountOnlineListCommand, "", NULL }, { "lock", SEC_PLAYER, false, &HandleAccountLockCommand, "", NULL }, { "set", SEC_ADMINISTRATOR, true, NULL, "", accountSetCommandTable }, { "password", SEC_PLAYER, false, &HandleAccountPasswordCommand, "", NULL }, { "", SEC_PLAYER, false, &HandleAccountCommand, "", NULL }, { NULL, SEC_PLAYER, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { { "account", SEC_PLAYER, true, NULL, "", accountCommandTable }, { NULL, SEC_PLAYER, false, NULL, "", NULL } }; return commandTable; } static bool HandleAccountAddonCommand(ChatHandler* handler, char const* args) { if (!*args) { handler->SendSysMessage(LANG_CMD_SYNTAX); handler->SetSentErrorMessage(true); return false; } char* exp = strtok((char*)args, " "); uint32 accountId = handler->GetSession()->GetAccountId(); int expansion = atoi(exp); //get int anyway (0 if error) if (expansion < 0 || uint8(expansion) > sWorld->getIntConfig(CONFIG_EXPANSION)) { handler->SendSysMessage(LANG_IMPROPER_VALUE); handler->SetSentErrorMessage(true); return false; } PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_EXPANSION); stmt->setUInt8(0, uint8(expansion)); stmt->setUInt32(1, accountId); LoginDatabase.Execute(stmt); handler->PSendSysMessage(LANG_ACCOUNT_ADDON, expansion); return true; } /// Create an account static bool HandleAccountCreateCommand(ChatHandler* handler, char const* args) { if (!*args) return false; ///- %Parse the command line arguments char* accountName = strtok((char*)args, " "); char* password = strtok(NULL, " "); if (!accountName || !password) return false; AccountOpResult result = AccountMgr::CreateAccount(std::string(accountName), std::string(password)); switch (result) { case AOR_OK: handler->PSendSysMessage(LANG_ACCOUNT_CREATED, accountName); if (handler->GetSession()) { sLog->outDebug(LOG_FILTER_WARDEN, "Account: %d (IP: %s) Character:[%s] (GUID: %u) Change Password.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow()); } break; case AOR_NAME_TOO_LONG: handler->SendSysMessage(LANG_ACCOUNT_TOO_LONG); handler->SetSentErrorMessage(true); return false; case AOR_NAME_ALREDY_EXIST: handler->SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST); handler->SetSentErrorMessage(true); return false; case AOR_DB_INTERNAL_ERROR: handler->PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR, accountName); handler->SetSentErrorMessage(true); return false; default: handler->PSendSysMessage(LANG_ACCOUNT_NOT_CREATED, accountName); handler->SetSentErrorMessage(true); return false; } return true; } /// Delete a user account and all associated characters in this realm /// \todo This function has to be enhanced to respect the login/realm split (delete char, delete account chars in realm then delete account) static bool HandleAccountDeleteCommand(ChatHandler* handler, char const* args) { if (!*args) return false; ///- Get the account name from the command line char* account = strtok((char*)args, " "); if (!account) return false; std::string accountName = account; if (!AccountMgr::normalizeString(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } uint32 accountId = AccountMgr::GetId(accountName); if (!accountId) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } /// Commands not recommended call from chat, but support anyway /// can delete only for account with less security /// This is also reject self apply in fact if (handler->HasLowerSecurityAccount(NULL, accountId, true)) return false; AccountOpResult result = AccountMgr::DeleteAccount(accountId); switch (result) { case AOR_OK: handler->PSendSysMessage(LANG_ACCOUNT_DELETED, accountName.c_str()); break; case AOR_NAME_NOT_EXIST: handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; case AOR_DB_INTERNAL_ERROR: handler->PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR, accountName.c_str()); handler->SetSentErrorMessage(true); return false; default: handler->PSendSysMessage(LANG_ACCOUNT_NOT_DELETED, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } return true; } /// Display info on users currently in the realm static bool HandleAccountOnlineListCommand(ChatHandler* handler, char const* /*args*/) { ///- Get the list of accounts ID logged to the realm PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ONLINE); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) { handler->SendSysMessage(LANG_ACCOUNT_LIST_EMPTY); return true; } ///- Display the list of account/characters online handler->SendSysMessage(LANG_ACCOUNT_LIST_BAR_HEADER); handler->SendSysMessage(LANG_ACCOUNT_LIST_HEADER); handler->SendSysMessage(LANG_ACCOUNT_LIST_BAR); ///- Cycle through accounts do { Field* fieldsDB = result->Fetch(); std::string name = fieldsDB[0].GetString(); uint32 account = fieldsDB[1].GetUInt32(); ///- Get the username, last IP and GM level of each account // No SQL injection. account is uint32. stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO); stmt->setUInt32(0, account); PreparedQueryResult resultLogin = LoginDatabase.Query(stmt); if (resultLogin) { Field* fieldsLogin = resultLogin->Fetch(); handler->PSendSysMessage(LANG_ACCOUNT_LIST_LINE, fieldsLogin[0].GetCString(), name.c_str(), fieldsLogin[1].GetCString(), fieldsDB[2].GetUInt16(), fieldsDB[3].GetUInt16(), fieldsLogin[3].GetUInt8(), fieldsLogin[2].GetUInt8()); } else handler->PSendSysMessage(LANG_ACCOUNT_LIST_ERROR, name.c_str()); } while (result->NextRow()); handler->SendSysMessage(LANG_ACCOUNT_LIST_BAR); return true; } static bool HandleAccountLockCommand(ChatHandler* handler, char const* args) { if (!*args) { handler->SendSysMessage(LANG_USE_BOL); handler->SetSentErrorMessage(true); return false; } std::string param = (char*)args; if (!param.empty()) { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK); if (param == "on") { stmt->setBool(0, true); // locked handler->PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED); } else if (param == "off") { stmt->setBool(0, false); // unlocked handler->PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED); } stmt->setUInt32(1, handler->GetSession()->GetAccountId()); LoginDatabase.Execute(stmt); return true; } handler->SendSysMessage(LANG_USE_BOL); handler->SetSentErrorMessage(true); return false; } static bool HandleAccountPasswordCommand(ChatHandler* handler, char const* args) { if (!*args) { handler->SendSysMessage(LANG_CMD_SYNTAX); handler->SetSentErrorMessage(true); return false; } char* oldPassword = strtok((char*)args, " "); char* newPassword = strtok(NULL, " "); char* passwordConfirmation = strtok(NULL, " "); if (!oldPassword || !newPassword || !passwordConfirmation) { handler->SendSysMessage(LANG_CMD_SYNTAX); handler->SetSentErrorMessage(true); return false; } if (!AccountMgr::CheckPassword(handler->GetSession()->GetAccountId(), std::string(oldPassword))) { handler->SendSysMessage(LANG_COMMAND_WRONGOLDPASSWORD); handler->SetSentErrorMessage(true); return false; } if (strcmp(newPassword, passwordConfirmation) != 0) { handler->SendSysMessage(LANG_NEW_PASSWORDS_NOT_MATCH); handler->SetSentErrorMessage(true); return false; } AccountOpResult result = AccountMgr::ChangePassword(handler->GetSession()->GetAccountId(), std::string(newPassword)); switch (result) { case AOR_OK: handler->SendSysMessage(LANG_COMMAND_PASSWORD); break; case AOR_PASS_TOO_LONG: handler->SendSysMessage(LANG_PASSWORD_TOO_LONG); handler->SetSentErrorMessage(true); return false; default: handler->SendSysMessage(LANG_COMMAND_NOTCHANGEPASSWORD); handler->SetSentErrorMessage(true); return false; } return true; } static bool HandleAccountCommand(ChatHandler* handler, char const* /*args*/) { AccountTypes gmLevel = handler->GetSession()->GetSecurity(); handler->PSendSysMessage(LANG_ACCOUNT_LEVEL, uint32(gmLevel)); return true; } /// Set/Unset the expansion level for an account static bool HandleAccountSetAddonCommand(ChatHandler* handler, char const* args) { ///- Get the command line arguments char* account = strtok((char*)args, " "); char* exp = strtok(NULL, " "); if (!account) return false; std::string accountName; uint32 accountId; if (!exp) { Player* player = handler->getSelectedPlayer(); if (!player) return false; accountId = player->GetSession()->GetAccountId(); AccountMgr::GetName(accountId, accountName); exp = account; } else { ///- Convert Account name to Upper Format accountName = account; if (!AccountMgr::normalizeString(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } accountId = AccountMgr::GetId(accountName); if (!accountId) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } } // Let set addon state only for lesser (strong) security level // or to self account if (handler->GetSession() && handler->GetSession()->GetAccountId() != accountId && handler->HasLowerSecurityAccount(NULL, accountId, true)) return false; int expansion = atoi(exp); //get int anyway (0 if error) if (expansion < 0 || uint8(expansion) > sWorld->getIntConfig(CONFIG_EXPANSION)) return false; PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_EXPANSION); stmt->setUInt8(0, expansion); stmt->setUInt32(1, accountId); LoginDatabase.Execute(stmt); handler->PSendSysMessage(LANG_ACCOUNT_SETADDON, accountName.c_str(), accountId, expansion); return true; } static bool HandleAccountSetGmLevelCommand(ChatHandler* handler, char const* args) { if (!*args) return false; std::string targetAccountName; uint32 targetAccountId = 0; uint32 targetSecurity = 0; uint32 gm = 0; char* arg1 = strtok((char*)args, " "); char* arg2 = strtok(NULL, " "); char* arg3 = strtok(NULL, " "); bool isAccountNameGiven = true; if (arg1 && !arg3) { if (!handler->getSelectedPlayer()) return false; isAccountNameGiven = false; } // Check for second parameter if (!isAccountNameGiven && !arg2) return false; // Check for account if (isAccountNameGiven) { targetAccountName = arg1; if (!AccountMgr::normalizeString(targetAccountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, targetAccountName.c_str()); handler->SetSentErrorMessage(true); return false; } } // Check for invalid specified GM level. gm = (isAccountNameGiven) ? atoi(arg2) : atoi(arg1); if (gm > SEC_CONSOLE) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } // handler->getSession() == NULL only for console targetAccountId = (isAccountNameGiven) ? AccountMgr::GetId(targetAccountName) : handler->getSelectedPlayer()->GetSession()->GetAccountId(); int32 gmRealmID = (isAccountNameGiven) ? atoi(arg3) : atoi(arg2); uint32 playerSecurity; if (handler->GetSession()) playerSecurity = AccountMgr::GetSecurity(handler->GetSession()->GetAccountId(), gmRealmID); else playerSecurity = SEC_CONSOLE; // can set security level only for target with less security and to less security that we have // This is also reject self apply in fact targetSecurity = AccountMgr::GetSecurity(targetAccountId, gmRealmID); if (targetSecurity >= playerSecurity || gm >= playerSecurity) { handler->SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); handler->SetSentErrorMessage(true); return false; } // Check and abort if the target gm has a higher rank on one of the realms and the new realm is -1 if (gmRealmID == -1 && !AccountMgr::IsConsoleAccount(playerSecurity)) { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ACCESS_GMLEVEL_TEST); stmt->setUInt32(0, targetAccountId); stmt->setUInt8(1, uint8(gm)); PreparedQueryResult result = LoginDatabase.Query(stmt); if (result) { handler->SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); handler->SetSentErrorMessage(true); return false; } } // Check if provided realmID has a negative value other than -1 if (gmRealmID < -1) { handler->SendSysMessage(LANG_INVALID_REALMID); handler->SetSentErrorMessage(true); return false; } // If gmRealmID is -1, delete all values for the account id, else, insert values for the specific realmID PreparedStatement* stmt; if (gmRealmID == -1) { stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS); stmt->setUInt32(0, targetAccountId); } else { stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM); stmt->setUInt32(0, targetAccountId); stmt->setUInt32(1, realmID); } LoginDatabase.Execute(stmt); if (gm != 0) { stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_ACCESS); stmt->setUInt32(0, targetAccountId); stmt->setUInt8(1, uint8(gm)); stmt->setInt32(2, gmRealmID); LoginDatabase.Execute(stmt); } handler->PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm); return true; } /// Set password for account static bool HandleAccountSetPasswordCommand(ChatHandler* handler, char const* args) { if (!*args) return false; ///- Get the command line arguments char* account = strtok((char*)args, " "); char* password = strtok(NULL, " "); char* passwordConfirmation = strtok(NULL, " "); if (!account || !password || !passwordConfirmation) return false; std::string accountName = account; if (!AccountMgr::normalizeString(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } uint32 targetAccountId = AccountMgr::GetId(accountName); if (!targetAccountId) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } /// can set password only for target with less security /// This is also reject self apply in fact if (handler->HasLowerSecurityAccount(NULL, targetAccountId, true)) return false; if (strcmp(password, passwordConfirmation)) { handler->SendSysMessage(LANG_NEW_PASSWORDS_NOT_MATCH); handler->SetSentErrorMessage(true); return false; } AccountOpResult result = AccountMgr::ChangePassword(targetAccountId, password); switch (result) { case AOR_OK: handler->SendSysMessage(LANG_COMMAND_PASSWORD); break; case AOR_NAME_NOT_EXIST: handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; case AOR_PASS_TOO_LONG: handler->SendSysMessage(LANG_PASSWORD_TOO_LONG); handler->SetSentErrorMessage(true); return false; default: handler->SendSysMessage(LANG_COMMAND_NOTCHANGEPASSWORD); handler->SetSentErrorMessage(true); return false; } return true; } }; void AddSC_account_commandscript() { new account_commandscript(); }