#include <cstdarg>
#include <cstdio>
#include <fstream>
#include <map>
#include <mysql/mysql.h>
#include "world.h"
#include "smysql.h"
#include "avatar.h"
#include "colorTable.h"
#include "stringutil.h"
#include "timestamp.h"
#include "stringutil.h"
#include "log.h"
#include "commandTable.h"
using namespace std;
bool Char::SetName( const string &name )
{
string buf;
if ( name.length() < 3 || name.length() > 15 )
{
buf << name.length();
return false;
}
buf << name;
for ( string::iterator cChar = buf.begin(); cChar != buf.end(); ++cChar )
{
if ( !isalnum(*cChar) && (*cChar) != '\'' )
return false;
}
Set( "name", name );
return true;
}
bool Char::Set( const string &set, const string &value )
{
string buf;
if ( !strcasecmp( set, "title" ) )
{
if ( value[0] != ',' && value[0] != '\'' && value[0] != ' ' )
buf << " " << value;
else
buf << value;
_info[set] = buf;
}
else
_info[set] = value;
return true;
}
string Char::Get( const string &get )
{
if ( get == "name" )
{
string s = _info[get];
if ( s.empty() )
return s;
s[0] = toupper(s[0]);
return s;
}
return _info[get];
}
Avatar::Avatar( )
{
_disconnected = false;
_socket = new Socket;
_gotInput = false;
_status = LOGIN;
}
Avatar::~Avatar( )
{
if ( _socket )
{
if ( !_socket->GetSocketIP().empty() )
{
SocketServer::Instance()._socketList.remove( _socket );
SocketServer::Instance().KillSocket( _socket );
if ( Get( "name" ).empty() )
cout << _socket->GetSocketIP() << " has disconnected @ " << Timestamp::Instance().GetDateTime() << "\n\r";
else
cout << Get( "name" ) << " has disconnected @ " << Timestamp::Instance().GetDateTime() << "\n\r";
}
}
delete _socket;
}
bool Avatar::Load( )
{
string query;
Mysql::LMAP::iterator avatar_info;
Mysql::RESULT z;
query << "SELECT * FROM user WHERE username='" << Mysql::Instance().EscapeString( Get( "name" ) ) << "'";
if ( !Mysql::Instance().Load( query.c_str() ) )
return false;
z = Mysql::Instance()._info;
avatar_info = z[0].find("username");
Set( "name", avatar_info->second );
avatar_info = z[0].find("password");
Set( "password", avatar_info->second );
avatar_info = z[0].find("_group");
Set( "group", avatar_info->second );
avatar_info = z[0].find("reply");
Set( "reply", avatar_info->second );
avatar_info = z[0].find("title");
Set( "title", avatar_info->second );
avatar_info = z[0].find("login");
Set( "login", avatar_info->second );
avatar_info = z[0].find("prompt");
Set( "prompt", avatar_info->second );
avatar_info = z[0].find("version");
Set( "version", avatar_info->second );
avatar_info = z[0].find("last_room");
Set( "last_room", avatar_info->second );
_room = NULL;
return true;
}
bool Avatar::Save( )
{
string query;
if ( Get( "group" ).empty() )
{
Create();
return true;
}
query << "UPDATE user SET username='" << Mysql::Instance().EscapeString( Get( "name" ) ) << "', password='" << Mysql::Instance().EscapeString( Get( "password" ) ) << "', _group='" << Get( "group" ) << "',";
query << " login='" << Mysql::Instance().EscapeString( Get( "login" ) ) << "', reply='" << Mysql::Instance().EscapeString( Get( "reply" ) ) << "', title='" << Mysql::Instance().EscapeString( Get( "title" ) ) << "',";
query << " prompt='" << Mysql::Instance().EscapeString( Get( "prompt" ) ) << "', last_room=";
if ( _room )
query << _room->id;
else
query << Get("last_room");
query << ", version=" << Get("version") << " WHERE username='" << Mysql::Instance().EscapeString( Get( "name" ) ) << "'";
Mysql::Instance().RealQuery( query.c_str() );
return true;
}
bool Avatar::Create( )
{
string query;
query << "INSERT INTO user ( username, password ) VALUES ( '" << Mysql::Instance().EscapeString( Get( "name" ) ) << "', '" << Get( "password" ) << "' )";
Mysql::Instance().Query( query.c_str() );
return true;
}
bool Avatar::Delete( )
{
string query;
query << "DELETE FROM user WHERE username='" << Mysql::Instance().EscapeString( Get( "name" ) ) << "'";
Mysql::Instance().Query( query.c_str() );
return true;
}
STATUS Avatar::GetStatus( )
{
return _status;
}
void Avatar::SetStatus( STATUS status )
{
_status = status;
}
void Avatar::Send( char * message, ... )
{
va_list args;
char buf[MAX_BUFFER];
string buf2;
va_start( args, message );
vsprintf( buf, message, args);
buf2 = _socket->GetOutput();
buf2.append( buf );
_socket->SetOutput( buf2 );
va_end( args );
}
void Avatar::Send( const string &message )
{
string buf;
buf.append( message );
_socket->SetOutput( buf );
}
void Avatar::SetSocket( Socket * socket )
{
_socket = socket;
}
Socket * Avatar::GetSocket( )
{
return _socket;
}
bool Avatar::VerifyPassword( const string &password )
{
return Get( "password" ) == EncryptPassword( password );
}
string Avatar::EncryptPassword( const string &password )
{
return password; }
void Avatar::ClearPassword( )
{
string blah = "e"; blah.erase();
Set( "password", blah );
}
void Avatar::SetEdit( const string &edit )
{
if ( edit.empty() )
_edit.erase();
else
_edit = edit;
}
string Avatar::GetEdit( )
{
return _edit;
}
bool Avatar::HasPassword( )
{
return Get( "password" ).empty();
}
void Avatar::SetGotInput( bool value )
{
_gotInput = value;
}
bool Avatar::GotInput( )
{
return _gotInput;
}
void Avatar::FlushOutput( )
{
string output;
string buf2;
string buf3;
string colorClear;
output = _socket->GetOutput();
if ( output.empty() != true || _gotInput )
{
if ( output.find( string(_handlers.front()->Prompt( this ) )) != string::npos )
return;
if ( !_gotInput )
output.insert( 0, "\n\r" );
else
{
if ( _socket->GetInput().empty() )
_gotInput = false;
}
output.append( "\n\r" + _handlers.front()->Prompt( (this) ) );
_socket->SetOutput( output );
}
colorClear << ColorTable::COLOR_ESCAPE << ColorTable::COLOR_CLEAR;
buf3 = _socket->GetOutput();
buf3.append( colorClear );
for ( string::iterator cChar = buf3.begin(); cChar != buf3.end(); ++cChar )
{
if ( (*cChar) == ColorTable::COLOR_ESCAPE )
{
if ( ++cChar == buf3.end() )
break;
buf2 << ColorTable::Substitute( (*cChar) );
}
else
buf2 << (*cChar); }
_socket->SetOutput( buf2 );
}
void Avatar::SetDisconnected( bool value )
{
DoCmd( this, "save");
this->_room->_avatarList.remove(this);
_disconnected = value;
_socket->SetDisconnected( true );
}
bool Avatar::IsDisconnected( )
{
return _disconnected;
}
void Avatar::ReplaceHandler( Handler * handler )
{
PopHandler( );
StackHandler( handler );
}
void Avatar::StackHandler( Handler * handler )
{
_handlers.push_front( handler );
handler->Enter( this );
}
void Avatar::ExitHandler( )
{
PopHandler( );
_handlers.front()->Enter( this ) ;
}
void Avatar::PopHandler( )
{
Handler * previous_handler = _handlers.front();
_handlers.pop_front( );
previous_handler->Exit( this );
}
void Avatar::HandleInput( const std::string &input )
{
string::iterator cChar;
string string1;
string string2;
string2 = input;
for ( cChar = string2.begin(); cChar != string2.end(); ++cChar )
{
if ( ( (*cChar) == '\n' || (*cChar) == '\r' ) && cChar != string2.begin() )
{
_handlers.front()->Handle( this, string1 );
string1.erase();
}
else
string1 << (*cChar);
}
_handlers.front()->Handle( this, string1 );
}
bool Avatar::Set( const string &set, const string &value )
{
string buf;
if ( !strcasecmp( set, "title" ) )
{
if ( value[0] != ',' && value[0] != '\'' && value[0] != ' ' )
buf << " " << value;
else
buf << value;
_info[set] = buf;
}
else if ( !strcasecmp( set, "name" ) )
{
string buf;
if ( value.length() < 3 || value.length() > 15 )
{
buf << value.length();
Send( "Names must be 3-15 characters in length.\n\r" );
return false;
}
buf << value;
for ( string::iterator cChar = buf.begin(); cChar != buf.end(); ++cChar )
{
if ( !isalnum(*cChar) && (*cChar) != '\'' )
{
Send( "Names may only contain: alpha-numeric '\n\r" );
return false;
}
}
_info[set] = buf;
}
else if ( !strcasecmp( set, "password" ) )
_info[set] = value;
else
_info[set] = value;
return true;
}