From 32248f0880b320f103264b695efca46fa43fec69 Mon Sep 17 00:00:00 2001 From: false_genesis Date: Sat, 1 Nov 2008 10:21:43 +0000 Subject: [PATCH] * updated the ControlSocket to be telnet-compatible. original idea by klip, thx. * added optional password to the ContolSocket * fixed possible exception/crash in the DefScript variable handler (occurred when typing "getvar" into the console or telnet). maybe a very slight code speedup, too. * minor chat script updates (more telnet-friendly) * note: if you use PHP or anything that is NOT telnet/netcat to send commands to the ControlSocket, you have to terminate each line with '\n' ! --- bin/conf/PseuWoW.conf.default | 3 + bin/scripts/__core_chat.def | 39 +++++++------ src/Client/ControlSocket.cpp | 92 +++++++++++++++++++++++++++++- src/Client/ControlSocket.h | 6 ++ src/Client/DefScript/DefScript.cpp | 14 ++--- src/Client/PseuWoW.cpp | 3 +- src/Client/PseuWoW.h | 1 + 7 files changed, 130 insertions(+), 28 deletions(-) diff --git a/bin/conf/PseuWoW.conf.default b/bin/conf/PseuWoW.conf.default index 274a40d..14b4122 100644 --- a/bin/conf/PseuWoW.conf.default +++ b/bin/conf/PseuWoW.conf.default @@ -117,6 +117,9 @@ enablegui=0 rmcontrolport=8101 // IP or hostname that is allowed to connect. leave blank to allow connections from everywhere (dangerous!) rmcontrolhost=localhost +// password required to gain access. leave blank for no password. +// to authenticate, type "pw your_pass_word" into telnet or send it somehow else if not using telnet. +rmcontrolpass= // if you have exported and copied data from your original client, // set this to 1 to enable movement and everything map related. diff --git a/bin/scripts/__core_chat.def b/bin/scripts/__core_chat.def index 5d3beb0..11295eb 100644 --- a/bin/scripts/__core_chat.def +++ b/bin/scripts/__core_chat.def @@ -12,8 +12,9 @@ #permission=10 SET,lang ${@1} DEFAULT,lang 0 -SENDCHATMESSAGE,17,{${lang}},{${@def}},{${@0}} +SET,r ?{SENDCHATMESSAGE,17,{${lang}},{${@def}},{${@0}}} UNSET lang +RETURN ${r} //----------------------------------------------------------- @@ -24,7 +25,7 @@ UNSET lang // args: // @def: command to send -SAY ${#CMDCHAR}${@def} +RETURN ?{SAY ${#CMDCHAR}${@def}} //----------------------------------------------------------- @@ -56,8 +57,7 @@ IF ?{AND,?{string_is_command ${@def}} ?{SMALLER,?{GETPLAYERPERM ${@thiscmd_name} RETURN false ELSE // no: say the text as usual. - SAY,{${@0}} ${@def} - RETURN true + RETURN ?{SAY,{${@0}} ${@def}} ENDIF @@ -75,9 +75,10 @@ DEFAULT,lang ${#DEFAULTLANG} LOGDEBUG * Saying '${msg}' in lang ${lang} -SENDCHATMESSAGE,1,${lang},{${msg}} +SET,r ?{SENDCHATMESSAGE,1,${lang},{${msg}}} UNSET lang UNSET msg +RETURN ${r} //----------------------------------------------------------- @@ -93,16 +94,17 @@ default,lang 0 LOGDEBUG * Saying '${msg}' in lang ${lang} to guild -SENDCHATMESSAGE,4,${lang},{${msg}} +SET,r ?{SENDCHATMESSAGE,4,${lang},{${msg}}} UNSET lang UNSET msg +RETURN ${r} //----------------------------------------------------------- #script=sayitem #permission=0 //----------------------------------------------------------- // example script to "say" a clickable item -SAY ?{getchatitem ${@def}} +RETURN ?{SAY ?{getchatitem ${@def}}} //----------------------------------------------------------- @@ -118,16 +120,17 @@ default,lang 0 LOGDEBUG * Saying '${msg}' in lang ${lang} to party -SENDCHATMESSAGE,2,${lang},{${msg}} +SET,r ?{SENDCHATMESSAGE,2,${lang},{${msg}}} UNSET lang UNSET msg +RETURN ${r} //----------------------------------------------------------- #script=sayred //----------------------------------------------------------- // example script how to output colored text #permission=0 -SAY,{${@0}} |cffFF0000${@def} +RETURN ?{SAY,{${@0}} |cffFF0000${@def}} //----------------------------------------------------------- #script=sayv @@ -140,16 +143,16 @@ SET,vl ${@0} DEFAULT,vl 0 IF ?{NOT ?{ISSET ${vn}}} - SAY,{${vl}} * Var '${@def}' not defined. + SET,r ?{SAY,{${vl}} * Var '${@def}' not defined.} ELSE SET,vv ${${vn}} - SAY,{${vl}} * Var '${@def}' = '${vv}' + SET,r ?{SAY,{${vl}} * Var '${@def}' = '${vv}'} ENDIF UNSET vv UNSET vn UNSET vl - +RETURN ${r} //----------------------------------------------------------- #script=whisper @@ -168,10 +171,11 @@ DEFAULT,lang ${#DEFAULTLANG} LOGDEBUG * Whisp to '{${player}}' '{${msg}}' in lang '${lang}' -SENDCHATMESSAGE,7,{${lang}},{${msg}},{${player}} +SET,r ?{SENDCHATMESSAGE,7,{${lang}},{${msg}},{${player}}} UNSET lang UNSET msg UNSET player +RETURN ${r} //------------------------------------------------------------- @@ -189,9 +193,10 @@ DEFAULT,lang ${#DEFAULTLANG} LOGDEBUG * Yelling '${msg}' in lang ${lang} -SENDCHATMESSAGE,6,${lang},{${msg}} +SET,r ?{SENDCHATMESSAGE,6,${lang},{${msg}}} UNSET lang UNSET msg +RETURN ${r} //----------------------------------------------------------- @@ -205,8 +210,7 @@ IF ?{AND,?{string_is_command ${@def}} ?{SMALLER,?{GETPLAYERPERM ${@thiscmd_name} RETURN false ELSE // no: say the text as usual. - YELL,{${@0}} ${@def} - RETURN true + RETURN ?{YELL,{${@0}} ${@def}} ENDIF @@ -223,7 +227,8 @@ DEFAULT,lang ${#DEFAULTLANG} LOGDEBUG * Me ${msg} (in lang ${lang}) -SENDCHATMESSAGE,10,${lang},{${msg}} +SET,r ?{SENDCHATMESSAGE,10,${lang},{${msg}}} UNSET lang UNSET msg +RETURN ${r} diff --git a/src/Client/ControlSocket.cpp b/src/Client/ControlSocket.cpp index 56370cd..e83ef43 100644 --- a/src/Client/ControlSocket.cpp +++ b/src/Client/ControlSocket.cpp @@ -6,6 +6,7 @@ ControlSocket::ControlSocket(SocketHandler& h) : TcpSocket(h) { _ok = false; + _authed = false; DEBUG(logdebug("ControlSocket created")); } @@ -28,6 +29,12 @@ void ControlSocket::OnAccept(void) return; } + SendTelnetText(_instance->GetScripts()->variables.Get("@version")); + if(_instance->GetConf()->rmcontrolpass.size()) + { + SendTelnetText("Authentication?"); + } + _ok = true; } @@ -45,15 +52,94 @@ void ControlSocket::OnRead(void) char *buf = new char[len]; ibuf.Read(buf,len); - if(buf[0]==0) + + if(buf[0]==0 && len > 1) { // reserved for future applications } else { - if(_instance && _instance->GetScripts()) - _instance->GetScripts()->RunSingleLine(&buf[0]); + uint32 i = 0; + while(i < len) + { + if(buf[i] == 127) // ignore del key for now + continue; + if(buf[i] == 27) // escape sequence, drop whole buf (sent on direction key press for example) + break; + if(buf[i] == 8) // backspace + { + if(_str.length()) + _str.erase(_str.length() - 1); + } + else if(buf[i] == 10 || buf[i] == 13 || buf[i] == 0) // newline or \0 char + { + if(_str.length() && _instance && _instance->GetScripts()) + { + HandleString(_str); + } + _str.clear(); + } + else + { + _str += buf[i]; + } + ++i; + } } delete [] buf; } + +void ControlSocket::SendTelnetText(std::string s) +{ + s += "\n\r"; + SendBuf(s.c_str(),s.size()); +} + +void ControlSocket::_Execute(std::string s) +{ + DefReturnResult& r = _instance->GetScripts()->RunSingleLine(s); + if(r.ok) + { + std::stringstream ss; + ss << "+OK"; + if(r.ret.size()) + ss << ". r: [" << r.ret << "]"; + SendTelnetText(ss.str()); + } + else + SendTelnetText("+ERR"); +} + +void ControlSocket::HandleString(std::string s) +{ + if(_instance->GetConf()->rmcontrolpass.size()) + { + if(_authed) + { + _Execute(s); + } + else + { + if(s.size() > 3 && !memicmp(s.c_str(),"pw ",3)) // string format: "pw secret12345" + { + if(_instance->GetConf()->rmcontrolpass == s.c_str() + 3) + { + logdetail("ControlSocket: Authenticated successfully with: \"%s\"",s.c_str()); + SendTelnetText("+accepted"); + _authed = true; + } + else + { + SendTelnetText("+wrong password"); + SetCloseAndDelete(true); + } + } + } + } + else + { + _Execute(s); + } +} + diff --git a/src/Client/ControlSocket.h b/src/Client/ControlSocket.h index 3fac151..ace88c4 100644 --- a/src/Client/ControlSocket.h +++ b/src/Client/ControlSocket.h @@ -14,9 +14,15 @@ public: void OnAccept(); void OnRead(); + void HandleString(std::string); + void SendTelnetText(std::string); + private: + void _Execute(std::string); PseuInstance *_instance; bool _ok; + std::string _str; + bool _authed; }; diff --git a/src/Client/DefScript/DefScript.cpp b/src/Client/DefScript/DefScript.cpp index 7fd8bc1..92593c3 100644 --- a/src/Client/DefScript/DefScript.cpp +++ b/src/Client/DefScript/DefScript.cpp @@ -1055,24 +1055,24 @@ DefXChgResult DefScriptPackage::ReplaceVars(std::string str, CmdSet *pSet, unsig return xchg; } -std::string DefScriptPackage::_NormalizeVarName(std::string vn_in, std::string sn){ - if(vn_in.empty()) - return vn_in; - std::string vn=vn_in; +std::string DefScriptPackage::_NormalizeVarName(std::string vn, std::string sn) +{ bool global=false; if(sn.empty()) global = true; while(true) { - if(vn.at(0)=='#') + if(vn.empty()) + break; + if(vn[0]=='#') global = true; - if(vn.at(0)=='#' || vn.at(0)==':') + if(vn[0]=='#' || vn[0]==':') vn.erase(0,1); else break; } - if( (!global) && (vn.at(0)!='@') ) + if( (!global) && (vn[0]!='@') ) vn=sn+"::"+vn; return vn; diff --git a/src/Client/PseuWoW.cpp b/src/Client/PseuWoW.cpp index d7a1a26..ceae02f 100644 --- a/src/Client/PseuWoW.cpp +++ b/src/Client/PseuWoW.cpp @@ -352,7 +352,7 @@ void PseuInstance::Update() { logdetail("Disconnected, switching GUI back to Loginscreen."); _gui->SetSceneState(SCENESTATE_LOGINSCREEN); - while(_gui->GetSceneState() != SCENESTATE_LOGINSCREEN) // .. and wait until scenestate is set + while(_gui && _gui->GetSceneState() != SCENESTATE_LOGINSCREEN) // .. and wait until scenestate is set Sleep(1); } } @@ -485,6 +485,7 @@ void PseuInstanceConf::ApplyFromVarSet(VarSet &v) enablegui=(bool)atoi(v.Get("ENABLEGUI").c_str()); rmcontrolport=atoi(v.Get("RMCONTROLPORT").c_str()); rmcontrolhost=v.Get("RMCONTROLHOST"); + rmcontrolpass=v.Get("RMCONTROLPASS"); useMaps=(bool)atoi(v.Get("USEMAPS").c_str()); skipaddonchat=(bool)atoi(v.Get("SKIPADDONCHAT").c_str()); dumpPackets=(uint8)atoi(v.Get("DUMPPACKETS").c_str()); diff --git a/src/Client/PseuWoW.h b/src/Client/PseuWoW.h index 9b4f658..387b94f 100644 --- a/src/Client/PseuWoW.h +++ b/src/Client/PseuWoW.h @@ -54,6 +54,7 @@ class PseuInstanceConf bool disablespellcheck; uint32 rmcontrolport; std::string rmcontrolhost; + std::string rmcontrolpass; bool useMaps; bool skipaddonchat; uint8 dumpPackets;