41 | | |
42 | | //CliCommand and CliCommandHolder are defined in World.h to avoid cyclic deps |
43 | | |
44 | | //func prototypes must be defined |
45 | | |
46 | | void CliHelp(char*,pPrintf); |
47 | | void CliInfo(char*,pPrintf); |
48 | | void CliBan(char*,pPrintf); |
49 | | void CliBanList(char*,pPrintf); |
50 | | void CliRemoveBan(char*,pPrintf); |
51 | | void CliSetGM(char*,pPrintf); |
52 | | void CliListGM(char*,pPrintf); |
53 | | void CliVersion(char*,pPrintf); |
54 | | void CliExit(char*,pPrintf); |
55 | | void CliIdleRestart(char*,pPrintf zprintf); |
56 | | void CliRestart(char*,pPrintf zprintf); |
57 | | void CliIdleShutdown(char*,pPrintf zprintf); |
58 | | void CliShutdown(char*,pPrintf zprintf); |
59 | | void CliBroadcast(char*,pPrintf); |
60 | | void CliCreate(char*,pPrintf); |
61 | | void CliDelete(char*,pPrintf); |
62 | | void CliCharDelete(char *,pPrintf); |
63 | | void CliLoadScripts(char*,pPrintf); |
64 | | void CliKick(char*,pPrintf); |
65 | | void CliTele(char*,pPrintf); |
66 | | void CliMotd(char*,pPrintf); |
67 | | void CliCorpses(char*,pPrintf); |
68 | | void CliSetLogLevel(char*,pPrintf); |
69 | | void CliUpTime(char*,pPrintf); |
70 | | void CliSetAddon(char*,pPrintf); |
71 | | void CliWritePlayerDump(char*,pPrintf); |
72 | | void CliLoadPlayerDump(char*,pPrintf); |
73 | | void CliSave(char*,pPrintf); |
74 | | void CliSend(char*,pPrintf); |
75 | | void CliPLimit(char*,pPrintf); |
76 | | void CliSetPassword(char*,pPrintf); |
77 | | /// Table of known commands |
78 | | const CliCommand Commands[]= |
79 | | { |
80 | | {"help", & CliHelp,"Display this help message"}, |
81 | | {"broadcast", & CliBroadcast,"Announce in-game message"}, |
82 | | {"create", & CliCreate,"Create account"}, |
83 | | {"delete", & CliDelete,"Delete account and characters"}, |
84 | | {"chardelete", & CliCharDelete,"Delete character"}, |
85 | | {"info", & CliInfo,"Display Server infomation"}, |
86 | | {"uptime", & CliUpTime, "Displays the server uptime"}, |
87 | | {"motd", & CliMotd,"Change or display motd"}, |
88 | | {"kick", & CliKick,"Kick user"}, |
89 | | {"ban", & CliBan,"Ban account|ip"}, |
90 | | {"listbans", & CliBanList,"List bans"}, |
91 | | {"unban", & CliRemoveBan,"Remove ban from account|ip"}, |
92 | | {"setgm", & CliSetGM,"Edit user privileges"}, |
93 | | {"setpass", & CliSetPassword,"Set password for account"}, |
94 | | {"setaddon", & CliSetAddon,"Set user expansion addon level allowed"}, |
95 | | {"listgm", & CliListGM,"Display user privileges"}, |
96 | | {"loadscripts", & CliLoadScripts,"Load script library"}, |
97 | | {"setloglevel", & CliSetLogLevel,"Set Log Level"}, |
98 | | {"corpses", & CliCorpses,"Manually call corpses erase global even code"}, |
99 | | {"version", & CliVersion,"Display server version"}, |
100 | | {"idlerestart", & CliIdleRestart,"Restart server with some delay when there are no active connections remaining"}, |
101 | | {"restart", & CliRestart,"Restart server with some delay"}, |
102 | | {"idleshutdown", & CliIdleShutdown,"Shutdown server with some delay when there are no active connections remaining"}, |
103 | | {"shutdown", & CliShutdown,"Shutdown server with some delay"}, |
104 | | {"exit", & CliExit,"Shutdown server NOW"}, |
105 | | {"writepdump", &CliWritePlayerDump,"Write a player dump to a file"}, |
106 | | {"loadpdump", &CliLoadPlayerDump,"Load a player dump from a file"}, |
107 | | {"saveall", &CliSave,"Save all players"}, |
108 | | {"send", &CliSend,"Send message to a player"}, |
109 | | {"tele", &CliTele,"Teleport player to location"}, |
110 | | {"plimit", &CliPLimit,"Show or set player login limitations"} |
111 | | }; |
112 | | /// \todo Need some pragma pack? Else explain why in a comment. |
113 | | #define CliTotalCmds sizeof(Commands)/sizeof(CliCommand) |
114 | | |
| 39 | #include "Chat.h" |
| 40 | |
| 41 | void utf8print(const char* str) |
| 42 | { |
125 | | |
126 | | /// Create a character dump file |
127 | | void CliWritePlayerDump(char*command,pPrintf zprintf) |
128 | | { |
129 | | char * file = strtok(command, " "); |
130 | | char * p2 = strtok(NULL, " "); |
131 | | if(!file || !p2) |
132 | | { |
133 | | zprintf("Syntax is: writepdump $filename $playerNameOrGUID\r\n"); |
134 | | return; |
135 | | } |
136 | | |
137 | | std::string name; |
138 | | if(!consoleToUtf8(p2,name)) // convert from console encoding to utf8 |
139 | | return; |
140 | | |
141 | | if(!normalizePlayerName(name)) |
142 | | { |
143 | | zprintf("Syntax is: writepdump $filename $playerNameOrGUID\r\n"); |
144 | | return; |
145 | | } |
146 | | |
147 | | uint32 guid = objmgr.GetPlayerGUIDByName(name); |
148 | | if(!guid) |
149 | | guid = atoi(p2); |
150 | | |
151 | | if(!guid) |
152 | | { |
153 | | zprintf("Syntax is: writepdump $filename $playerNameOrGUID\r\n"); |
154 | | return; |
155 | | } |
156 | | |
157 | | PlayerDumpWriter().WriteDump(file, guid); |
158 | | } |
159 | | |
160 | | /// Load a character from a dump file |
161 | | void CliLoadPlayerDump(char*command,pPrintf zprintf) |
162 | | { |
163 | | char * file = strtok(command, " "); |
164 | | char * acc = strtok(NULL, " "); |
165 | | if (!file ||!acc) |
166 | | { |
167 | | zprintf("Syntax is: loadpdump $filename $account ($newname) ($newguid)\r\n"); |
168 | | return; |
169 | | } |
170 | | |
171 | | uint32 account_id = accmgr.GetId(acc); |
172 | | if(!account_id) |
173 | | { |
174 | | account_id = atoi(acc); |
175 | | if(account_id) |
176 | | { |
177 | | std::string acc_name; |
178 | | if(!accmgr.GetName(account_id,acc_name)) |
179 | | { |
180 | | zprintf("Failed to load the character! Account not exist.\r\n"); |
181 | | return; |
182 | | } |
183 | | } |
184 | | else |
185 | | { |
186 | | zprintf("Failed to load the character! Account not exist.\r\n"); |
187 | | return; |
188 | | } |
189 | | } |
190 | | |
191 | | char * name_str = strtok(NULL, " "); |
192 | | char * guid_str = name_str ? strtok(NULL, " ") : NULL; |
193 | | |
194 | | uint32 guid = guid_str ? atoi(guid_str) : 0; |
195 | | |
196 | | std::string name; |
197 | | if(name_str) |
198 | | { |
199 | | if(!consoleToUtf8(name_str,name)) // convert from console encoding to utf8 |
200 | | return; |
201 | | |
202 | | if(!normalizePlayerName(name)) |
203 | | { |
204 | | zprintf("Syntax is: loadpdump $filename $account ($newname) ($newguid)\r\n"); |
205 | | return; |
206 | | } |
207 | | } |
208 | | |
209 | | if(PlayerDumpReader().LoadDump(file, account_id, name, guid)) |
210 | | zprintf("Character loaded successfully!\r\n"); |
211 | | else |
212 | | zprintf("Failed to load the character!\r\n"); |
213 | | } |
214 | | |
215 | | /// Reload the scripts and notify the players |
216 | | void CliLoadScripts(char*command,pPrintf zprintf) |
217 | | { |
218 | | char const *del=strtok(command," "); |
219 | | if (!del) |
220 | | del=""; |
221 | | if(!LoadScriptingModule(del)) // Error report is already done by LoadScriptingModule |
222 | | return; |
223 | | |
224 | | sWorld.SendWorldText(LANG_SCRIPTS_RELOADED); |
332 | | } |
333 | | |
334 | | /// Restart the server (with some delay) as soon as no active connections remain on the server |
335 | | void CliIdleRestart(char* command,pPrintf zprintf) |
336 | | { |
337 | | char *args = strtok(command," "); |
338 | | |
339 | | if(!args) |
340 | | { |
341 | | zprintf("Syntax is: idlerestart $seconds|cancel\r\n"); |
342 | | return; |
343 | | } |
344 | | |
345 | | if(std::string(args)=="cancel") |
346 | | { |
347 | | sWorld.ShutdownCancel(); |
348 | | } |
349 | | else |
350 | | { |
351 | | |
352 | | uint32 time = atoi(args); |
353 | | |
354 | | ///- Prevent interpret wrong arg value as 0 secs shutdown time |
355 | | if(time==0 && (args[0]!='0' || args[1]!='\0') || time < 0) |
356 | | { |
357 | | zprintf("Syntax is: idlerestart $seconds|cancel\r\n"); |
358 | | return; |
359 | | } |
360 | | |
361 | | sWorld.ShutdownServ(time,SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE); |
362 | | } |
363 | | } |
364 | | |
365 | | /// Restart the server with some delay |
366 | | void CliRestart(char* command,pPrintf zprintf) |
367 | | { |
368 | | char *args = strtok(command," "); |
369 | | |
370 | | if(!args) |
371 | | { |
372 | | zprintf("Syntax is: restart $seconds|cancel\r\n"); |
373 | | return; |
374 | | } |
375 | | |
376 | | if(std::string(args)=="cancel") |
377 | | { |
378 | | sWorld.ShutdownCancel(); |
379 | | } |
380 | | else |
381 | | { |
382 | | int32 time = atoi(args); |
383 | | |
384 | | ///- Prevent interpret wrong arg value as 0 secs shutdown time |
385 | | if(time==0 && (args[0]!='0' || args[1]!='\0') || time < 0) |
386 | | { |
387 | | zprintf("Syntax is: restart $seconds|cancel\r\n"); |
388 | | return; |
389 | | } |
390 | | |
391 | | sWorld.ShutdownServ(time,SHUTDOWN_MASK_RESTART); |
392 | | } |
393 | | } |
394 | | |
395 | | /// Shutdown the server (with some delay) as soon as no active connections remain on the server |
396 | | void CliIdleShutdown(char* command,pPrintf zprintf) |
397 | | { |
398 | | char *args = strtok(command," "); |
399 | | |
400 | | if(!args) |
401 | | { |
402 | | zprintf("Syntax is: idleshutdown $seconds|cancel\r\n"); |
403 | | return; |
404 | | } |
405 | | |
406 | | if(std::string(args)=="cancel") |
407 | | { |
408 | | sWorld.ShutdownCancel(); |
409 | | } |
410 | | else |
411 | | { |
412 | | |
413 | | uint32 time = atoi(args); |
414 | | |
415 | | ///- Prevent interpret wrong arg value as 0 secs shutdown time |
416 | | if(time==0 && (args[0]!='0' || args[1]!='\0') || time < 0) |
417 | | { |
418 | | zprintf("Syntax is: idleshutdown $seconds|cancel\r\n"); |
419 | | return; |
420 | | } |
421 | | |
422 | | sWorld.ShutdownServ(time,SHUTDOWN_MASK_IDLE); |
423 | | } |
424 | | } |
425 | | |
426 | | /// Shutdown the server with some delay |
427 | | void CliShutdown(char* command,pPrintf zprintf) |
428 | | { |
429 | | char *args = strtok(command," "); |
430 | | |
431 | | if(!args) |
432 | | { |
433 | | zprintf("Syntax is: shutdown $seconds|cancel\r\n"); |
434 | | return; |
435 | | } |
436 | | |
437 | | if(std::string(args)=="cancel") |
438 | | { |
439 | | sWorld.ShutdownCancel(); |
440 | | } |
441 | | else |
442 | | { |
443 | | int32 time = atoi(args); |
444 | | |
445 | | ///- Prevent interpret wrong arg value as 0 secs shutdown time |
446 | | if(time==0 && (args[0]!='0' || args[1]!='\0') || time < 0) |
447 | | { |
448 | | zprintf("Syntax is: shutdown $seconds|cancel\r\n"); |
449 | | return; |
450 | | } |
451 | | |
452 | | sWorld.ShutdownServ(time); |
453 | | } |
| 173 | return true; |
505 | | zprintf("=====================================================================\r\n"); |
506 | | } |
507 | | |
508 | | /// Display a list of banned accounts and ip addresses |
509 | | void CliBanList(char*,pPrintf zprintf) |
510 | | { |
511 | | bool found = false; |
512 | | ///- Get the list of banned accounts and display them |
513 | | QueryResult *result = loginDatabase.Query("SELECT id,username FROM account WHERE id IN (SELECT id FROM account_banned WHERE active = 1)"); |
514 | | if(result) |
515 | | { |
516 | | found = true; |
517 | | |
518 | | zprintf("Currently Banned Accounts:\r\n"); |
519 | | zprintf("===============================================================================\r\n"); |
520 | | zprintf("| Account | BanDate | UnbanDate | Banned By | Ban Reason |\r\n"); |
521 | | do |
522 | | { |
523 | | zprintf("-------------------------------------------------------------------------------\r\n"); |
524 | | Field *fields = result->Fetch(); |
525 | | // No SQL injection. id is uint32. |
526 | | QueryResult *banInfo = loginDatabase.PQuery("SELECT bandate,unbandate,bannedby,banreason FROM account_banned WHERE id = %u AND active = 1 ORDER BY unbandate", fields[0].GetUInt32()); |
527 | | if (banInfo) |
528 | | { |
529 | | Field *fields2 = banInfo->Fetch(); |
530 | | do |
531 | | { |
532 | | time_t t_ban = fields2[0].GetUInt64(); |
533 | | tm* aTm_ban = localtime(&t_ban); |
534 | | zprintf("|%-15.15s|", fields[1].GetString()); |
535 | | zprintf("%02d-%02d-%02d %02d:%02d|", aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min); |
536 | | if ( fields2[0].GetUInt64() == fields2[1].GetUInt64() ) |
537 | | zprintf(" permanent |"); |
538 | | else |
539 | | { |
540 | | time_t t_unban = fields2[1].GetUInt64(); |
541 | | tm* aTm_unban = localtime(&t_unban); |
542 | | zprintf("%02d-%02d-%02d %02d:%02d|",aTm_unban->tm_year%100, aTm_unban->tm_mon+1, aTm_unban->tm_mday, aTm_unban->tm_hour, aTm_unban->tm_min); |
543 | | } |
544 | | zprintf("%-15.15s|%-15.15s|\r\n",fields2[2].GetString(),fields2[3].GetString()); |
545 | | }while ( banInfo->NextRow() ); |
546 | | delete banInfo; |
547 | | } |
548 | | }while( result->NextRow() ); |
549 | | zprintf("===============================================================================\r\n"); |
550 | | delete result; |
551 | | } |
552 | | |
553 | | ///- Get the list of banned IP addresses and display them |
554 | | result = loginDatabase.Query( "SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP()) ORDER BY unbandate" ); |
555 | | if(result) |
556 | | { |
557 | | found = true; |
558 | | |
559 | | zprintf("Currently Banned IPs:\r\n"); |
560 | | zprintf("===============================================================================\r\n"); |
561 | | zprintf("| IP | BanDate | UnbanDate | Banned By | Ban Reason |\r\n"); |
562 | | do |
563 | | { |
564 | | zprintf("-------------------------------------------------------------------------------\r\n"); |
565 | | Field *fields = result->Fetch(); |
566 | | time_t t_ban = fields[1].GetUInt64(); |
567 | | tm* aTm_ban = localtime(&t_ban); |
568 | | zprintf("|%-15.15s|", fields[0].GetString()); |
569 | | zprintf("%02d-%02d-%02d %02d:%02d|", aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min); |
570 | | if ( fields[1].GetUInt64() == fields[2].GetUInt64() ) |
571 | | zprintf(" permanent |"); |
572 | | else |
573 | | { |
574 | | time_t t_unban = fields[2].GetUInt64(); |
575 | | tm* aTm_unban = localtime(&t_unban); |
576 | | zprintf("%02d-%02d-%02d %02d:%02d|", aTm_unban->tm_year%100, aTm_unban->tm_mon+1, aTm_unban->tm_mday, aTm_unban->tm_hour, aTm_unban->tm_min); |
577 | | } |
578 | | zprintf("%-15.15s|%-15.15s|\r\n", fields[3].GetString(), fields[4].GetString()); |
579 | | }while( result->NextRow() ); |
580 | | zprintf("===============================================================================\r\n"); |
581 | | delete result; |
582 | | } |
583 | | |
584 | | if(!found) |
585 | | zprintf("We do not have banned users\r\n"); |
586 | | } |
587 | | |
588 | | /// Ban an IP address or a user account |
589 | | void CliBan(char*command,pPrintf zprintf) |
590 | | { |
591 | | ///- Get the command parameter |
592 | | char* type_str = strtok((char*)command, " "); |
593 | | char* nameOrIP_str = strtok(NULL, " "); |
594 | | char* duration_str = strtok(NULL," "); |
595 | | char* reason_str = strtok(NULL,""); |
596 | | |
597 | | if(!type_str||!nameOrIP_str||!duration_str||!reason_str)// ?!? input of single char "0"-"9" wouldn't detect when with: || !atoi(duration) |
598 | | { |
599 | | zprintf("Syntax: ban account|ip|character $AccountOrIpOrCharacter $duration[s|m|h|d] $reason \r\n"); |
600 | | return; |
601 | | } |
602 | | |
603 | | std::string type; |
604 | | if(!consoleToUtf8(type_str,type)) // convert from console encoding to utf8 |
605 | | return; |
606 | | |
607 | | std::string nameOrIP; |
608 | | if(!consoleToUtf8(nameOrIP_str,nameOrIP)) // convert from console encoding to utf8 |
609 | | return; |
610 | | |
611 | | std::string duration; |
612 | | if(!consoleToUtf8(duration_str,duration)) // convert from console encoding to utf8 |
613 | | return; |
614 | | |
615 | | std::string reason; |
616 | | if(!consoleToUtf8(reason_str,reason)) // convert from console encoding to utf8 |
617 | | return; |
618 | | |
619 | | switch (sWorld.BanAccount(type, nameOrIP, duration, reason, "Set by console.")) |
620 | | { |
621 | | case BAN_SUCCESS: |
622 | | if(atoi(duration_str)>0) |
623 | | zprintf("%s is banned for %s. Reason: %s.\r\n",nameOrIP.c_str(),secsToTimeString(TimeStringToSecs(duration_str),true,false).c_str(),reason.c_str()); |
624 | | else |
625 | | zprintf("%s is banned permanently. Reason: %s.\r\n",nameOrIP.c_str(),reason.c_str()); |
626 | | break; |
627 | | case BAN_NOTFOUND: |
628 | | zprintf("%s %s not found\r\n", type.c_str(), nameOrIP.c_str()); |
629 | | break; |
630 | | case BAN_SYNTAX_ERROR: |
631 | | zprintf("Syntax: ban account|ip|character $AccountOrIpOrCharacter $duration[s|m|h|d] $reason \r\n"); |
632 | | break; |
633 | | } |
634 | | } |
635 | | |
636 | | /// Display %TrinIty version |
637 | | void CliVersion(char*,pPrintf zprintf) |
638 | | { |
639 | | //<--maybe better append to info cmd |
640 | | zprintf( "%s (world-daemon)\r\n", _FULLVERSION ); |
641 | | } |
642 | | |
643 | | /// Unban an IP adress or a user account |
644 | | void CliRemoveBan(char *command,pPrintf zprintf) |
645 | | { |
646 | | ///- Get the command parameter |
647 | | char *type_str = strtok(command," "); |
648 | | char *nameorip_str = strtok(NULL," "); |
649 | | if(!nameorip_str||!type_str) |
650 | | { |
651 | | zprintf("Syntax is: unban account|ip|character $nameorip\r\n"); |
652 | | return; |
653 | | } |
654 | | |
655 | | std::string type; |
656 | | if(!consoleToUtf8(type_str,type)) // convert from console encoding to utf8 |
657 | | return; |
658 | | |
659 | | std::string nameorip; |
660 | | if(!consoleToUtf8(nameorip_str,nameorip)) // convert from console encoding to utf8 |
661 | | return; |
662 | | |
663 | | if (!sWorld.RemoveBanAccount(type, nameorip)) |
664 | | zprintf("%s %s not found\r\n", type.c_str(), nameorip.c_str()); |
665 | | else |
666 | | zprintf("We removed ban from %s: %s\r\n",type_str,nameorip.c_str()); |
667 | | } |
668 | | |
669 | | /// Display the list of GMs |
670 | | void CliListGM(char*,pPrintf zprintf) |
671 | | { |
672 | | |
673 | | ///- Get the accounts with GM Level >0 |
674 | | Field *fields; |
675 | | |
676 | | QueryResult *result = loginDatabase.Query( "SELECT username,gmlevel FROM account WHERE gmlevel > 0" ); |
677 | | if(result) |
678 | | { |
679 | | |
680 | | zprintf("Current gamemasters:\r\n"); |
681 | | zprintf("========================\r\n"); |
682 | | zprintf("| Account | GM |\r\n"); |
683 | | zprintf("========================\r\n"); |
684 | | |
685 | | ///- Circle through them. Display username and GM level |
686 | | do |
687 | | { |
688 | | fields = result->Fetch(); |
689 | | zprintf("|%15s|", fields[0].GetString()); |
690 | | zprintf("%6s|\r\n",fields[1].GetString()); |
691 | | }while( result->NextRow() ); |
692 | | |
693 | | zprintf("========================\r\n"); |
694 | | delete result; |
695 | | } |
696 | | else |
697 | | { |
698 | | zprintf("No gamemasters\r\n"); |
699 | | } |
700 | | } |
701 | | |
702 | | /// Set the GM level of an account |
703 | | void CliSetGM(char *command,pPrintf zprintf) |
704 | | { |
705 | | ///- Get the command line arguments |
706 | | char *szAcc = strtok(command," "); |
707 | | char *szLevel = strtok(NULL," "); |
708 | | |
709 | | if(!szAcc||!szLevel) //wrong syntax 'setgm' without name |
710 | | { |
711 | | zprintf("Syntax is: setgm $account $number (0 - normal, 3 - gamemaster)>\r\n"); |
712 | | return; |
713 | | } |
714 | | |
715 | | //wow it's ok,let's hope it was integer given |
716 | | int lev=atoi(szLevel); //get int anyway (0 if error) |
717 | | |
718 | | std::string safe_account_name; |
719 | | if(!consoleToUtf8(szAcc,safe_account_name)) // convert from console encoding to utf8 |
720 | | return; |
721 | | |
722 | | ///- Convert Account name to Upper Format |
723 | | AccountMgr::normilizeString(safe_account_name); |
724 | | |
725 | | ///- Escape the account name to allow quotes in names |
726 | | loginDatabase.escape_string(safe_account_name); |
727 | | |
728 | | ///- Try to find the account, then update the GM level |
729 | | // No SQL injection (account name is escaped) |
730 | | QueryResult *result = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",safe_account_name.c_str()); |
731 | | |
732 | | if (result) |
733 | | { |
734 | | Field *fields = result->Fetch(); |
735 | | uint32 account_id = fields[0].GetUInt32(); |
736 | | delete result; |
737 | | |
738 | | WorldSession* session = sWorld.FindSession(account_id); |
739 | | if(session) |
740 | | session->SetSecurity(lev); |
741 | | |
742 | | // No SQL injection (account name is escaped) |
743 | | loginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE username = '%s'",lev,safe_account_name.c_str()); |
744 | | zprintf("We set %s gmlevel %d\r\n",safe_account_name.c_str(),lev); |
745 | | } |
746 | | else |
747 | | { |
748 | | zprintf("No account %s found\r\n",safe_account_name.c_str()); |
749 | | } |
750 | | } |
751 | | |
752 | | /// Set password for account |
753 | | void CliSetPassword(char *command,pPrintf zprintf) |
754 | | { |
755 | | ///- Get the command line arguments |
756 | | char *szAcc = strtok(command," "); |
757 | | char *szPassword1 = strtok(NULL," "); |
758 | | char *szPassword2 = strtok(NULL," "); |
759 | | |
760 | | if(!szAcc||!szPassword1 || !szPassword2) |
761 | | { |
762 | | zprintf("Syntax is: setpass $account $password $password\r\n"); |
763 | | return; |
764 | | } |
765 | | |
766 | | std::string account_name; |
767 | | if(!consoleToUtf8(szAcc,account_name)) // convert from console encoding to utf8 |
768 | | return; |
769 | | |
770 | | std::string pass1; |
771 | | if(!consoleToUtf8(szPassword1,pass1)) // convert from console encoding to utf8 |
772 | | return; |
773 | | |
774 | | std::string pass2; |
775 | | if(!consoleToUtf8(szPassword2,pass2)) // convert from console encoding to utf8 |
776 | | return; |
777 | | |
778 | | uint32 acc_id = accmgr.GetId(szAcc); |
779 | | if (!acc_id) |
780 | | { |
781 | | zprintf("Account '%s' does not exist!\r\n", account_name.c_str()); |
782 | | return; |
783 | | } |
784 | | |
785 | | if (pass1 != pass2) |
786 | | { |
787 | | zprintf("Password does not match the confirm password, password not changed!\r\n"); |
788 | | return; |
789 | | } |
790 | | |
791 | | AccountOpResult result = accmgr.ChangePassword(acc_id, pass1); |
792 | | |
793 | | switch(result) |
794 | | { |
795 | | case AOR_OK: |
796 | | zprintf("The password was changed for account '%s' (ID: %u).\r\n",account_name.c_str(),acc_id); |
797 | | break; |
798 | | case AOR_PASS_TOO_LONG: |
799 | | zprintf("Password can't be longer than 16 characters (client limit), password not changed!\r\n"); |
800 | | break; |
801 | | case AOR_NAME_NOT_EXIST: |
802 | | zprintf("Account '%s' does not exist!\r\n", account_name.c_str()); |
803 | | break; |
804 | | case AOR_DB_INTERNAL_ERROR: |
805 | | zprintf("Password not changed! (probably sql file format was updated)\r\n"); |
806 | | break; |
807 | | default: |
808 | | zprintf("Password not changed! (unknown error\r\n"); |
809 | | break; |
810 | | } |
| 216 | SendSysMessage("====================================================================="); |
| 217 | return true; |
853 | | zprintf("User %s with password %s NOT created (unknown error)\r\n",account_name.c_str(),password.c_str()); |
854 | | break; |
855 | | } |
856 | | } |
857 | | |
858 | | /// Command parser and dispatcher |
859 | | void ParseCommand( pPrintf zprintf, char* input) |
860 | | { |
861 | | unsigned int x; |
862 | | bool bSuccess=false; |
863 | | if (!input) |
864 | | return; |
865 | | |
866 | | unsigned int l=strlen(input); |
867 | | char *supposedCommand=NULL,* arguments=(char*)(""); |
868 | | if(l) |
869 | | { |
870 | | ///- Get the command and the arguments |
871 | | supposedCommand = strtok(input," "); |
872 | | if (supposedCommand) |
873 | | { |
874 | | if (l>strlen(supposedCommand)) |
875 | | arguments=&input[strlen(supposedCommand)+1]; |
876 | | |
877 | | ///- Circle through the command table and, if found, put the command in the queue |
878 | | for ( x=0;x<CliTotalCmds;x++) |
879 | | if(!strcmp(Commands[x].cmd,supposedCommand)) |
880 | | { |
881 | | sWorld.QueueCliCommand(new CliCommandHolder(&Commands[x], arguments, zprintf)); |
882 | | bSuccess=true; |
883 | | break; |
884 | | } |
885 | | |
886 | | ///- Display an error message if the command is unknown |
887 | | if(x==CliTotalCmds) |
888 | | zprintf("Unknown command: %s\r\n", input); |
889 | | } |
890 | | } |
891 | | if (!bSuccess) |
892 | | zprintf("TC>"); |
893 | | } |
894 | | |
895 | | /// Kick a character out of the realm |
896 | | void CliKick(char*command,pPrintf zprintf) |
897 | | { |
898 | | char *kickName = strtok(command, " "); |
899 | | |
900 | | if (!kickName) |
901 | | { |
902 | | zprintf("Syntax is: kick $charactername\r\n"); |
903 | | return; |
904 | | } |
905 | | |
906 | | std::string name; |
907 | | if(!consoleToUtf8(kickName,name)) // convert from console encoding to utf8 |
908 | | return; |
909 | | |
910 | | if(!normalizePlayerName(name)) |
911 | | return; |
912 | | |
913 | | sWorld.KickPlayer(name); |
914 | | } |
915 | | |
916 | | /// Teleport a character to location |
917 | | void CliTele(char*command,pPrintf zprintf) |
918 | | { |
919 | | char *charName = strtok(command, " "); |
920 | | char *locName = strtok(NULL, " "); |
921 | | |
922 | | if (!charName || !locName) |
923 | | { |
924 | | zprintf("Syntax is: tele $charactername $location\r\n"); |
925 | | return; |
926 | | } |
927 | | |
928 | | std::string name = charName; |
929 | | if(!consoleToUtf8(charName,name)) // convert from console encoding to utf8 |
930 | | return; |
931 | | |
932 | | if(!normalizePlayerName(name)) |
933 | | return; |
934 | | |
935 | | std::string location; |
936 | | if(!consoleToUtf8(locName,location)) // convert from console encoding to utf8 |
937 | | return; |
938 | | |
939 | | WorldDatabase.escape_string(location); |
940 | | QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM game_tele WHERE name = '%s'",location.c_str()); |
941 | | if (!result) |
942 | | { |
943 | | zprintf(objmgr.GetTrinityStringForDBCLocale(LANG_COMMAND_TELE_NOTFOUND),"\r\n"); |
944 | | return; |
945 | | } |
946 | | |
947 | | Field *fields = result->Fetch(); |
948 | | float x = fields[0].GetFloat(); |
949 | | float y = fields[1].GetFloat(); |
950 | | float z = fields[2].GetFloat(); |
951 | | float ort = fields[3].GetFloat(); |
952 | | int mapid = fields[4].GetUInt16(); |
953 | | delete result; |
954 | | |
955 | | if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) |
956 | | { |
957 | | zprintf(objmgr.GetTrinityStringForDBCLocale(LANG_INVALID_TARGET_COORD),"\r\n",x,y,mapid); |
958 | | return; |
959 | | } |
960 | | |
961 | | Player *chr = objmgr.GetPlayer(name.c_str()); |
962 | | if (chr) |
963 | | { |
964 | | |
965 | | if(chr->IsBeingTeleported()==true) |
966 | | { |
967 | | zprintf(objmgr.GetTrinityStringForDBCLocale(LANG_IS_TELEPORTED),"\r\n",chr->GetName()); |
968 | | return; |
969 | | } |
970 | | |
971 | | if(chr->isInFlight()) |
972 | | { |
973 | | zprintf(objmgr.GetTrinityStringForDBCLocale(LANG_CHAR_IN_FLIGHT),"\r\n",chr->GetName()); |
974 | | return; |
975 | | } |
976 | | |
977 | | zprintf(objmgr.GetTrinityStringForDBCLocale(LANG_TELEPORTING_TO),"\r\n",chr->GetName(),"", location.c_str()); |
978 | | |
979 | | chr->SaveRecallPosition(); |
980 | | |
981 | | chr->TeleportTo(mapid,x,y,z,chr->GetOrientation()); |
982 | | } |
983 | | else if (uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str())) |
984 | | { |
985 | | zprintf(objmgr.GetTrinityStringForDBCLocale(LANG_TELEPORTING_TO),"\r\n",name.c_str(), objmgr.GetTrinityStringForDBCLocale(LANG_OFFLINE), location.c_str()); |
986 | | Player::SavePositionInDB(mapid,x,y,z,ort,MapManager::Instance().GetZoneId(mapid,x,y),guid); |
987 | | } |
988 | | else |
989 | | zprintf(objmgr.GetTrinityStringForDBCLocale(LANG_NO_PLAYER),"\r\n",name.c_str()); |
990 | | } |
991 | | |
992 | | /// Display/Define the 'Message of the day' for the realm |
993 | | void CliMotd(char*command,pPrintf zprintf) |
994 | | { |
995 | | |
996 | | if (strlen(command) == 0) |
997 | | { |
998 | | zprintf("Current Message of the day: \r\n%s\r\n", sWorld.GetMotd()); |
999 | | return; |
1000 | | } |
1001 | | else |
1002 | | { |
1003 | | std::string commandUtf8; |
1004 | | if(!consoleToUtf8(command,commandUtf8)) // convert from console encoding to utf8 |
1005 | | return; |
1006 | | |
1007 | | sWorld.SetMotd(commandUtf8); |
1008 | | zprintf("Message of the day changed to:\r\n%s\r\n", commandUtf8.c_str()); |
1009 | | } |
1010 | | } |
1011 | | |
1012 | | /// Comment me |
1013 | | /// \todo What is CorpsesErase for? |
1014 | | void CliCorpses(char*,pPrintf) |
1015 | | { |
1016 | | CorpsesErase(); |
| 255 | PSendSysMessage(LANG_ACCOUNT_NOT_CREATED,account_name.c_str()); |
| 256 | SetSentErrorMessage(true); |
| 257 | return false; |
| 258 | } |
| 259 | |
| 260 | return true; |
1029 | | } |
1030 | | |
1031 | | /// Display the server uptime |
1032 | | void CliUpTime(char*,pPrintf zprintf) |
1033 | | { |
1034 | | uint32 uptime = sWorld.GetUptime(); |
1035 | | std::string suptime = secsToTimeString(uptime,true,(uptime > 86400)); |
1036 | | zprintf("Server has been up for: %s\r\n", suptime.c_str()); |
1037 | | } |
1038 | | |
1039 | | /// Set/Unset the TBC flag for an account |
1040 | | void CliSetAddon(char *command,pPrintf zprintf) |
1041 | | { |
1042 | | ///- Get the command line arguments |
1043 | | char *szAcc = strtok(command," "); |
1044 | | char *szExp = strtok(NULL," "); |
1045 | | |
1046 | | if(!szAcc||!szExp) |
1047 | | { |
1048 | | zprintf("Syntax is: setbc $account $number (0 - normal, 1 - tbc, 2 - wotlk)>\r\n"); |
1049 | | return; |
1050 | | } |
1051 | | |
1052 | | int lev=atoi(szExp); //get int anyway (0 if error) |
1053 | | |
1054 | | if(lev < 0) |
1055 | | { |
1056 | | zprintf("Syntax is: setbc $account $number (0 - normal, 1 - tbc, 2 - wotlk)>\r\n"); |
1057 | | return; |
1058 | | } |
1059 | | |
1060 | | ///- Escape the account name to allow quotes in names |
1061 | | std::string safe_account_name; |
1062 | | if(!consoleToUtf8(szAcc,safe_account_name)) // convert from console encoding to utf8 |
1063 | | return; |
1064 | | |
1065 | | ///- Convert Account name to Upper Format |
1066 | | AccountMgr::normilizeString(safe_account_name); |
1067 | | |
1068 | | ///- Escape the account name to allow quotes in names |
1069 | | loginDatabase.escape_string(safe_account_name); |
1070 | | |
1071 | | // No SQL injection (account name is escaped) |
1072 | | QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE username = '%s'",safe_account_name.c_str()); |
1073 | | |
1074 | | if (result) |
1075 | | { |
1076 | | // No SQL injection (account name is escaped) |
1077 | | loginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE username = '%s'",lev,safe_account_name.c_str()); |
1078 | | zprintf("We set %s to expansion allowed %d\r\n",safe_account_name.c_str(),lev); |
1079 | | |
1080 | | delete result; |
1081 | | } |
1082 | | else |
1083 | | { |
1084 | | zprintf("No account %s found\r\n",safe_account_name.c_str()); |
1085 | | } |
1086 | | } |
1087 | | |
1088 | | /// Save all players |
1089 | | void CliSave(char*,pPrintf zprintf) |
1090 | | { |
1091 | | ///- Save players |
1092 | | ObjectAccessor::Instance().SaveAllPlayers(); |
1093 | | zprintf( objmgr.GetTrinityStringForDBCLocale(LANG_PLAYERS_SAVED) ); |
1094 | | |
1095 | | ///- Send a message |
1096 | | sWorld.SendWorldText(LANG_PLAYERS_SAVED); |
1097 | | } |
1098 | | |
1099 | | /// Send a message to a player in game |
1100 | | void CliSend(char *playerN,pPrintf zprintf) |
1101 | | { |
1102 | | ///- Get the command line arguments |
1103 | | char* name_str = strtok((char*)playerN, " "); |
1104 | | char* msg_str = strtok(NULL, ""); |
1105 | | |
1106 | | if(!name_str || !msg_str) |
1107 | | { |
1108 | | zprintf("Syntax: send $player $message (Player name is case sensitive)\r\n"); |
1109 | | return; |
1110 | | } |
1111 | | |
1112 | | std::string name; |
1113 | | if(!consoleToUtf8(name_str,name)) // convert from console encoding to utf8 |
1114 | | return; |
1115 | | |
1116 | | std::string msg; |
1117 | | if(!consoleToUtf8(msg_str,msg)) // convert from console encoding to utf8 |
1118 | | return; |
1119 | | |
1120 | | if(!normalizePlayerName(name)) |
1121 | | { |
1122 | | zprintf("Syntax: send $player $message (Player name is case sensitive)\r\n"); |
1123 | | return; |
1124 | | } |
1125 | | |
1126 | | ///- Find the player and check that he is not logging out. |
1127 | | Player *rPlayer = objmgr.GetPlayer(name.c_str()); |
1128 | | if(!rPlayer) |
1129 | | { |
1130 | | zprintf("Player %s not found!\r\n", name.c_str()); |
1131 | | return; |
1132 | | } |
1133 | | |
1134 | | if (rPlayer->GetSession()->isLogingOut()) |
1135 | | { |
1136 | | zprintf("Cannot send message while player %s is logging out!\r\n",name.c_str()); |
1137 | | return; |
1138 | | } |
1139 | | |
1140 | | ///- Send the message |
1141 | | //Use SendAreaTriggerMessage for fastest delivery. |
1142 | | rPlayer->GetSession()->SendAreaTriggerMessage("%s", msg.c_str()); |
1143 | | rPlayer->GetSession()->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); |
1144 | | |
1145 | | //Confirmation message |
1146 | | zprintf("Message '%s' sent to %s\r\n",msg.c_str(), name.c_str()); |
1147 | | } |
1148 | | |
1149 | | void CliPLimit(char *args,pPrintf zprintf) |
1150 | | { |
1151 | | if(*args) |
1152 | | { |
1153 | | char* param = strtok((char*)args, " "); |
1154 | | if(!param || !*param) |
1155 | | return; |
1156 | | |
1157 | | int l = strlen(param); |
1158 | | |
1159 | | if( strncmp(param,"player",l) == 0 ) |
1160 | | sWorld.SetPlayerLimit(-SEC_PLAYER); |
1161 | | else if(strncmp(param,"moderator",l) == 0 ) |
1162 | | sWorld.SetPlayerLimit(-SEC_MODERATOR); |
1163 | | else if(strncmp(param,"gamemaster",l) == 0 ) |
1164 | | sWorld.SetPlayerLimit(-SEC_GAMEMASTER); |
1165 | | else if(strncmp(param,"administrator",l) == 0 ) |
1166 | | sWorld.SetPlayerLimit(-SEC_ADMINISTRATOR); |
1167 | | else if(strncmp(param,"reset",l) == 0 ) |
1168 | | sWorld.SetPlayerLimit(sConfig.GetIntDefault("PlayerLimit", DEFAULT_PLAYER_LIMIT)); |
1169 | | else |
1170 | | { |
1171 | | int val = atoi(param); |
1172 | | if(val < -SEC_ADMINISTRATOR) val = -SEC_ADMINISTRATOR; |
1173 | | |
1174 | | sWorld.SetPlayerLimit(val); |
1175 | | } |
1176 | | |
1177 | | // kick all low security level players |
1178 | | if(sWorld.GetPlayerAmountLimit() > SEC_PLAYER) |
1179 | | sWorld.KickAllLess(sWorld.GetPlayerSecurityLimit()); |
1180 | | } |
1181 | | |
1182 | | uint32 pLimit = sWorld.GetPlayerAmountLimit(); |
1183 | | AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); |
1184 | | char const* secName = ""; |
1185 | | switch(allowedAccountType) |
1186 | | { |
1187 | | case SEC_PLAYER: secName = "Player"; break; |
1188 | | case SEC_MODERATOR: secName = "Moderator"; break; |
1189 | | case SEC_GAMEMASTER: secName = "Gamemaster"; break; |
1190 | | case SEC_ADMINISTRATOR: secName = "Administrator"; break; |
1191 | | default: secName = "<unknown>"; break; |
1192 | | } |
1193 | | |
1194 | | zprintf("Player limits: amount %u, min. security level %s.\r\n",pLimit,secName); |
| 274 | return true; |