2008-10-02 16:23:55 -05:00
/*
2009-02-04 12:42:26 +01:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
2008-10-14 11:57:03 -05:00
*
2009-02-04 12:04:12 +01:00
* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
2008-10-02 16:23:55 -05:00
*
* 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
2008-11-15 11:56:59 -06:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2008-10-02 16:23:55 -05:00
* 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
2008-11-15 11:56:59 -06:00
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2008-10-02 16:23:55 -05:00
*/
2008-10-14 11:57:03 -05:00
/// \addtogroup Trinityd
2008-10-02 16:23:55 -05:00
/// @{
/// \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"
2008-10-26 13:32:42 -05:00
#include "Chat.h"
2008-10-02 16:23:55 -05:00
2008-10-26 13:32:42 -05:00
void utf8print ( const char * str )
2008-10-02 16:23:55 -05:00
{
#if PLATFORM == PLATFORM_WINDOWS
2008-11-30 12:47:26 -06:00
wchar_t wtemp_buf [ 6000 ];
2008-10-26 13:32:42 -05:00
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 );
2008-10-02 16:23:55 -05:00
#else
2008-11-15 11:56:59 -06:00
printf ( str );
2008-10-02 16:23:55 -05:00
#endif
2008-10-26 13:32:42 -05:00
}
2008-10-02 16:23:55 -05:00
2008-10-26 13:32:42 -05:00
/// 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 )
2008-10-02 16:23:55 -05:00
{
2008-10-26 13:32:42 -05:00
if ( !* args )
return false ;
2008-10-02 16:23:55 -05:00
2008-10-26 13:32:42 -05:00
///- Get the account name from the command line
char * account_name_str = strtok (( char * ) args , " " );
if ( ! account_name_str )
return false ;
2008-10-02 16:23:55 -05:00
2008-10-26 13:32:42 -05:00
std :: string account_name = account_name_str ;
if ( ! AccountMgr :: normilizeString ( account_name ))
2008-10-02 16:23:55 -05:00
{
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_ACCOUNT_NOT_EXIST , account_name . c_str ());
SetSentErrorMessage ( true );
return false ;
2008-10-02 16:23:55 -05:00
}
2008-10-26 13:32:42 -05:00
uint32 account_id = accmgr . GetId ( account_name );
2008-10-02 16:23:55 -05:00
if ( ! account_id )
{
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_ACCOUNT_NOT_EXIST , account_name . c_str ());
SetSentErrorMessage ( true );
return false ;
2008-10-02 16:23:55 -05:00
}
2008-10-26 13:32:42 -05:00
/// Commands not recommended call from chat, but support anyway
if ( m_session )
2008-10-02 16:23:55 -05:00
{
2008-10-26 13:32:42 -05:00
uint32 targetSecurity = accmgr . GetSecurity ( account_id );
2008-10-02 16:23:55 -05:00
2008-10-26 13:32:42 -05:00
/// can delete only for account with less security
/// This is also reject self apply in fact
if ( targetSecurity >= m_session -> GetSecurity ())
2008-10-02 16:23:55 -05:00
{
2008-10-26 13:32:42 -05:00
SendSysMessage ( LANG_YOURS_SECURITY_IS_LOW );
SetSentErrorMessage ( true );
return false ;
2008-10-02 16:23:55 -05:00
}
}
2008-10-26 13:32:42 -05:00
AccountOpResult result = accmgr . DeleteAccount ( account_id );
2008-10-02 16:23:55 -05:00
switch ( result )
{
case AOR_OK :
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_ACCOUNT_DELETED , account_name . c_str ());
2008-10-02 16:23:55 -05:00
break ;
case AOR_NAME_NOT_EXIST :
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_ACCOUNT_NOT_EXIST , account_name . c_str ());
SetSentErrorMessage ( true );
return false ;
2008-10-02 16:23:55 -05:00
case AOR_DB_INTERNAL_ERROR :
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_ACCOUNT_NOT_DELETED_SQL_ERROR , account_name . c_str ());
SetSentErrorMessage ( true );
return false ;
2008-10-02 16:23:55 -05:00
default :
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_ACCOUNT_NOT_DELETED , account_name . c_str ());
SetSentErrorMessage ( true );
return false ;
2008-10-02 16:23:55 -05:00
}
2008-10-26 13:32:42 -05:00
2008-11-15 11:56:59 -06:00
return true ;
2008-10-02 16:23:55 -05:00
}
2008-10-26 13:32:42 -05:00
bool ChatHandler :: HandleCharacterDeleteCommand ( const char * args )
2008-10-02 16:23:55 -05:00
{
2008-10-26 13:32:42 -05:00
if ( !* args )
return false ;
2008-10-02 16:23:55 -05:00
2008-11-15 11:56:59 -06:00
char * character_name_str = strtok (( char * ) args , " " );
2008-10-02 16:23:55 -05:00
if ( ! character_name_str )
2008-11-15 11:56:59 -06:00
return false ;
2008-10-02 16:23:55 -05:00
2008-10-26 13:32:42 -05:00
std :: string character_name = character_name_str ;
2008-10-02 16:23:55 -05:00
if ( ! normalizePlayerName ( character_name ))
2008-11-15 11:56:59 -06:00
return false ;
2008-10-02 16:23:55 -05:00
uint64 character_guid ;
uint32 account_id ;
2008-11-15 11:56:59 -06:00
Player * player = objmgr . GetPlayer ( character_name . c_str ());
2008-10-02 16:23:55 -05:00
if ( player )
{
character_guid = player -> GetGUID ();
account_id = player -> GetSession () -> GetAccountId ();
player -> GetSession () -> KickPlayer ();
}
else
{
character_guid = objmgr . GetPlayerGUIDByName ( character_name );
if ( ! character_guid )
{
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_NO_PLAYER , character_name . c_str ());
SetSentErrorMessage ( true );
return false ;
2008-10-02 16:23:55 -05:00
}
account_id = objmgr . GetPlayerAccountIdByGUID ( character_guid );
}
2008-11-15 11:56:59 -06:00
std :: string account_name ;
2008-10-26 13:32:42 -05:00
accmgr . GetName ( account_id , account_name );
2008-10-02 16:23:55 -05:00
2008-11-15 11:56:59 -06:00
Player :: DeleteFromDB ( character_guid , account_id , true );
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_CHARACTER_DELETED , character_name . c_str (), GUID_LOPART ( character_guid ), account_name . c_str (), account_id );
return true ;
2008-10-02 16:23:55 -05:00
}
/// Exit the realm
2008-10-26 13:32:42 -05:00
bool ChatHandler :: HandleServerExitCommand ( const char * args )
2008-10-02 16:23:55 -05:00
{
2008-10-26 13:32:42 -05:00
SendSysMessage ( LANG_COMMAND_EXIT );
2008-11-20 16:16:57 -06:00
World :: StopNow ( SHUTDOWN_EXIT_CODE );
2008-11-15 11:56:59 -06:00
return true ;
2008-10-02 16:23:55 -05:00
}
/// Display info on users currently in the realm
2008-10-26 13:32:42 -05:00
bool ChatHandler :: HandleAccountOnlineListCommand ( const char * args )
2008-10-02 16:23:55 -05:00
{
///- Get the list of accounts ID logged to the realm
QueryResult * resultDB = CharacterDatabase . Query ( "SELECT name,account FROM characters WHERE online > 0" );
if ( ! resultDB )
2008-10-26 13:32:42 -05:00
return true ;
2008-10-02 16:23:55 -05:00
///- Display the list of account/characters online
2008-10-26 13:32:42 -05:00
SendSysMessage ( "=====================================================================" );
SendSysMessage ( LANG_ACCOUNT_LIST_HEADER );
SendSysMessage ( "=====================================================================" );
2008-10-02 16:23:55 -05:00
///- 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
2009-01-04 17:20:23 +01:00
QueryResult * resultLogin = LoginDatabase . PQuery ( "SELECT username, last_ip, gmlevel, expansion FROM account WHERE id = '%u'" , account );
2008-10-02 16:23:55 -05:00
if ( resultLogin )
{
Field * fieldsLogin = resultLogin -> Fetch ();
2008-10-26 13:32:42 -05:00
PSendSysMessage ( "|%15s| %20s | %15s |%4d|%5d|" ,
2008-10-02 16:23:55 -05:00
fieldsLogin [ 0 ]. GetString (), name . c_str (), fieldsLogin [ 1 ]. GetString (), fieldsLogin [ 2 ]. GetUInt32 (), fieldsLogin [ 3 ]. GetUInt32 ());
delete resultLogin ;
}
else
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_ACCOUNT_LIST_ERROR , name . c_str ());
2008-10-02 16:23:55 -05:00
} while ( resultDB -> NextRow ());
delete resultDB ;
2008-10-26 13:32:42 -05:00
SendSysMessage ( "=====================================================================" );
return true ;
2008-10-02 16:23:55 -05:00
}
/// Create an account
2008-10-26 13:32:42 -05:00
bool ChatHandler :: HandleAccountCreateCommand ( const char * args )
2008-10-02 16:23:55 -05:00
{
2008-10-26 13:32:42 -05:00
if ( !* args )
return false ;
2008-10-02 16:23:55 -05:00
///- %Parse the command line arguments
2008-10-26 13:32:42 -05:00
char * szAcc = strtok (( char * ) args , " " );
2008-10-02 16:23:55 -05:00
char * szPassword = strtok ( NULL , " " );
if ( ! szAcc || ! szPassword )
2008-11-15 11:56:59 -06:00
return false ;
2008-10-02 16:23:55 -05:00
2008-10-26 13:32:42 -05:00
// normilized in accmgr.CreateAccount
std :: string account_name = szAcc ;
std :: string password = szPassword ;
2008-10-02 16:23:55 -05:00
AccountOpResult result = accmgr . CreateAccount ( account_name , password );
switch ( result )
{
case AOR_OK :
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_ACCOUNT_CREATED , account_name . c_str ());
2008-10-02 16:23:55 -05:00
break ;
case AOR_NAME_TOO_LONG :
2008-10-26 13:32:42 -05:00
SendSysMessage ( LANG_ACCOUNT_TOO_LONG );
SetSentErrorMessage ( true );
return false ;
2008-10-02 16:23:55 -05:00
case AOR_NAME_ALREDY_EXIST :
2008-10-26 13:32:42 -05:00
SendSysMessage ( LANG_ACCOUNT_ALREADY_EXIST );
SetSentErrorMessage ( true );
return false ;
2008-10-02 16:23:55 -05:00
case AOR_DB_INTERNAL_ERROR :
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_ACCOUNT_NOT_CREATED_SQL_ERROR , account_name . c_str ());
SetSentErrorMessage ( true );
return false ;
2008-10-02 16:23:55 -05:00
default :
2008-10-26 13:32:42 -05:00
PSendSysMessage ( LANG_ACCOUNT_NOT_CREATED , account_name . c_str ());
SetSentErrorMessage ( true );
return false ;
2008-10-02 16:23:55 -05:00
}
2008-11-15 11:56:59 -06:00
return true ;
2008-10-02 16:23:55 -05:00
}
/// Set the level of logging
2008-10-26 13:32:42 -05:00
bool ChatHandler :: HandleServerSetLogLevelCommand ( const char * args )
2008-10-02 16:23:55 -05:00
{
2008-10-26 13:32:42 -05:00
if ( !* args )
return false ;
2008-10-02 16:23:55 -05:00
2008-10-26 13:32:42 -05:00
char * NewLevel = strtok (( char * ) args , " " );
if ( ! NewLevel )
2008-11-15 11:56:59 -06:00
return false ;
2008-10-02 16:23:55 -05:00
2008-10-26 13:32:42 -05:00
sLog . SetLogLevel ( NewLevel );
2008-11-15 11:56:59 -06:00
return true ;
2008-10-02 16:23:55 -05:00
}
2009-01-01 19:32:44 -06:00
/// set diff time record interval
bool ChatHandler :: HandleServerSetDiffTimeCommand ( const char * args )
{
if ( !* args )
return false ;
char * NewTimeStr = strtok (( char * ) args , " " );
if ( ! NewTimeStr )
return false ;
int32 NewTime = atoi ( NewTimeStr );
if ( NewTime < 0 )
return false ;
sWorld . SetRecordDiffInterval ( NewTime );
printf ( "Record diff every %u ms \n " , NewTime );
return true ;
}
2008-10-02 16:23:55 -05:00
/// @}
#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
2008-10-12 17:35:16 -05:00
printf ( "TC>" );
2008-10-02 16:23:55 -05:00
///- As long as the World is running (no World::m_stopEvent), get the command line and handle it
2008-11-20 16:16:57 -06:00
while ( ! World :: IsStopped ())
2008-10-02 16:23:55 -05:00
{
fflush ( stdout );
#ifdef linux
2008-11-20 16:16:57 -06:00
while ( ! kb_hit_return () && ! World :: IsStopped ())
2008-10-02 16:23:55 -05:00
// With this, we limit CLI to 10commands/second
usleep ( 100 );
2008-11-20 16:16:57 -06:00
if ( World :: IsStopped ())
2008-10-02 16:23:55 -05:00
break ;
#endif
2008-10-26 13:32:42 -05:00
char * command_str = fgets ( commandbuf , sizeof ( commandbuf ), stdin );
if ( command_str != NULL )
2008-10-02 16:23:55 -05:00
{
2008-10-26 13:32:42 -05:00
for ( int x = 0 ; command_str [ x ]; x ++ )
if ( command_str [ x ] == '\r' || command_str [ x ] == '\n' )
2008-11-15 11:56:59 -06:00
{
command_str [ x ] = 0 ;
break ;
}
2008-10-26 13:32:42 -05:00
2008-11-15 11:56:59 -06:00
if ( !* command_str )
2008-10-02 16:23:55 -05:00
{
2008-10-26 13:32:42 -05:00
printf ( "TC>" );
continue ;
2008-10-02 16:23:55 -05:00
}
2008-10-26 13:32:42 -05:00
std :: string command ;
if ( ! consoleToUtf8 ( command_str , command )) // convert from console encoding to utf8
{
printf ( "TC>" );
continue ;
}
sWorld . QueueCliCommand ( & utf8print , command . c_str ());
2008-10-02 16:23:55 -05:00
}
else if ( feof ( stdin ))
2008-11-15 11:56:59 -06:00
{
2008-11-20 16:16:57 -06:00
World :: StopNow ( SHUTDOWN_EXIT_CODE );
2008-11-15 11:56:59 -06:00
}
2008-10-02 16:23:55 -05:00
}
///- End the database thread
WorldDatabase . ThreadEnd (); // free mySQL thread resources
}
2009-02-17 20:07:49 -06:00