/
white.sheikh
/
mangoszero-server
Обзор
Документация
Войти
/
white.sheikh
/
mangoszero-server
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/game/ChatCommands/AccountCommands.cpp
433 строки
13 KB
PargeLenis
Standardize Account Handling (#182)
30 янв 2023, 00:08
Не верифицирован
30 янв 2023, 00:08
0562367
Код
Авторство
О чём код?
/** * MaNGOS is a full featured server for World of Warcraft, supporting * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 * * Copyright (C) 2005-2023 MaNGOS <https://getmangos.eu> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * World of Warcraft, and all World of Warcraft or Warcraft art, images, * and lore are copyrighted by Blizzard Entertainment, Inc. */ /* * Account related commands */ #include "World.h" #include "Chat.h" #include "Language.h" #include "AccountMgr.h" /********************************************************************** CommandTable : accountCommandTable /***********************************************************************/ bool ChatHandler::HandleAccountCommand(char* args) { // let show subcommands at unexpected data in args if (*args) { return false; } AccountTypes gmlevel = GetAccessLevel(); PSendSysMessage(LANG_ACCOUNT_LEVEL, uint32(gmlevel)); return true; } bool ChatHandler::HandleAccountPasswordCommand(char* args) { // allow use from RA, but not from console (not have associated account id) if (!GetAccountId()) { SendSysMessage(LANG_RA_ONLY_COMMAND); SetSentErrorMessage(true); return false; } // allow or quoted string with possible spaces or literal without spaces char* old_pass = ExtractQuotedOrLiteralArg(&args); char* new_pass = ExtractQuotedOrLiteralArg(&args); char* new_pass_c = ExtractQuotedOrLiteralArg(&args); if (!old_pass || !new_pass || !new_pass_c) { return false; } std::string password_old = old_pass; std::string password_new = new_pass; std::string password_new_c = new_pass_c; if (password_new != password_new_c) { SendSysMessage(LANG_NEW_PASSWORDS_NOT_MATCH); SetSentErrorMessage(true); return false; } if (!sAccountMgr.CheckPassword(GetAccountId(), password_old)) { SendSysMessage(LANG_COMMAND_WRONGOLDPASSWORD); SetSentErrorMessage(true); return false; } AccountOpResult result = sAccountMgr.ChangePassword(GetAccountId(), password_new); switch (result) { case AOR_OK: SendSysMessage(LANG_COMMAND_PASSWORD); break; case AOR_PASS_TOO_LONG: SendSysMessage(LANG_PASSWORD_TOO_LONG); SetSentErrorMessage(true); return false; case AOR_NAME_NOT_EXIST: // not possible case, don't want get account name for output default: SendSysMessage(LANG_COMMAND_NOTCHANGEPASSWORD); SetSentErrorMessage(true); return false; } // OK, but avoid normal report for hide passwords, but log use command for anyone LogCommand(".account password *** *** ***"); SetSentErrorMessage(true); return false; } bool ChatHandler::HandleAccountLockCommand(char* args) { // allow use from RA, but not from console (not have associated account id) if (!GetAccountId()) { SendSysMessage(LANG_RA_ONLY_COMMAND); SetSentErrorMessage(true); return false; } bool value; if (!ExtractOnOff(&args, value)) { SendSysMessage(LANG_USE_BOL); SetSentErrorMessage(true); return false; } if (value) { LoginDatabase.PExecute("UPDATE `account` SET `locked` = '1' WHERE `id` = '%u'", GetAccountId()); PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED); } else { LoginDatabase.PExecute("UPDATE `account` SET `locked` = '0' WHERE `id` = '%u'", GetAccountId()); PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED); } return true; } /// Display info on users currently in the realm bool ChatHandler::HandleAccountOnlineListCommand(char* args) { uint32 limit; if (!ExtractOptUInt32(&args, limit, 100)) { return false; } ///- Get the list of accounts ID logged to the realm // 0 1 2 3 4 QueryResult* result = LoginDatabase.PQuery("SELECT `id`, `username`, `last_ip`, `gmlevel`, `expansion` FROM `account` WHERE `active_realm_id` = %u", realmID); return ShowAccountListHelper(result, &limit); } /// 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, delete account chars in realm then delete account bool ChatHandler::HandleAccountDeleteCommand(char* args) { if (!*args) { return false; } std::string account_name; uint32 account_id = ExtractAccountId(&args, &account_name); if (!account_id) { 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 (HasLowerSecurityAccount(NULL, account_id, true)) { return false; } AccountOpResult result = sAccountMgr.DeleteAccount(account_id); switch (result) { case AOR_OK: PSendSysMessage(LANG_ACCOUNT_DELETED, account_name.c_str()); break; case AOR_NAME_NOT_EXIST: PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, account_name.c_str()); SetSentErrorMessage(true); return false; case AOR_DB_INTERNAL_ERROR: PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR, account_name.c_str()); SetSentErrorMessage(true); return false; default: PSendSysMessage(LANG_ACCOUNT_NOT_DELETED, account_name.c_str()); SetSentErrorMessage(true); return false; } return true; } /// Create an account bool ChatHandler::HandleAccountCreateCommand(char* args) { ///- %Parse the command line arguments char* szAcc = ExtractQuotedOrLiteralArg(&args); char* szPassword = ExtractQuotedOrLiteralArg(&args); if (!szAcc || !szPassword) { return false; } // normalized in accmgr.CreateAccount std::string account_name = szAcc; std::string password = szPassword; AccountOpResult result; uint32 expansion = 0; if(ExtractUInt32(&args, expansion)) { // No point in assigning to result as it's never used on this side of the if/else branch sAccountMgr.CreateAccount(account_name, password, expansion); } else { result = sAccountMgr.CreateAccount(account_name, password); switch (result) { case AOR_OK: PSendSysMessage(LANG_ACCOUNT_CREATED, account_name.c_str()); break; case AOR_NAME_TOO_LONG: SendSysMessage(LANG_ACCOUNT_TOO_LONG); SetSentErrorMessage(true); return false; case AOR_NAME_ALREADY_EXIST: SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST); SetSentErrorMessage(true); return false; case AOR_DB_INTERNAL_ERROR: PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR, account_name.c_str()); SetSentErrorMessage(true); return false; default: PSendSysMessage(LANG_ACCOUNT_NOT_CREATED, account_name.c_str()); SetSentErrorMessage(true); return false; } } return true; } /// Output list of character for account bool ChatHandler::HandleAccountCharactersCommand(char* args) { ///- Get the command line arguments std::string account_name; Player* target = NULL; // only for triggering use targeted player account uint32 account_id = ExtractAccountId(&args, &account_name, &target); if (!account_id) { return false; } ///- Get the characters for account id QueryResult* result = CharacterDatabase.PQuery("SELECT `guid`, `name`, `race`, `class`, `level` FROM `characters` WHERE `account` = %u", account_id); return ShowPlayerListHelper(result); } /********************************************************************** CommandTable : accountSetCommandTable /***********************************************************************/ /// Set/Unset the expansion level for an account bool ChatHandler::HandleAccountSetAddonCommand(char* args) { ///- Get the command line arguments char* accountStr = ExtractOptNotLastArg(&args); std::string account_name; uint32 account_id = ExtractAccountId(&accountStr, &account_name); if (!account_id) { return false; } // Let set addon state only for lesser (strong) security level // or to self account if (GetAccountId() && GetAccountId() != account_id && HasLowerSecurityAccount(NULL, account_id, true)) { return false; } uint32 lev; if (!ExtractUInt32(&args, lev)) { return false; } // No SQL injection LoginDatabase.PExecute("UPDATE `account` SET `expansion` = '%u' WHERE `id` = '%u'", lev, account_id); PSendSysMessage(LANG_ACCOUNT_SETADDON, account_name.c_str(), account_id, lev); return true; } bool ChatHandler::HandleAccountSetGmLevelCommand(char* args) { char* accountStr = ExtractOptNotLastArg(&args); std::string targetAccountName; Player* targetPlayer = NULL; uint32 targetAccountId = ExtractAccountId(&accountStr, &targetAccountName, &targetPlayer); if (!targetAccountId) { return false; } /// only target player different from self allowed if (GetAccountId() == targetAccountId) { return false; } int32 gm; if (!ExtractInt32(&args, gm)) { return false; } if (gm < SEC_PLAYER || gm > SEC_ADMINISTRATOR) { SendSysMessage(LANG_BAD_VALUE); SetSentErrorMessage(true); return false; } /// can set security level only for target with less security and to less security that we have /// This will reject self apply by specify account name if (HasLowerSecurityAccount(NULL, targetAccountId, true)) { return false; } /// account can't set security to same or grater level, need more power GM or console AccountTypes plSecurity = GetAccessLevel(); if (AccountTypes(gm) >= plSecurity) { SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); SetSentErrorMessage(true); return false; } if (targetPlayer) { ChatHandler(targetPlayer).PSendSysMessage(LANG_YOURS_SECURITY_CHANGED, GetNameLink().c_str(), gm); targetPlayer->GetSession()->SetSecurity(AccountTypes(gm)); } PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm); LoginDatabase.PExecute("UPDATE `account` SET `gmlevel` = '%i' WHERE `id` = '%u'", gm, targetAccountId); return true; } /// Set password for account bool ChatHandler::HandleAccountSetPasswordCommand(char* args) { ///- Get the command line arguments std::string account_name; uint32 targetAccountId = ExtractAccountId(&args, &account_name); if (!targetAccountId) { return false; } // allow or quoted string with possible spaces or literal without spaces char* szPassword1 = ExtractQuotedOrLiteralArg(&args); char* szPassword2 = ExtractQuotedOrLiteralArg(&args); if (!szPassword1 || !szPassword2) { return false; } /// can set password only for target with less security /// This is also reject self apply in fact if (HasLowerSecurityAccount(NULL, targetAccountId, true)) { return false; } if (strcmp(szPassword1, szPassword2)) { SendSysMessage(LANG_NEW_PASSWORDS_NOT_MATCH); SetSentErrorMessage(true); return false; } AccountOpResult result = sAccountMgr.ChangePassword(targetAccountId, szPassword1); switch (result) { case AOR_OK: SendSysMessage(LANG_COMMAND_PASSWORD); break; case AOR_NAME_NOT_EXIST: PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, account_name.c_str()); SetSentErrorMessage(true); return false; case AOR_PASS_TOO_LONG: SendSysMessage(LANG_PASSWORD_TOO_LONG); SetSentErrorMessage(true); return false; default: SendSysMessage(LANG_COMMAND_NOTCHANGEPASSWORD); SetSentErrorMessage(true); return false; } // OK, but avoid normal report for hide passwords, but log use command for anyone char msg[100]; snprintf(msg, 100, ".account set password %s *** ***", account_name.c_str()); LogCommand(msg); SetSentErrorMessage(true); return false; }