/////////////////////////////////////////////////////////// ///////////////// Have an itch? Scratch it! /////////////// ///////////////////////// SCRATCH ///////////////////////// ///////////////////// A MUD Server //////////////////// ///////////////////// By: Jared Devall //////////////////// ///////////////////// Thanks: //////////////////// ///////////////////// DIKU/Merc/ROM //////////////////// ///////////////////// Aetas/Deus Gang //////////////////// ///////////////////// Beej //////////////////// /////////////////////////////////////////////////////////// #include "handler.h" #include "avatar.h" #include "world.h" #include "stringutil.h" #include "commandTable.h" #include "timestamp.h" #include <arpa/telnet.h> #include <iostream> #include <cstring> #include <list> using namespace std; void GetNameHandler::Enter( Avatar * avatar ) { } void GetNameHandler::Exit( Avatar * avatar ) { delete this; return; } void GetNameHandler::Handle( Avatar * avatar, const string &input) { if ( input.empty() ) return; if ( !avatar->SetName( input ) ) { avatar->Send( "Names must be 3-15 characters in length.\n\r" ); return; } avatar->ReplaceHandler( new CheckNameHandler ); } string GetNameHandler::Prompt( Avatar * avatar ) { return "Give us a name: "; } void InputHandler::Enter( Avatar * avatar ) { } void InputHandler::Exit( Avatar * avatar ) { delete this; } void InputHandler::Handle( Avatar * avatar, const string &input ) { if ( input.empty() ) return; CommandTable::Instance().Execute( avatar, input ); } string InputHandler::Prompt( Avatar * avatar ) { string buf; string prompt; prompt = avatar->Get( "prompt" ); if ( prompt.empty() ) { prompt = "%R> "; } for ( string::iterator cChar = prompt.begin(); cChar != prompt.end(); ++cChar ) { if ( (*cChar) == '%' ) { ++cChar; switch ( (*cChar) ) { case 'R': buf << "The Void"; break; case 'T': buf << Timestamp::Instance().GetTime(); break; case 's': buf << ' '; break; case 'c': buf << "\n\r"; break; case '%': buf << '%'; break; default: string buf2; buf2 << "Invalid escape code: " << (*cChar) << "\n\r"; avatar->Send( buf2 ); } } else { buf << (*cChar); } } buf << "{x"; return buf; } ///////////////////// checkNameHandler /////////////////////// void CheckNameHandler::Enter( Avatar * avatar ) { if ( !avatar->Load() ) { avatar->Send( "That username does not exist.\n\r" ); } else { string name; avatar->Send( "Username found.\n\r" ); avatar->ReplaceHandler( new GetPasswordHandler ); } } void CheckNameHandler::Exit( Avatar * avatar ) { delete this; } void CheckNameHandler::Handle( Avatar * avatar, const string &input) { if ( input.empty() ) return; switch ( input[0] ) { case 'Y': case 'y': avatar->Send( "User created.\n\r" ); avatar->ReplaceHandler( new GetPasswordHandler ); break; case 'n': case 'N': avatar->Send( "User not created.\n\r" ); avatar->ReplaceHandler( new GetNameHandler ); break; } } string CheckNameHandler::Prompt( Avatar * avatar ) { return "Create a new User? [Y/N] "; } ///////////////////// GetPasswordHandler /////////////////////// string thePassword; int tries = 0; void GetPasswordHandler::Enter( Avatar * avatar ) { static const char echo_off[] = {IAC, WILL, TELOPT_ECHO, '\0'}; avatar->Send( echo_off ); //avatar->GetSocket()->FlushInput( ); } void GetPasswordHandler::Exit( Avatar * avatar ) { static const char echo_on[] = {IAC, WONT, TELOPT_ECHO, '\0'}; avatar->Send( echo_on ); delete this; } void GetPasswordHandler::Handle( Avatar * avatar, const string &input ) { list< Avatar *>::iterator a_it; if ( input.empty() ) return; thePassword = avatar->Get( "password" ); if ( thePassword.empty() ) { if ( avatar->Set( "password", avatar->EncryptPassword( input ) ) ) { avatar->Send( "Password Acceptable.\n\r" ); } } else { if ( avatar->VerifyPassword( input ) ) { avatar->Send( "Passwords match.\n\r\n\r" ); avatar->Set( "login", Timestamp::Instance().GetDateTime() ); avatar->Save(); avatar->Load(); for ( a_it = World::Instance()._avatarList.begin(); a_it != World::Instance()._avatarList.end(); ++a_it ) { if ( ( (*a_it) != avatar ) && ( (*a_it)->GetStatus() == CONNECTED ) && ( (*a_it)->Get( "name" ) == avatar->Get( "name" ) ) ) { int previous_descriptor = (*a_it)->GetSocket()->GetDescriptor(); (*a_it)->GetSocket()->SetDescriptor( avatar->GetSocket()->GetDescriptor() ); avatar->GetSocket()->SetDescriptor( previous_descriptor ); avatar->SetDisconnected( true ); (*a_it)->Send( "You have reconnected.\n\r" ); (*a_it)->Set( "login", Timestamp::Instance().GetDateTime() ); string buf; buf << "## " << avatar->Get( "name" ) << " has reconnected.\n\r"; World::Instance().Broadcast( buf, WCONNECTED ); cout << avatar->Get( "name" ) << " has reconnected @ " << Timestamp::Instance().GetDateTime() << "\n\r"; return; } } string buf; avatar->SetStatus( CONNECTED ); buf << "## " << avatar->Get( "name" ) << " has connected.\n\r"; World::Instance().Broadcast( buf, WCONNECTED ); cout << avatar->Get( "name" ) << " has connected @ " << Timestamp::Instance().GetDateTime() << "\n\r"; avatar->ReplaceHandler( new InputHandler ); } else { tries++; avatar->Send( "Passwords do not match.\n\r" ); thePassword.erase(); switch ( tries ) { default: case 3: avatar->Send( "No more chances.\n\r" ); avatar->ClearPassword(); avatar->ReplaceHandler( new GetNameHandler ); tries = 0; break; case 2: avatar->Send( "1 more chance.\n\r" ); break; case 1: avatar->Send( "2 more chances.\n\r" ); break; case 0: avatar->Send( "3 more chances.\n\r" ); break; } } } } string GetPasswordHandler::Prompt( Avatar * avatar ) { return "Enter password: "; }