OregonCore  revision 3611e8a-git
Your Favourite TBC server
Level4.cpp
Go to the documentation of this file.
1 
2 #include "Common.h"
3 #include "ObjectMgr.h"
4 #include "World.h"
5 #include "WorldSession.h"
6 #include "Config/Config.h"
7 
8 #include "AccountMgr.h"
9 #include "Chat.h"
10 #include "Language.h"
11 #include "Log.h"
12 #include "MapManager.h"
13 #include "Player.h"
14 #include "Util.h"
15 
16 // Delete a user account and all associated characters in this realm
17 // 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
19 {
20  if (!*args)
21  return false;
22 
24  char* account_name_str = strtok ((char*)args, " ");
25  if (!account_name_str)
26  return false;
27 
28  std::string account_name = account_name_str;
29  if (!AccountMgr::normalizeString(account_name))
30  {
31  PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, account_name.c_str());
32  SetSentErrorMessage(true);
33  return false;
34  }
35 
36  uint32 account_id = sAccountMgr->GetId(account_name);
37  if (!account_id)
38  {
39  PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, account_name.c_str());
40  SetSentErrorMessage(true);
41  return false;
42  }
43 
44  // Commands not recommended call from chat, but support anyway
45  if (m_session)
46  {
47  uint32 targetSecurity = sAccountMgr->GetSecurity(account_id);
48 
49  // can delete only for account with less security
50  // This is also reject self apply in fact
51  if (targetSecurity >= m_session->GetSecurity())
52  {
54  SetSentErrorMessage (true);
55  return false;
56  }
57  }
58 
59  AccountOpResult result = sAccountMgr->DeleteAccount(account_id);
60  switch (result)
61  {
62  case AOR_OK:
63  PSendSysMessage(LANG_ACCOUNT_DELETED, account_name.c_str());
64  break;
65  case AOR_NAME_NOT_EXIST:
66  PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, account_name.c_str());
67  SetSentErrorMessage(true);
68  return false;
71  SetSentErrorMessage(true);
72  return false;
73  default:
74  PSendSysMessage(LANG_ACCOUNT_NOT_DELETED, account_name.c_str());
75  SetSentErrorMessage(true);
76  return false;
77  }
78 
79  return true;
80 }
81 
89 bool ChatHandler::GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string searchString)
90 {
91  QueryResult_AutoPtr resultChar;
92  if (!searchString.empty())
93  {
94  // search by GUID
95  if (isNumeric(searchString.c_str()))
96  resultChar = CharacterDatabase.PQuery("SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND guid = %llu", uint64(atoi(searchString.c_str())));
97  // search by name
98  else
99  {
100  if (!normalizePlayerName(searchString))
101  return false;
102 
103  resultChar = CharacterDatabase.PQuery("SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND deleteInfos_Name " _LIKE_ " " _CONCAT3_("'%%'", "'%s'", "'%%'"), searchString.c_str());
104  }
105  }
106  else
107  resultChar = CharacterDatabase.Query("SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL");
108 
109  if (resultChar)
110  {
111  do
112  {
113  Field* fields = resultChar->Fetch();
114 
115  DeletedInfo info;
116 
117  info.lowguid = fields[0].GetUInt32();
118  info.name = fields[1].GetCppString();
119  info.accountId = fields[2].GetUInt32();
120 
121  // account name will be empty for not existed account
122  sAccountMgr->GetName(info.accountId, info.accountName);
123 
124  info.deleteDate = time_t(fields[3].GetUInt64());
125 
126  foundList.push_back(info);
127  }
128  while (resultChar->NextRow());
129  }
130 
131  return true;
132 }
133 
141 std::string ChatHandler::GenerateDeletedCharacterGUIDsWhereStr(DeletedInfoList::const_iterator& itr, DeletedInfoList::const_iterator const& itr_end)
142 {
143  std::ostringstream wherestr;
144  wherestr << "guid IN ('";
145  for (; itr != itr_end; ++itr)
146  {
147  wherestr << itr->lowguid;
148 
149  if (wherestr.str().size() > MAX_QUERY_LEN - 50) // near to max query
150  {
151  ++itr;
152  break;
153  }
154 
155  DeletedInfoList::const_iterator itr2 = itr;
156  if (++itr2 != itr_end)
157  wherestr << "','";
158  }
159  wherestr << "')";
160  return wherestr.str();
161 }
162 
174 {
175  if (!m_session)
176  {
180  }
181 
182  for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
183  {
184  std::string dateStr = TimeToTimestampStr(itr->deleteDate);
185 
186  if (!m_session)
188  itr->lowguid, itr->name.c_str(), itr->accountName.empty() ? "<Not existed>" : itr->accountName.c_str(),
189  itr->accountId, dateStr.c_str());
190  else
192  itr->lowguid, itr->name.c_str(), itr->accountName.empty() ? "<Not existed>" : itr->accountName.c_str(),
193  itr->accountId, dateStr.c_str());
194  }
195 
196  if (!m_session)
198 }
199 
211 {
212  DeletedInfoList foundList;
213  if (!GetDeletedCharacterInfoList(foundList, args))
214  return false;
215 
216  // if no characters have been found, output a warning
217  if (foundList.empty())
218  {
220  return false;
221  }
222 
224  return true;
225 }
226 
238 {
239  if (delInfo.accountName.empty()) // account not exist
240  {
241  PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_ACCOUNT, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId);
242  return;
243  }
244 
245  // check character count
246  uint32 charcount = sAccountMgr->GetCharactersCount(delInfo.accountId);
247  if (charcount >= 10)
248  {
249  PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_FULL, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId);
250  return;
251  }
252 
253  if (sObjectMgr.GetPlayerGUIDByName(delInfo.name))
254  {
255  PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_NAME, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId);
256  return;
257  }
258 
259  CharacterDatabase.PExecute("UPDATE characters SET name='%s', account='%u', deleteDate=NULL, deleteInfos_Name=NULL, deleteInfos_Account=NULL WHERE deleteDate IS NOT NULL AND guid = %u",
260  delInfo.name.c_str(), delInfo.accountId, delInfo.lowguid);
261 }
262 
275 {
276  // It is required to submit at least one argument
277  if (!*args)
278  return false;
279 
280  std::string searchString;
281  std::string newCharName;
282  uint32 newAccount = 0;
283 
284  // GCC by some strange reason fail build code without temporary variable
285  std::istringstream params(args);
286  params >> searchString >> newCharName >> newAccount;
287 
288  DeletedInfoList foundList;
289  if (!GetDeletedCharacterInfoList(foundList, searchString))
290  return false;
291 
292  if (foundList.empty())
293  {
295  return false;
296  }
297 
300 
301  if (newCharName.empty())
302  {
303  // Drop not existed account cases
304  for (DeletedInfoList::iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
306  }
307  else if (foundList.size() == 1 && normalizePlayerName(newCharName))
308  {
309  DeletedInfo delInfo = foundList.front();
310 
311  // update name
312  delInfo.name = newCharName;
313 
314  // if new account provided update deleted info
315  if (newAccount && newAccount != delInfo.accountId)
316  {
317  delInfo.accountId = newAccount;
318  sAccountMgr->GetName(newAccount, delInfo.accountName);
319  }
320 
322  }
323  else
325 
326  return true;
327 }
328 
340 {
341  // It is required to submit at least one argument
342  if (!*args)
343  return false;
344 
345  DeletedInfoList foundList;
346  if (!GetDeletedCharacterInfoList(foundList, args))
347  return false;
348 
349  if (foundList.empty())
350  {
352  return false;
353  }
354 
357 
358  // Call the appropriate function to delete them (current account for deleted characters is 0)
359  for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
360  Player::DeleteFromDB(itr->lowguid, 0, false, true);
361 
362  return true;
363 }
364 
377 {
378  int32 keepDays = sWorld.getConfig(CONFIG_CHARDELETE_KEEP_DAYS);
379 
380  char* px = strtok((char*)args, " ");
381  if (px)
382  {
383  if (!isNumeric(px))
384  return false;
385 
386  keepDays = atoi(px);
387  if (keepDays < 0)
388  return false;
389  }
390  // config option value 0 -> disabled and can't be used
391  else if (keepDays <= 0)
392  return false;
393 
395  return true;
396 }
397 
399 {
400  if (!*args)
401  return false;
402 
403  char* character_name_str = strtok((char*)args, " ");
404  if (!character_name_str)
405  return false;
406 
407  std::string character_name = character_name_str;
408  if (!normalizePlayerName(character_name))
409  return false;
410 
411  uint64 character_guid;
412  uint32 account_id;
413 
414  Player* player = sObjectMgr.GetPlayer(character_name.c_str());
415  if (player)
416  {
417  character_guid = player->GetGUID();
418  account_id = player->GetSession()->GetAccountId();
419  player->GetSession()->KickPlayer();
420  }
421  else
422  {
423  character_guid = sObjectMgr.GetPlayerGUIDByName(character_name);
424  if (!character_guid)
425  {
426  PSendSysMessage(LANG_NO_PLAYER, character_name.c_str());
427  SetSentErrorMessage(true);
428  return false;
429  }
430 
431  account_id = sObjectMgr.GetPlayerAccountIdByGUID(character_guid);
432  }
433 
434  std::string account_name;
435  sAccountMgr->GetName (account_id, account_name);
436 
437  Player::DeleteFromDB(character_guid, account_id, true);
438  PSendSysMessage(LANG_CHARACTER_DELETED, character_name.c_str(), GUID_LOPART(character_guid), account_name.c_str(), account_id);
439  return true;
440 }
441 
442 // Exit the realm
443 bool ChatHandler::HandleServerExitCommand(const char* /*args*/)
444 {
447  return true;
448 }
449 
450 // Display info on users currently in the realm
452 {
453  // Get the list of accounts ID logged to the realm
454  QueryResult_AutoPtr resultDB = CharacterDatabase.Query("SELECT name,account FROM characters WHERE online > 0");
455  if (!resultDB)
456  return true;
457 
458  // Display the list of account/characters online
459  SendSysMessage("=====================================================================");
461  SendSysMessage("=====================================================================");
462 
463  // Circle through accounts
464  do
465  {
466  Field* fieldsDB = resultDB->Fetch();
467  std::string name = fieldsDB[0].GetCppString();
468  uint32 account = fieldsDB[1].GetUInt32();
469 
470  // Get the username, last IP and GM level of each account
471  // No SQL injection. account is uint32.
472  QueryResult_AutoPtr resultLogin =
473  LoginDatabase.PQuery("SELECT a.username, a.last_ip, aa.gmlevel, a.expansion "
474  "FROM account a "
475  "LEFT JOIN account_access aa "
476  "ON (a.id = aa.id) "
477  "WHERE a.id = '%u'", account);
478  if (resultLogin)
479  {
480  Field* fieldsLogin = resultLogin->Fetch();
481  PSendSysMessage("|%15s| %20s | %15s |%4d|%5d|",
482  fieldsLogin[0].GetString(), name.c_str(), fieldsLogin[1].GetString(), fieldsLogin[2].GetUInt32(), fieldsLogin[3].GetUInt32());
483  }
484  else
486 
487  }
488  while (resultDB->NextRow());
489 
490  SendSysMessage("=====================================================================");
491  return true;
492 }
493 
494 // Create an account
496 {
497  if (!*args)
498  return false;
499 
500  // Parse the command line arguments
501  char* szAcc = strtok((char*)args, " ");
502  char* szPassword = strtok(NULL, " ");
503  if (!szAcc || !szPassword)
504  return false;
505 
506  // normalized in sAccountMgr->CreateAccount
507  std::string account_name = szAcc;
508  std::string password = szPassword;
509 
510  AccountOpResult result = sAccountMgr->CreateAccount(account_name, password);
511  switch (result)
512  {
513  case AOR_OK:
514  PSendSysMessage(LANG_ACCOUNT_CREATED, account_name.c_str());
515  break;
516  case AOR_NAME_TOO_LONG:
518  SetSentErrorMessage(true);
519  return false;
522  SetSentErrorMessage(true);
523  return false;
526  SetSentErrorMessage(true);
527  return false;
528  default:
529  PSendSysMessage(LANG_ACCOUNT_NOT_CREATED, account_name.c_str());
530  SetSentErrorMessage(true);
531  return false;
532  }
533 
534  return true;
535 }
536 
537 // Sets/gets the mask for logging
539 {
540  // no arguments, retrieve current log masks
541  if (!*args)
542  {
543  PSendSysMessage("Current logging mask: %lu", sLog.GetLogMask());
544  PSendSysMessage("Current logging db mask: %lu", sLog.GetDBLogMask());
545  return true;
546  }
547 
548  // first argument
549  unsigned long mask = strtoul(args, NULL, 0); // recognize base
550  sLog.SetLogMask(mask);
551 
552  PSendSysMessage("Logging mask set to %lu", mask);
553 
554  // second argument (if set)
555  if ((args = strchr(args, ' ')))
556  {
557  ++args;
558  mask = strtoul(args, NULL, 0); // recognize base
559  sLog.SetDBLogMask(mask);
560 
561  PSendSysMessage("Logging db mask set to %lu", mask);
562  }
563  return true;
564 }
565 
566 // set diff time record interval
568 {
569  if (!*args)
570  return false;
571 
572  char* NewTimeStr = strtok((char*)args, " ");
573  if (!NewTimeStr)
574  return false;
575 
576  int32 NewTime = atoi(NewTimeStr);
577  if (NewTime < 0)
578  return false;
579 
580  sWorld.SetRecordDiffInterval(NewTime);
581  printf( "Record diff every %u ms\n", NewTime);
582  return true;
583 }
584 
void SetSentErrorMessage(bool val)
Definition: Chat.h:590
static void DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmChars=true, bool deleteFinally=false)
Definition: Player.cpp:3893
#define GUID_LOPART(x)
Definition: ObjectGuid.h:110
bool GetDeletedCharacterInfoList(DeletedInfoList &foundList, std::string searchString="")
Definition: Level4.cpp:89
QueryResult_AutoPtr PQuery(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:400
Definition: Field.h:24
std::string accountName
the account name
Definition: Chat.h:580
#define sLog
Log class singleton.
Definition: Log.h:187
ACE_INT32 int32
Definition: Define.h:67
QueryResult_AutoPtr Query(const char *sql)
Definition: Database.cpp:383
virtual void SendSysMessage(const char *str)
Definition: Chat.cpp:787
uint32 GetAccountId() const
Definition: WorldSession.h:100
WorldSession * m_session
Definition: Chat.h:593
bool HandleServerExitCommand(const char *args)
Definition: Level4.cpp:443
#define sObjectMgr
Definition: ObjectMgr.h:1285
time_t deleteDate
the date at which the character has been deleted
Definition: Chat.h:581
const char * GetString() const
Definition: Field.h:41
bool HandleAccountOnlineListCommand(const char *args)
Definition: Level4.cpp:451
bool HandleCharacterDeletedOldCommand(const char *args)
Definition: Level4.cpp:376
bool HandleCharacterEraseCommand(const char *args)
Definition: Level4.cpp:398
bool normalizePlayerName(std::string &name)
Definition: ObjectMgr.cpp:225
void HandleCharacterDeletedRestoreHelper(DeletedInfo const &delInfo)
Definition: Level4.cpp:237
std::string GetCppString() const
Definition: Field.h:52
std::string GenerateDeletedCharacterGUIDsWhereStr(DeletedInfoList::const_iterator &itr, DeletedInfoList::const_iterator const &itr_end)
Definition: Level4.cpp:141
void PSendSysMessage(const char *format,...) ATTR_PRINTF(2
Definition: Chat.cpp:855
DatabaseType LoginDatabase
Accessor to the realm/login database.
Definition: Main.cpp:55
void HandleCharacterDeletedListHelper(DeletedInfoList const &foundList)
Definition: Level4.cpp:173
bool HandleCharacterDeletedListCommand(const char *args)
Definition: Level4.cpp:210
AccountOpResult
Definition: AccountMgr.h:26
#define _LIKE_
Definition: DatabaseEnv.h:30
static bool normalizeString(std::string &utf8str)
Definition: AccountMgr.cpp:223
std::string TimeToTimestampStr(time_t t)
Definition: Util.cpp:216
bool HandleAccountDeleteCommand(const char *args)
Definition: Level4.cpp:18
bool PExecute(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:441
#define sAccountMgr
Definition: AccountMgr.h:60
uint32 accountId
the account id
Definition: Chat.h:579
static void DeleteOldCharacters()
Definition: Player.cpp:4109
bool HandleCharacterDeletedDeleteCommand(const char *args)
Definition: Level4.cpp:339
ACE_UINT64 uint64
Definition: Define.h:70
bool isNumeric(wchar_t wchar)
Definition: Util.h:202
#define _CONCAT3_(A, B, C)
Definition: DatabaseEnv.h:32
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
std::list< DeletedInfo > DeletedInfoList
Definition: Chat.h:584
uint32 lowguid
the low GUID from the character
Definition: Chat.h:577
bool HandleServerSetLogMaskCommand(const char *args)
Definition: Level4.cpp:538
std::string name
the character name
Definition: Chat.h:578
WorldSession * GetSession() const
Definition: Player.h:1959
#define sWorld
Definition: World.h:860
DatabaseType CharacterDatabase
Accessor to the character database.
Definition: Main.cpp:54
void uint32 GetSecurity() const
Definition: WorldSession.h:96
ACE_UINT32 uint32
Definition: Define.h:71
bool HandleAccountCreateCommand(const char *args)
Definition: Level4.cpp:495
Definition: Player.h:922
bool HandleCharacterDeletedRestoreCommand(const char *args)
Definition: Level4.cpp:274
static void StopNow(uint8 exitcode)
Definition: World.h:632
const uint64 & GetGUID() const
Definition: Object.h:156
bool HandleServerSetDiffTimeCommand(const char *args)
Definition: Level4.cpp:567
#define MAX_QUERY_LEN
Definition: Database.h:44