2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /// \addtogroup mangosd
27 #include "ScriptCalls.h"
28 #include "ObjectMgr.h"
29 #include "WorldSession.h"
30 #include "Config/ConfigEnv.h"
32 #include "AccountMgr.h"
33 #include "CliRunnable.h"
34 #include "MapManager.h"
38 void utf8print(const char* str
)
40 #if PLATFORM == PLATFORM_WINDOWS
41 wchar_t wtemp_buf
[6000];
42 size_t wtemp_len
= 6000-1;
43 if(!Utf8toWStr(str
,strlen(str
),wtemp_buf
,wtemp_len
))
47 CharToOemBuffW(&wtemp_buf
[0],&temp_buf
[0],wtemp_len
+1);
54 /// Delete a user account and all associated characters in this realm
55 /// \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
56 bool ChatHandler::HandleAccountDeleteCommand(const char* args
)
61 ///- Get the account name from the command line
62 char *account_name_str
=strtok ((char*)args
," ");
63 if (!account_name_str
)
66 std::string account_name
= account_name_str
;
67 if(!AccountMgr::normilizeString(account_name
))
69 PSendSysMessage(LANG_ACCOUNT_NOT_EXIST
,account_name
.c_str());
70 SetSentErrorMessage(true);
74 uint32 account_id
= accmgr
.GetId(account_name
);
77 PSendSysMessage(LANG_ACCOUNT_NOT_EXIST
,account_name
.c_str());
78 SetSentErrorMessage(true);
82 /// Commands not recommended call from chat, but support anyway
85 uint32 targetSecurity
= accmgr
.GetSecurity(account_id
);
87 /// can delete only for account with less security
88 /// This is also reject self apply in fact
89 if (targetSecurity
>= m_session
->GetSecurity())
91 SendSysMessage (LANG_YOURS_SECURITY_IS_LOW
);
92 SetSentErrorMessage (true);
97 AccountOpResult result
= accmgr
.DeleteAccount(account_id
);
101 PSendSysMessage(LANG_ACCOUNT_DELETED
,account_name
.c_str());
103 case AOR_NAME_NOT_EXIST
:
104 PSendSysMessage(LANG_ACCOUNT_NOT_EXIST
,account_name
.c_str());
105 SetSentErrorMessage(true);
107 case AOR_DB_INTERNAL_ERROR
:
108 PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR
,account_name
.c_str());
109 SetSentErrorMessage(true);
112 PSendSysMessage(LANG_ACCOUNT_NOT_DELETED
,account_name
.c_str());
113 SetSentErrorMessage(true);
120 bool ChatHandler::HandleCharacterDeleteCommand(const char* args
)
125 char *character_name_str
= strtok((char*)args
," ");
126 if(!character_name_str
)
129 std::string character_name
= character_name_str
;
130 if(!normalizePlayerName(character_name
))
133 uint64 character_guid
;
136 Player
*player
= objmgr
.GetPlayer(character_name
.c_str());
139 character_guid
= player
->GetGUID();
140 account_id
= player
->GetSession()->GetAccountId();
141 player
->GetSession()->KickPlayer();
145 character_guid
= objmgr
.GetPlayerGUIDByName(character_name
);
148 PSendSysMessage(LANG_NO_PLAYER
,character_name
.c_str());
149 SetSentErrorMessage(true);
153 account_id
= objmgr
.GetPlayerAccountIdByGUID(character_guid
);
156 std::string account_name
;
157 accmgr
.GetName (account_id
,account_name
);
159 Player::DeleteFromDB(character_guid
, account_id
, true);
160 PSendSysMessage(LANG_CHARACTER_DELETED
,character_name
.c_str(),GUID_LOPART(character_guid
),account_name
.c_str(), account_id
);
165 bool ChatHandler::HandleServerExitCommand(const char* args
)
167 SendSysMessage(LANG_COMMAND_EXIT
);
168 World::StopNow(SHUTDOWN_EXIT_CODE
);
172 /// Display info on users currently in the realm
173 bool ChatHandler::HandleAccountOnlineListCommand(const char* args
)
175 ///- Get the list of accounts ID logged to the realm
176 QueryResult
*resultDB
= CharacterDatabase
.Query("SELECT name,account FROM characters WHERE online > 0");
180 ///- Display the list of account/characters online
181 SendSysMessage("=====================================================================");
182 SendSysMessage(LANG_ACCOUNT_LIST_HEADER
);
183 SendSysMessage("=====================================================================");
185 ///- Circle through accounts
188 Field
*fieldsDB
= resultDB
->Fetch();
189 std::string name
= fieldsDB
[0].GetCppString();
190 uint32 account
= fieldsDB
[1].GetUInt32();
192 ///- Get the username, last IP and GM level of each account
193 // No SQL injection. account is uint32.
195 QueryResult
*resultLogin
= loginDatabase
.PQuery("SELECT username, last_ip, gmlevel, expansion FROM account WHERE id = '%u'",account
);
199 Field
*fieldsLogin
= resultLogin
->Fetch();
200 PSendSysMessage("|%15s| %20s | %15s |%4d|%5d|",
201 fieldsLogin
[0].GetString(),name
.c_str(),fieldsLogin
[1].GetString(),fieldsLogin
[2].GetUInt32(),fieldsLogin
[3].GetUInt32());
206 PSendSysMessage(LANG_ACCOUNT_LIST_ERROR
,name
.c_str());
208 }while(resultDB
->NextRow());
212 SendSysMessage("=====================================================================");
216 /// Create an account
217 bool ChatHandler::HandleAccountCreateCommand(const char* args
)
222 ///- %Parse the command line arguments
223 char *szAcc
= strtok((char*)args
, " ");
224 char *szPassword
= strtok(NULL
, " ");
225 if(!szAcc
|| !szPassword
)
228 // normilized in accmgr.CreateAccount
229 std::string account_name
= szAcc
;
230 std::string password
= szPassword
;
232 AccountOpResult result
= accmgr
.CreateAccount(account_name
, password
);
236 PSendSysMessage(LANG_ACCOUNT_CREATED
,account_name
.c_str());
238 case AOR_NAME_TOO_LONG
:
239 SendSysMessage(LANG_ACCOUNT_TOO_LONG
);
240 SetSentErrorMessage(true);
242 case AOR_NAME_ALREDY_EXIST
:
243 SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST
);
244 SetSentErrorMessage(true);
246 case AOR_DB_INTERNAL_ERROR
:
247 PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR
,account_name
.c_str());
248 SetSentErrorMessage(true);
251 PSendSysMessage(LANG_ACCOUNT_NOT_CREATED
,account_name
.c_str());
252 SetSentErrorMessage(true);
259 /// Set the level of logging
260 bool ChatHandler::HandleServerSetLogLevelCommand(const char *args
)
265 char *NewLevel
= strtok((char*)args
, " ");
269 sLog
.SetLogLevel(NewLevel
);
276 // Non-blocking keypress detector, when return pressed, return 1, else always return 0
284 FD_SET(STDIN_FILENO
, &fds
);
285 select(STDIN_FILENO
+1, &fds
, NULL
, NULL
, &tv
);
286 return FD_ISSET(STDIN_FILENO
, &fds
);
291 void CliRunnable::run()
293 ///- Init new SQL thread for the world database (one connection call enough)
294 WorldDatabase
.ThreadStart(); // let thread do safe mySQL requests
296 char commandbuf
[256];
298 ///- Display the list of available CLI functions then beep
301 if(sConfig
.GetBoolDefault("BeepAtStart", true))
302 printf("\a"); // \a = Alert
304 // print this here the first time
305 // later it will be printed after command queue updates
308 ///- As long as the World is running (no World::m_stopEvent), get the command line and handle it
309 while (!World::IsStopped())
313 while (!kb_hit_return() && !World::IsStopped())
314 // With this, we limit CLI to 10commands/second
316 if (World::IsStopped())
319 char *command_str
= fgets(commandbuf
,sizeof(commandbuf
),stdin
);
320 if (command_str
!= NULL
)
322 for(int x
=0;command_str
[x
];x
++)
323 if(command_str
[x
]=='\r'||command_str
[x
]=='\n')
337 if(!consoleToUtf8(command_str
,command
)) // convert from console encoding to utf8
343 sWorld
.QueueCliCommand(&utf8print
,command
.c_str());
345 else if (feof(stdin
))
347 World::StopNow(SHUTDOWN_EXIT_CODE
);
351 ///- End the database thread
352 WorldDatabase
.ThreadEnd(); // free mySQL thread resources