aboutsummaryrefslogtreecommitdiff
path: root/src/trinitycore/CliRunnable.cpp
diff options
context:
space:
mode:
authormegamage <none@none>2008-12-24 11:18:01 -0600
committermegamage <none@none>2008-12-24 11:18:01 -0600
commit184b82abccfff95b18bed81ded1b5a7e98d2dbd3 (patch)
tree4329c771076612bc55e52febfb5f323a2f21007e /src/trinitycore/CliRunnable.cpp
parent3cb4e7c716b11f357b3265257c51e7b6cc5c36f9 (diff)
Backed out changeset: ad4f100c0a9d
--HG-- branch : trunk
Diffstat (limited to 'src/trinitycore/CliRunnable.cpp')
-rw-r--r--src/trinitycore/CliRunnable.cpp355
1 files changed, 355 insertions, 0 deletions
diff --git a/src/trinitycore/CliRunnable.cpp b/src/trinitycore/CliRunnable.cpp
new file mode 100644
index 00000000000..7fe2ab784a6
--- /dev/null
+++ b/src/trinitycore/CliRunnable.cpp
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ *
+ * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ *
+ * 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
+ */
+
+/// \addtogroup Trinityd
+/// @{
+/// \file
+
+#include "Common.h"
+#include "Language.h"
+#include "Log.h"
+#include "World.h"
+#include "ScriptCalls.h"
+#include "ObjectMgr.h"
+#include "WorldSession.h"
+#include "Config/ConfigEnv.h"
+#include "Util.h"
+#include "AccountMgr.h"
+#include "CliRunnable.h"
+#include "MapManager.h"
+#include "Player.h"
+#include "Chat.h"
+
+void utf8print(const char* str)
+{
+#if PLATFORM == PLATFORM_WINDOWS
+ wchar_t wtemp_buf[6000];
+ size_t wtemp_len = 6000-1;
+ if(!Utf8toWStr(str,strlen(str),wtemp_buf,wtemp_len))
+ return;
+
+ char temp_buf[6000];
+ CharToOemBuffW(&wtemp_buf[0],&temp_buf[0],wtemp_len+1);
+ printf(temp_buf);
+#else
+ printf(str);
+#endif
+}
+
+/// 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(const char* args)
+{
+ if(!*args)
+ return false;
+
+ ///- Get the account name from the command line
+ char *account_name_str=strtok ((char*)args," ");
+ if (!account_name_str)
+ return false;
+
+ std::string account_name = account_name_str;
+ if(!AccountMgr::normilizeString(account_name))
+ {
+ PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str());
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ uint32 account_id = accmgr.GetId(account_name);
+ if(!account_id)
+ {
+ PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str());
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ /// Commands not recommended call from chat, but support anyway
+ if(m_session)
+ {
+ uint32 targetSecurity = accmgr.GetSecurity(account_id);
+
+ /// can delete only for account with less security
+ /// This is also reject self apply in fact
+ if (targetSecurity >= m_session->GetSecurity())
+ {
+ SendSysMessage (LANG_YOURS_SECURITY_IS_LOW);
+ SetSentErrorMessage (true);
+ return false;
+ }
+ }
+
+ AccountOpResult result = accmgr.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;
+}
+
+bool ChatHandler::HandleCharacterDeleteCommand(const char* args)
+{
+ if(!*args)
+ return false;
+
+ char *character_name_str = strtok((char*)args," ");
+ if(!character_name_str)
+ return false;
+
+ std::string character_name = character_name_str;
+ if(!normalizePlayerName(character_name))
+ return false;
+
+ uint64 character_guid;
+ uint32 account_id;
+
+ Player *player = objmgr.GetPlayer(character_name.c_str());
+ if(player)
+ {
+ character_guid = player->GetGUID();
+ account_id = player->GetSession()->GetAccountId();
+ player->GetSession()->KickPlayer();
+ }
+ else
+ {
+ character_guid = objmgr.GetPlayerGUIDByName(character_name);
+ if(!character_guid)
+ {
+ PSendSysMessage(LANG_NO_PLAYER,character_name.c_str());
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ account_id = objmgr.GetPlayerAccountIdByGUID(character_guid);
+ }
+
+ std::string account_name;
+ accmgr.GetName (account_id,account_name);
+
+ Player::DeleteFromDB(character_guid, account_id, true);
+ PSendSysMessage(LANG_CHARACTER_DELETED,character_name.c_str(),GUID_LOPART(character_guid),account_name.c_str(), account_id);
+ return true;
+}
+
+/// Exit the realm
+bool ChatHandler::HandleServerExitCommand(const char* args)
+{
+ SendSysMessage(LANG_COMMAND_EXIT);
+ World::StopNow(SHUTDOWN_EXIT_CODE);
+ return true;
+}
+
+/// Display info on users currently in the realm
+bool ChatHandler::HandleAccountOnlineListCommand(const char* args)
+{
+ ///- Get the list of accounts ID logged to the realm
+ QueryResult *resultDB = CharacterDatabase.Query("SELECT name,account FROM characters WHERE online > 0");
+ if (!resultDB)
+ return true;
+
+ ///- Display the list of account/characters online
+ SendSysMessage("=====================================================================");
+ SendSysMessage(LANG_ACCOUNT_LIST_HEADER);
+ SendSysMessage("=====================================================================");
+
+ ///- Circle through accounts
+ do
+ {
+ Field *fieldsDB = resultDB->Fetch();
+ std::string name = fieldsDB[0].GetCppString();
+ uint32 account = fieldsDB[1].GetUInt32();
+
+ ///- Get the username, last IP and GM level of each account
+ // No SQL injection. account is uint32.
+ // 0 1 2 3
+ QueryResult *resultLogin = loginDatabase.PQuery("SELECT username, last_ip, gmlevel, expansion FROM account WHERE id = '%u'",account);
+
+ if(resultLogin)
+ {
+ Field *fieldsLogin = resultLogin->Fetch();
+ PSendSysMessage("|%15s| %20s | %15s |%4d|%5d|",
+ fieldsLogin[0].GetString(),name.c_str(),fieldsLogin[1].GetString(),fieldsLogin[2].GetUInt32(),fieldsLogin[3].GetUInt32());
+
+ delete resultLogin;
+ }
+ else
+ PSendSysMessage(LANG_ACCOUNT_LIST_ERROR,name.c_str());
+
+ }while(resultDB->NextRow());
+
+ delete resultDB;
+
+ SendSysMessage("=====================================================================");
+ return true;
+}
+
+/// Create an account
+bool ChatHandler::HandleAccountCreateCommand(const char* args)
+{
+ if(!*args)
+ return false;
+
+ ///- %Parse the command line arguments
+ char *szAcc = strtok((char*)args, " ");
+ char *szPassword = strtok(NULL, " ");
+ if(!szAcc || !szPassword)
+ return false;
+
+ // normilized in accmgr.CreateAccount
+ std::string account_name = szAcc;
+ std::string password = szPassword;
+
+ AccountOpResult result = accmgr.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_ALREDY_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;
+}
+
+/// Set the level of logging
+bool ChatHandler::HandleServerSetLogLevelCommand(const char *args)
+{
+ if(!*args)
+ return false;
+
+ char *NewLevel = strtok((char*)args, " ");
+ if (!NewLevel)
+ return false;
+
+ sLog.SetLogLevel(NewLevel);
+ return true;
+}
+
+/// @}
+
+#ifdef linux
+// Non-blocking keypress detector, when return pressed, return 1, else always return 0
+int kb_hit_return()
+{
+ struct timeval tv;
+ fd_set fds;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ FD_ZERO(&fds);
+ FD_SET(STDIN_FILENO, &fds);
+ select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
+ return FD_ISSET(STDIN_FILENO, &fds);
+}
+#endif
+
+/// %Thread start
+void CliRunnable::run()
+{
+ ///- Init new SQL thread for the world database (one connection call enough)
+ WorldDatabase.ThreadStart(); // let thread do safe mySQL requests
+
+ char commandbuf[256];
+
+ ///- Display the list of available CLI functions then beep
+ sLog.outString();
+
+ if(sConfig.GetBoolDefault("BeepAtStart", true))
+ printf("\a"); // \a = Alert
+
+ // print this here the first time
+ // later it will be printed after command queue updates
+ printf("TC>");
+
+ ///- As long as the World is running (no World::m_stopEvent), get the command line and handle it
+ while (!World::IsStopped())
+ {
+ fflush(stdout);
+ #ifdef linux
+ while (!kb_hit_return() && !World::IsStopped())
+ // With this, we limit CLI to 10commands/second
+ usleep(100);
+ if (World::IsStopped())
+ break;
+ #endif
+ char *command_str = fgets(commandbuf,sizeof(commandbuf),stdin);
+ if (command_str != NULL)
+ {
+ for(int x=0;command_str[x];x++)
+ if(command_str[x]=='\r'||command_str[x]=='\n')
+ {
+ command_str[x]=0;
+ break;
+ }
+
+
+ if(!*command_str)
+ {
+ printf("TC>");
+ continue;
+ }
+
+ std::string command;
+ if(!consoleToUtf8(command_str,command)) // convert from console encoding to utf8
+ {
+ printf("TC>");
+ continue;
+ }
+
+ sWorld.QueueCliCommand(&utf8print,command.c_str());
+ }
+ else if (feof(stdin))
+ {
+ World::StopNow(SHUTDOWN_EXIT_CODE);
+ }
+ }
+
+ ///- End the database thread
+ WorldDatabase.ThreadEnd(); // free mySQL thread resources
+}