diff --git a/src/Client/DefScript/DefScript.cpp b/src/Client/DefScript/DefScript.cpp index af818ea..68f7dd6 100644 --- a/src/Client/DefScript/DefScript.cpp +++ b/src/Client/DefScript/DefScript.cpp @@ -6,6 +6,7 @@ #include #include "VarSet.h" #include "DefScript.h" +#include "DefScriptTools.h" // --- SECTION FOR SCRIPT PACKAGES --- DefScriptPackage::DefScriptPackage() @@ -262,9 +263,8 @@ bool DefScript::AddLine(std::string l){ // --- SECTION FOR COMMAND SETS --- -CmdSet::CmdSet(DefScript *p){ +CmdSet::CmdSet(){ Clear(); - owner = p; } CmdSet::~CmdSet(){ @@ -286,17 +286,33 @@ void CmdSet::Clear() // the referred pSet is the parent from which RunScript() has been called -bool DefScriptPackage::RunScript(std::string name, CmdSet *pSet) +bool DefScriptPackage::BoolRunScript(std::string name, CmdSet *pSet) { + DefReturnResult r = RunScript(name,pSet); + return r.ok; +} + +// the referred pSet is the parent from which RunScript() has been called +DefReturnResult DefScriptPackage::RunScript(std::string name, CmdSet *pSet) +{ + DefReturnResult r; if(!ScriptExists(name)) if(!LoadByName(name)) - return false; // doesnt exist & cant be loaded + { + r.ok=false; // doesnt exist & cant be loaded + r.ret=""; + return r; + } DefScript *sc = GetScript(name); if(!sc) - return false; + { + r.ok=false; + r.ret=""; + return r; + } - CmdSet temp(sc); + CmdSet temp; if(!pSet) { pSet = &temp; @@ -306,40 +322,43 @@ bool DefScriptPackage::RunScript(std::string name, CmdSet *pSet) for(unsigned int i=0;iGetLines();i++) { - CmdSet curSet(NULL); - DefXChgResult final=ReplaceVars(sc->GetLine(i),pSet,false); - //printf("SC: \"%s\"\n",final.str.c_str()); - curSet=SplitLine(final.str); - curSet.owner=sc; // must set the owner after SplitLine() - curSet.myname=name; - curSet.caller=pSet?pSet->myname:""; - Interpret(curSet); + CmdSet mySet; + DefXChgResult final=ReplaceVars(sc->GetLine(i),pSet,0); + _DEFSC_DEBUG(printf("DefScript: \"%s\"\n",final.str.c_str())); + SplitLine(mySet,final.str); + mySet.myname=name; + mySet.caller=pSet?pSet->myname:""; + r=Interpret(mySet); + if(r.mustreturn) + { + r.mustreturn=false; + break; + } } - return true; + return r; } -bool DefScriptPackage::RunSingleLine(std::string line){ - DefXChgResult final=ReplaceVars(line,NULL,false); - CmdSet curSet=SplitLine(final.str); - return Interpret(curSet); +DefReturnResult DefScriptPackage::RunSingleLine(std::string line){ + DefXChgResult final=ReplaceVars(line,NULL,0); + CmdSet Set; + SplitLine(Set,final.str); + return Interpret(Set); } -bool DefScriptPackage::RunSingleLineFromScript(std::string line, DefScript *pScript){ - CmdSet Set(pScript); - Set.myname=pScript->GetName(); // temp fix, this needs to be cleaned up later - DefXChgResult final=ReplaceVars(line,&Set,false); - CmdSet curSet=SplitLine(final.str); - curSet.myname=pScript->GetName(); // temp fix, this needs to be cleaned up later - return Interpret(curSet); +DefReturnResult DefScriptPackage::RunSingleLineFromScript(std::string line, DefScript *pScript){ + CmdSet Set; + Set.myname=pScript->GetName(); + DefXChgResult final=ReplaceVars(line,&Set,0); + SplitLine(Set,final.str); + return Interpret(Set); } -CmdSet DefScriptPackage::SplitLine(std::string line){ +void DefScriptPackage::SplitLine(CmdSet& Set,std::string line){ unsigned int i=0; unsigned int bracketsOpen=0,curParam=0; bool cmdDefined=false; std::string tempLine; - CmdSet outSet(NULL); // extract cmd+params and txt for(i=0;i0 && t[i-1]=='$') + if(i>0 && (t[i-1]=='$' || t[i-1]=='?') ) isVar=true; if(!bo) ob=i; @@ -438,8 +456,7 @@ std::string DefScriptPackage::RemoveBracketsFromString(std::string t){ return t; } -CmdSet DefScriptPackage::RemoveBrackets(CmdSet oldSet){ - CmdSet Set=oldSet; +void DefScriptPackage::RemoveBrackets(CmdSet& Set){ std::string t; for(unsigned int a=0;a0 && str[i-1]=='?') + { + hasVar=true; + if(!bracketsOpen) + nextVar=DEFSCRIPT_FUNC; } bracketsOpen++; } @@ -507,7 +526,7 @@ DefXChgResult DefScriptPackage::ReplaceVars(std::string str, CmdSet *pSet, bool if(!bracketsOpen) { closingBracket=i; - if(!nextIsVar && isVar && !hasVar) // remove brackets in var names, like ${var{ia}ble} + if(nextVar==DEFSCRIPT_NONE && VarType!=DEFSCRIPT_NONE && !hasVar) // remove brackets in var names, like ${var{ia}ble} { str.erase(closingBracket,1); str.erase(openingBracket,1); @@ -519,66 +538,82 @@ DefXChgResult DefScriptPackage::ReplaceVars(std::string str, CmdSet *pSet, bool bLen=closingBracket-openingBracket-1; subStr=str.substr(openingBracket+1,bLen); //printf("SUBSTR: \"%s\"\n",subStr.c_str()); - xchg=ReplaceVars(subStr,pSet,nextIsVar); - if( (!nextIsVar) && hasVar && xchg.changed ) + xchg=ReplaceVars(subStr,pSet,nextVar); + if( nextVar==DEFSCRIPT_NONE && hasVar && xchg.changed ) { str.erase(openingBracket+1,subStr.length()); str.insert(openingBracket+1,xchg.str); hasVar=false; - nextIsVar=false; i-=(subStr.length()+1); hasChanged=true; } - else if( nextIsVar && hasVar && xchg.changed ) + else if( nextVar!=DEFSCRIPT_NONE && hasVar && xchg.changed ) { str.erase(openingBracket-1,bLen+3); // remove ${...} (+3 because of '${}') i-=(bLen+2); // adjust position str.insert(i,xchg.str); - //i--; hasVar=false; - nextIsVar=false; + nextVar=DEFSCRIPT_NONE; } } } } // end if '}' } // end for - if(!bracketsOpen && isVar) + if(!bracketsOpen && VarType!=DEFSCRIPT_NONE) { - std::string vname=_NormalizeVarName(str, (pSet==NULL) ? "" : pSet->myname); - if(vname[0]=='@') + if(VarType==DEFSCRIPT_VAR) { - std::stringstream vns; - std::string subs=vname.substr(1,str.length()-1); - unsigned int vn=atoi( subs.c_str() ); - vns << vn; - if(pSet && vns.str()==subs) // resolve arg macros @0 - @99 - str=pSet->arg[vn]; - else if(pSet && subs=="def") - str=pSet->defaultarg; - else if(pSet && subs=="myname") - str=pSet->myname; - else if(pSet && subs=="cmd") - str=pSet->cmd; - else if(pSet && subs=="caller") - str=pSet->caller; - else if(subs=="n") - str="\n"; - else if(variables.Exists(vname)) - str=variables.Get(vname); - else + std::string vname=_NormalizeVarName(str, (pSet==NULL) ? "" : pSet->myname); + if(vname[0]=='@') { - // TODO: call custom macro table - //... - str.clear(); - } - xchg.changed=true; - } - else - if(variables.Exists(vname)) - { - str=variables.Get(vname); + std::stringstream vns; + std::string subs=vname.substr(1,str.length()-1); + unsigned int vn=atoi( subs.c_str() ); + vns << vn; + if(pSet && vns.str()==subs) // resolve arg macros @0 - @99 + str=pSet->arg[vn]; + else if(pSet && subs=="def") + str=pSet->defaultarg; + else if(pSet && subs=="myname") + str=pSet->myname; + else if(pSet && subs=="cmd") + str=pSet->cmd; + else if(pSet && subs=="caller") + str=pSet->caller; + else if(subs=="n") + str="\n"; + else if(variables.Exists(vname)) + str=variables.Get(vname); + else + { + // TODO: call custom macro table + //... + str.clear(); + } xchg.changed=true; } + else + { + if(variables.Exists(vname)) + { + str=variables.Get(vname); + xchg.changed=true; + } + } + } + else if(VarType==DEFSCRIPT_FUNC) + { + DefReturnResult res; + if(pSet) + res=RunSingleLineFromScript(str,GetScript(pSet->myname)); + else + res=RunSingleLine(str); + str=res.ret; // returns empty string on invalid function!! + xchg.result.ok=res.ok; + if(res.ok) + xchg.changed=true; + //xchg.result.err += res.err; + } } xchg.str = str; @@ -607,12 +642,12 @@ std::string DefScriptPackage::_NormalizeVarName(std::string vn_in, std::string s return vn; } -bool DefScriptPackage::Interpret(CmdSet Set) +DefReturnResult DefScriptPackage::Interpret(CmdSet& Set) { - bool result=false; + DefReturnResult result; // first search if the script is defined in the internal functions - for(unsigned int i=0;result==false;i++) + for(unsigned int i=0;;i++) { if(functionTable[i].func==NULL || functionTable[i].name==NULL) // reached the end of the table? { @@ -621,18 +656,23 @@ bool DefScriptPackage::Interpret(CmdSet Set) if(Set.cmd==functionTable[i].name) { result=(this->*functionTable[i].func)(Set); - break; + return result; } } - // if nothing has been found its maybe an external script file to run - if(!result) + if(Set.cmd=="return") { - result=RunScript(Set.cmd, &Set); - if((!result) /*&& Script[Set.cmd]->GetDebug()*/) - std::cout << "Could not execute script command '" << Set.cmd << "'\n"; + result.mustreturn=true; + result.ret=Set.defaultarg; + return result; } + // if nothing has been found its maybe an external script file to run + result=RunScript(Set.cmd, &Set); + if((!result.ok) /*&& Script[Set.cmd]->GetDebug()*/) + std::cout << "Could not execute script command '" << Set.cmd << "'\n"; + + return result; } diff --git a/src/Client/DefScript/DefScript.h b/src/Client/DefScript/DefScript.h index fd5e312..59aacce 100644 --- a/src/Client/DefScript/DefScript.h +++ b/src/Client/DefScript/DefScript.h @@ -2,48 +2,39 @@ #ifndef __DEFSCRIPT_H #define __DEFSCRIPT_H -#define MAXARGS 99 -#ifdef _DEBUG -# define _DEFSC_DEBUG(code) code; -#else -# define _DEFSC_DEBUG(code) /* code */ -#endif - -#if COMPILER == COMPILER_MICROSOFT -typedef __int64 def_int64; -#else -typedef __int64_t def_int64; -#endif - - - #include #include #include "VarSet.h" #include "DynamicEvent.h" +#include "DefScriptDefines.h" + class DefScriptPackage; class DefScript; + +struct DefReturnResult +{ + DefReturnResult() { ok=true; mustreturn=false; ret="true"; } + DefReturnResult(bool b) { ok=b; mustreturn=false; ret=b?"true":"false"; } + bool ok; // true if the execution of the current statement was successful + bool mustreturn; + std::string ret; // return value used by ?{..} + //bool abrt; // true if ALL current script execution must be aborted. + //std::string err; // error string, including tracestack, etc. +}; + struct DefXChgResult { DefXChgResult() { changed=false; } bool changed; std::string str; -}; - -struct SecReturnResult -{ - bool ok; // true if the execution of the current statement was successful - bool abrt; // true if ALL current script execution must be aborted. - std::string ret; // return value used by ?{..} - std::string err; // error string, including tracestack, etc. -}; - + DefReturnResult result; +}; class CmdSet { public: - CmdSet(DefScript *p); + CmdSet(); ~CmdSet(); void Clear(); std::string cmd; @@ -51,13 +42,11 @@ class CmdSet { std::string defaultarg; std::string myname; std::string caller; - DefScript *owner; - void *ptr; }; struct DefScriptFunctionTable { char *name; - bool (DefScriptPackage::*func)(CmdSet Set); + DefReturnResult (DefScriptPackage::*func)(CmdSet& Set); }; class DefScript { @@ -84,9 +73,7 @@ private: unsigned char permission; bool debugmode; - DefScriptPackage *_parent; - //CmdSet _mySet; - + DefScriptPackage *_parent; }; @@ -99,29 +86,30 @@ public: DefScript *GetScript(std::string); unsigned int GetScripts(void); bool LoadScriptFromFile(std::string,std::string); - bool RunScript(std::string,CmdSet*); + DefReturnResult RunScript(std::string,CmdSet*); + bool BoolRunScript(std::string,CmdSet*); unsigned int GetScriptID(std::string); - bool RunSingleLine(std::string); + DefReturnResult RunSingleLine(std::string); bool ScriptExists(std::string); VarSet variables; void SetPath(std::string); bool LoadByName(std::string); void SetFunctionTable(DefScriptFunctionTable*); std::string _NormalizeVarName(std::string, std::string); - bool RunSingleLineFromScript(std::string line, DefScript *pScript); + DefReturnResult RunSingleLineFromScript(std::string line, DefScript *pScript); DefScript_DynamicEventMgr *GetEventMgr(void); std::string scPath; // Own executor functions void My_LoadUserPermissions(VarSet&); - bool My_Run(std::string line,std::string username); + void My_Run(std::string line,std::string username); private: - DefXChgResult ReplaceVars(std::string, CmdSet*, bool); - CmdSet SplitLine(std::string); - bool Interpret(CmdSet); - CmdSet RemoveBrackets(CmdSet); + DefXChgResult ReplaceVars(std::string str, CmdSet* pSet, unsigned char VarType); + void SplitLine(CmdSet&,std::string); + DefReturnResult Interpret(CmdSet&); + void RemoveBrackets(CmdSet&); std::string RemoveBracketsFromString(std::string); DefScriptFunctionTable *_GetFunctionTable(void) const; DefScriptFunctionTable *functionTable; @@ -132,48 +120,48 @@ private: std::map scriptPermissionMap; // Usable internal basic functions: - bool func_default(CmdSet); - bool func_set(CmdSet); - bool func_unset(CmdSet); - bool func_loaddef(CmdSet); - bool func_reloaddef(CmdSet); - bool func_out(CmdSet); - bool func_eof(CmdSet); - bool func_shdn(CmdSet); - bool func_setscriptpermission(CmdSet); - bool func_toint(CmdSet); - bool func_add(CmdSet); - bool func_sub(CmdSet); - bool func_mul(CmdSet); - bool func_div(CmdSet); - bool func_mod(CmdSet); - bool func_pow(CmdSet); - bool func_bitor(CmdSet); - bool func_bitand(CmdSet); - bool func_bitxor(CmdSet); - bool func_addevent(CmdSet); - bool func_removeevent(CmdSet); + DefReturnResult func_default(CmdSet&); + DefReturnResult func_set(CmdSet&); + DefReturnResult func_unset(CmdSet&); + DefReturnResult func_loaddef(CmdSet&); + DefReturnResult func_reloaddef(CmdSet&); + DefReturnResult func_out(CmdSet&); + DefReturnResult func_eof(CmdSet&); + DefReturnResult func_shdn(CmdSet&); + DefReturnResult func_setscriptpermission(CmdSet&); + DefReturnResult func_toint(CmdSet&); + DefReturnResult func_add(CmdSet&); + DefReturnResult func_sub(CmdSet&); + DefReturnResult func_mul(CmdSet&); + DefReturnResult func_div(CmdSet&); + DefReturnResult func_mod(CmdSet&); + DefReturnResult func_pow(CmdSet&); + DefReturnResult func_bitor(CmdSet&); + DefReturnResult func_bitand(CmdSet&); + DefReturnResult func_bitxor(CmdSet&); + DefReturnResult func_addevent(CmdSet&); + DefReturnResult func_removeevent(CmdSet&); // Useable own internal functions: - bool SCpause(CmdSet); - bool SCSendChatMessage(CmdSet); - bool SCsavecache(CmdSet); - bool SCemote(CmdSet); - bool SCfollow(CmdSet); - bool SCshdn(CmdSet); - bool SCjoinchannel(CmdSet); - bool SCleavechannel(CmdSet); - bool SCloadconf(CmdSet); - bool SCapplypermissions(CmdSet); - bool SCapplyconf(CmdSet); - bool SClog(CmdSet); - bool SClogdetail(CmdSet); - bool SClogdebug(CmdSet); - bool SClogerror(CmdSet); - bool SCcastspell(CmdSet); - bool SCqueryitem(CmdSet); - bool SCtarget(CmdSet); - bool SCloadscp(CmdSet); + DefReturnResult SCpause(CmdSet&); + DefReturnResult SCSendChatMessage(CmdSet&); + DefReturnResult SCsavecache(CmdSet&); + DefReturnResult SCemote(CmdSet&); + DefReturnResult SCfollow(CmdSet&); + DefReturnResult SCshdn(CmdSet&); + DefReturnResult SCjoinchannel(CmdSet&); + DefReturnResult SCleavechannel(CmdSet&); + DefReturnResult SCloadconf(CmdSet&); + DefReturnResult SCapplypermissions(CmdSet&); + DefReturnResult SCapplyconf(CmdSet&); + DefReturnResult SClog(CmdSet&); + DefReturnResult SClogdetail(CmdSet&); + DefReturnResult SClogdebug(CmdSet&); + DefReturnResult SClogerror(CmdSet&); + DefReturnResult SCcastspell(CmdSet&); + DefReturnResult SCqueryitem(CmdSet&); + DefReturnResult SCtarget(CmdSet&); + DefReturnResult SCloadscp(CmdSet&); // Own variable declarations std::map my_usrPermissionMap; diff --git a/src/Client/DefScript/DefScriptDefines.h b/src/Client/DefScript/DefScriptDefines.h new file mode 100644 index 0000000..f0d1561 --- /dev/null +++ b/src/Client/DefScript/DefScriptDefines.h @@ -0,0 +1,26 @@ +#ifndef DEFSCRIPTDEFINES_H +#define DEFSCRIPTDEFINES_H + +#define MAXARGS 99 +#ifdef _DEBUG +# define _DEFSC_DEBUG(code) code; +#else +# define _DEFSC_DEBUG(code) +#endif + +#if COMPILER == COMPILER_MICROSOFT +typedef __int64 int64; +typedef unsigned __int64 uint64; +#else +typedef __int64_t int64; +typedef unsigned __int64_t uint64; +#endif + +enum VariableType +{ + DEFSCRIPT_NONE=0, + DEFSCRIPT_VAR, + DEFSCRIPT_FUNC +}; + +#endif \ No newline at end of file diff --git a/src/Client/DefScript/DefScriptFunctions.cpp b/src/Client/DefScript/DefScriptFunctions.cpp index 1bc73e3..403228e 100644 --- a/src/Client/DefScript/DefScriptFunctions.cpp +++ b/src/Client/DefScript/DefScriptFunctions.cpp @@ -6,29 +6,38 @@ #include #include #include "DefScript.h" +#include "DefScriptTools.h" + +using namespace DefScriptTools; - -bool DefScriptPackage::func_shdn(CmdSet Set){ +DefReturnResult DefScriptPackage::func_shdn(CmdSet& Set){ + DefReturnResult r; //exit(0); // need to define own SCshdn(Set); - return true; + return r; } -bool DefScriptPackage::func_eof(CmdSet Set){ - // do nothing still - return true; -} - -bool DefScriptPackage::func_out(CmdSet Set){ +DefReturnResult DefScriptPackage::func_out(CmdSet& Set){ + DefReturnResult r; printf("%s\n",Set.defaultarg.c_str()); - return true; + r.ret=Set.defaultarg; + return r; } -bool DefScriptPackage::func_loaddef(CmdSet Set){ +DefReturnResult DefScriptPackage::func_loaddef(CmdSet& Set){ + DefReturnResult r; if( ScriptExists(Set.defaultarg) ) - return true; + { + r.ret="exists"; + return r; + } + return func_reloaddef(Set); +} + +DefReturnResult DefScriptPackage::func_reloaddef(CmdSet& Set){ + DefReturnResult r; bool result=false; std::string fn; if(Set.arg[0].empty()) @@ -45,267 +54,282 @@ bool DefScriptPackage::func_loaddef(CmdSet Set){ fn=Set.arg[0]; result=LoadScriptFromFile(fn,Set.defaultarg); } + r.ret=fn; if(!result) + { std::cout << "Could not load script '" << Set.defaultarg << "' [" << fn << "]\n"; - return true; + r.ret=""; + } + return r; } -bool DefScriptPackage::func_reloaddef(CmdSet Set){ - bool result=false; - std::string fn; - if(Set.arg[0].empty()) - { - result=LoadByName(Set.defaultarg); - fn=(scPath + Set.defaultarg).append(".def"); - } - else - { - std::string::size_type pos = Set.arg[0].find('/'); - if(pos == std::string::npos) - fn=scPath+Set.arg[0]; - else - fn=Set.arg[0]; - result=LoadScriptFromFile(fn,Set.defaultarg); - } - if(!result) - std::cout << "Could not load script '" << Set.defaultarg << "' [" << fn << "]\n"; - return true; -} - -bool DefScriptPackage::func_unset(CmdSet Set){ +DefReturnResult DefScriptPackage::func_unset(CmdSet& Set){ + DefReturnResult r; + r.ret=Set.defaultarg; if(Set.defaultarg.empty()){ //if(curIsDebug) // printf("Can't unset, no variable name given.\n"); - return false; + return r; } if(Set.defaultarg.at(0)=='@'){ //if(curIsDebug) // printf("Can't unset macros!\n"); - return false; + return r; } std::string vn=_NormalizeVarName(Set.defaultarg, Set.caller); variables.Unset(vn); //std::cout<<"Unset var '"<defaultarg<<"'\n"; - return true; + return r; } -bool DefScriptPackage::func_set(CmdSet Set){ +DefReturnResult DefScriptPackage::func_set(CmdSet& Set){ + DefReturnResult r; if(Set.arg[0].empty()){ //if(curIsDebug) // printf("Can't assign value, no variable name given.\n"); - return false; + return r; } if(Set.arg[0].at(0)=='@'){ //if(curIsDebug) // printf("Can't assign value to a macro!\n"); - return false; + return r; } std::string vname,vval=Set.defaultarg; vname=_NormalizeVarName(Set.arg[0], Set.myname); - if(!stricmp(Set.arg[1].c_str(),"onfail") && vval.find("${")!=std::string::npos) - vval=Set.arg[2]; + //if(!stricmp(Set.arg[1].c_str(),"onfail") && vval.find("${")!=std::string::npos) + // vval=Set.arg[2]; variables.Set(vname,vval); - - if(Set.owner && Set.owner->GetDebug()) + r.ret=vval; + + DefScript *sc = GetScript(Set.myname); + if(sc && sc->GetDebug()) printf("VAR: %s = '%s'\n",vname.c_str(),vval.c_str()); - return true; + return r; } -bool DefScriptPackage::func_default(CmdSet Set){ +DefReturnResult DefScriptPackage::func_default(CmdSet& Set){ + DefReturnResult r; if(Set.arg[0].empty()){ //if(curIsDebug) // printf("Can't assign value, no variable name given.\n"); - return false; + return r; } if(Set.arg[0].at(0)=='@'){ //if(curIsDebug) // printf("Can't assign value to a macro!\n"); - return false; + return r; } std::string vname,vval=Set.defaultarg; vname=_NormalizeVarName(Set.arg[0], Set.caller); if(variables.Get(vname).empty()) - variables.Set(vname,vval); // set only if it has no value + { + variables.Set(vname,vval); // set only if it has no value or the var doesnt exist + r.ret=vval; + } + else + { + r.ret=variables.Get(vname); + } - return true; + return r; } -bool DefScriptPackage::func_setscriptpermission(CmdSet Set) +DefReturnResult DefScriptPackage::func_setscriptpermission(CmdSet& Set) { + DefReturnResult r; if(Set.defaultarg.empty() || Set.arg[0].empty()) - return false; + return r; scriptPermissionMap[Set.arg[0]] = atoi(Set.defaultarg.c_str()); - return true; + return r; } -bool DefScriptPackage::func_toint(CmdSet Set) +DefReturnResult DefScriptPackage::func_toint(CmdSet& Set) { - if(Set.arg[0].empty()) - return false; - - std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); - def_int64 myint = strtol(Set.defaultarg.c_str(), NULL, 10); - std::stringstream ss; - ss << myint; - variables.Set(vname,ss.str()); - return true; -} - -bool DefScriptPackage::func_add(CmdSet Set) -{ - if(Set.arg[0].empty()) - return false; - - std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); - long long myvar = strtol(variables.Get(vname).c_str(), NULL, 10); - def_int64 myadd = strtol(Set.defaultarg.c_str(), NULL, 10); - myvar += myadd; - std::stringstream ss; - ss << myvar; - variables.Set(vname,ss.str()); - return true; -} - -bool DefScriptPackage::func_sub(CmdSet Set) -{ - if(Set.arg[0].empty()) - return false; - - std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); - def_int64 myvar = strtol(variables.Get(vname).c_str(), NULL, 10); - def_int64 myadd = strtol(Set.defaultarg.c_str(), NULL, 10); - myvar -= myadd; - std::stringstream ss; - ss << myvar; - variables.Set(vname,ss.str()); - return true; -} - -bool DefScriptPackage::func_mul(CmdSet Set) -{ - if(Set.arg[0].empty()) - return false; - - std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); - def_int64 myvar = strtol(variables.Get(vname).c_str(), NULL, 10); - def_int64 myadd = strtol(Set.defaultarg.c_str(), NULL, 10); - myvar *= myadd; - std::stringstream ss; - ss << myvar; - variables.Set(vname,ss.str()); - return true; -} - -bool DefScriptPackage::func_div(CmdSet Set) -{ - if(Set.arg[0].empty()) - return false; - - std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); - def_int64 myvar = strtol(variables.Get(vname).c_str(), NULL, 10); - def_int64 myadd = strtol(Set.defaultarg.c_str(), NULL, 10); - if(myadd==0) + DefReturnResult r; + std::string num=toString(floor(toNumber(Set.defaultarg.c_str()))); + if(!Set.arg[0].empty()) { - // TODO: some error handling - variables.Set(vname,"0"); + std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); + variables.Set(vname,num); } - myvar /= myadd; - std::stringstream ss; - ss << myvar; - variables.Set(vname,ss.str()); - return true; + r.ret=num; + return r; } -bool DefScriptPackage::func_mod(CmdSet Set) +DefReturnResult DefScriptPackage::func_add(CmdSet& Set) { + DefReturnResult r; if(Set.arg[0].empty()) - return false; + { + return r; + } std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); - def_int64 myvar = strtol(variables.Get(vname).c_str(), NULL, 10); - def_int64 myadd = strtol(Set.defaultarg.c_str(), NULL, 10); - myvar %= myadd; - std::stringstream ss; - ss << myvar; - variables.Set(vname,ss.str()); - return true; + double a=toNumber(variables.Get(vname)); + double b=toNumber(Set.defaultarg.c_str()); + a+=b; + variables.Set(vname,toString(a)); + r.ret=toString(a); + return r; } -bool DefScriptPackage::func_pow(CmdSet Set) +DefReturnResult DefScriptPackage::func_sub(CmdSet& Set) { + DefReturnResult r; if(Set.arg[0].empty()) - return false; + { + return r; + } std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); - def_int64 myvar = strtol(variables.Get(vname).c_str(), NULL, 10); - def_int64 myadd = strtol(Set.defaultarg.c_str(), NULL, 10); - long double myd=(long double)myvar,mya=(long double)myadd; - myd = (long double)pow(myd,mya); - myvar = (def_int64)myd; - std::stringstream ss; - ss << myvar; - variables.Set(vname,ss.str()); - return true; + double a=toNumber(variables.Get(vname)); + double b=toNumber(Set.defaultarg.c_str()); + a-=b; + variables.Set(vname,toString(a)); + r.ret=toString(a); + return r; } -bool DefScriptPackage::func_bitor(CmdSet Set) +DefReturnResult DefScriptPackage::func_mul(CmdSet& Set) { + DefReturnResult r; if(Set.arg[0].empty()) - return false; + { + return r; + } std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); - def_int64 myvar = strtol(variables.Get(vname).c_str(), NULL, 10); - def_int64 myadd = strtol(Set.defaultarg.c_str(), NULL, 10); - myvar |= myadd; - std::stringstream ss; - ss << myvar; - variables.Set(vname,ss.str()); - return true; + double a=toNumber(variables.Get(vname)); + double b=toNumber(Set.defaultarg.c_str()); + a*=b; + variables.Set(vname,toString(a)); + r.ret=toString(a); + return r; } -bool DefScriptPackage::func_bitand(CmdSet Set) +DefReturnResult DefScriptPackage::func_div(CmdSet& Set) { + DefReturnResult r; if(Set.arg[0].empty()) - return false; + { + return r; + } std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); - def_int64 myvar = strtol(variables.Get(vname).c_str(), NULL, 10); - def_int64 myadd = strtol(Set.defaultarg.c_str(), NULL, 10); - myvar &= myadd; - std::stringstream ss; - ss << myvar; - variables.Set(vname,ss.str()); - return true; + double a=toNumber(variables.Get(vname)); + double b=toNumber(Set.defaultarg.c_str()); + if(b==0) + a=0; + else + a/=b; + variables.Set(vname,toString(a)); + r.ret=toString(a); + return r; } -bool DefScriptPackage::func_bitxor(CmdSet Set) +DefReturnResult DefScriptPackage::func_mod(CmdSet& Set) { + DefReturnResult r; if(Set.arg[0].empty()) - return false; + { + return r; + } std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); - def_int64 myvar = strtol(variables.Get(vname).c_str(), NULL, 10); - def_int64 myadd = strtol(Set.defaultarg.c_str(), NULL, 10); - myvar ^= myadd; - std::stringstream ss; - ss << myvar; - variables.Set(vname,ss.str()); - return true; + uint64 a=(uint64)toNumber(variables.Get(vname)); + uint64 b=(uint64)toNumber(Set.defaultarg.c_str()); + if(b==0) + a=0; + else + a%=b; + variables.Set(vname,toString(a)); + r.ret=toString(a); + return r; } -bool DefScriptPackage::func_addevent(CmdSet Set) +DefReturnResult DefScriptPackage::func_pow(CmdSet& Set) { + DefReturnResult r; + if(Set.arg[0].empty()) + { + return r; + } + + std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); + double a=toNumber(variables.Get(vname)); + double b=toNumber(Set.defaultarg.c_str()); + a=pow(a,b); + variables.Set(vname,toString(a)); + r.ret=toString(a); + return r; +} + +DefReturnResult DefScriptPackage::func_bitor(CmdSet& Set) +{ + DefReturnResult r; + if(Set.arg[0].empty()) + { + return r; + } + + std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); + uint64 a=(uint64)toNumber(variables.Get(vname)); + uint64 b=(uint64)toNumber(Set.defaultarg.c_str()); + a|=b; + variables.Set(vname,toString(a)); + r.ret=toString(a); + return r; +} + +DefReturnResult DefScriptPackage::func_bitand(CmdSet& Set) +{ + DefReturnResult r; + if(Set.arg[0].empty()) + { + return r; + } + + std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); + uint64 a=(uint64)toNumber(variables.Get(vname)); + uint64 b=(uint64)toNumber(Set.defaultarg.c_str()); + a&=b; + variables.Set(vname,toString(a)); + r.ret=toString(a); + return r; +} + +DefReturnResult DefScriptPackage::func_bitxor(CmdSet& Set) +{ + DefReturnResult r; + if(Set.arg[0].empty()) + { + return r; + } + + std::string vname=_NormalizeVarName(Set.arg[0], Set.myname); + uint64 a=(uint64)toNumber(variables.Get(vname)); + uint64 b=(uint64)toNumber(Set.defaultarg.c_str()); + a^=b; + variables.Set(vname,toString(a)); + r.ret=toString(a); + return r; +} + +DefReturnResult DefScriptPackage::func_addevent(CmdSet& Set) +{ + DefReturnResult r; GetEventMgr()->Add(Set.arg[0],Set.defaultarg,atoi(Set.arg[1].c_str()),Set.myname.c_str()); - return true; + return r; } -bool DefScriptPackage::func_removeevent(CmdSet Set) +DefReturnResult DefScriptPackage::func_removeevent(CmdSet& Set) { + DefReturnResult r; GetEventMgr()->Remove(Set.defaultarg); - return true; + return r; } diff --git a/src/Client/DefScript/DefScriptTools.cpp b/src/Client/DefScript/DefScriptTools.cpp new file mode 100644 index 0000000..19541cb --- /dev/null +++ b/src/Client/DefScript/DefScriptTools.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "DefScriptDefines.h" +#include "DefScriptTools.h" + + +std::string DefScriptTools::stringToLower(std::string s) +{ + std::transform(s.begin(), s.end(), s.begin(), std::tolower); + return s; +} + +std::string DefScriptTools::stringToUpper(std::string s) +{ + std::transform(s.begin(), s.end(), s.begin(), std::toupper); + return s; +} + +std::string DefScriptTools::toString(double num) +{ + std::stringstream ss; + ss << num; + return ss.str(); +} + +std::string DefScriptTools::toString(uint64 num) +{ + std::stringstream ss; + ss << num; + return ss.str(); +} +// convert a string into double +// valid input formats: +// normal numbers: 5439 +// hex numbers: 0xa56ff, 0XFF, 0xDEADBABE, etc (must begin with 0x) +// float numbers: 99.65, 0.025 +// negative numbers: -100, -0x3d, -55.123 +double DefScriptTools::toNumber(std::string str) +{ + double num; + bool negative=false; + if(str.empty()) + return 0; + if(str[0]=='-') + { + str.erase(0,1); + negative=true; + } + if(str.find('.')==std::string::npos) + { + str=stringToUpper(str); + if(str.length() > 2 && str[0]=='0' && str[1]=='X') + num = strtoul(&(str.c_str()[2]),NULL,16); + else + num = strtoul(str.c_str(),NULL,10); + } + else + { + num = strtod(str.c_str(),NULL); + } + if(negative) + num = -num; + return num; +} \ No newline at end of file diff --git a/src/Client/DefScript/DefScriptTools.h b/src/Client/DefScript/DefScriptTools.h new file mode 100644 index 0000000..6dab53c --- /dev/null +++ b/src/Client/DefScript/DefScriptTools.h @@ -0,0 +1,15 @@ +#ifndef _DEFSCRIPTTOOLS_H +#define _DEFSCRIPTTOOLS_H + +namespace DefScriptTools +{ + std::string stringToUpper(std::string); + std::string stringToLower(std::string); + std::string toString(double); + std::string toString(uint64); + double toNumber(std::string); +} + + + +#endif diff --git a/src/Client/DefScriptInterface.cpp b/src/Client/DefScriptInterface.cpp index 2194c7a..2a68634 100644 --- a/src/Client/DefScriptInterface.cpp +++ b/src/Client/DefScriptInterface.cpp @@ -11,18 +11,18 @@ #include "CacheHandler.h" #include "SCPDatabase.h" -bool DefScriptPackage::SCshdn(CmdSet Set) +DefReturnResult DefScriptPackage::SCshdn(CmdSet& Set) { ((PseuInstance*)parentMethod)->Stop(); return true; } -bool DefScriptPackage::SCpause(CmdSet Set){ +DefReturnResult DefScriptPackage::SCpause(CmdSet& Set){ ((PseuInstance*)parentMethod)->Sleep(atoi(Set.defaultarg.c_str())); return true; } -bool DefScriptPackage::SCSendChatMessage(CmdSet Set){ +DefReturnResult DefScriptPackage::SCSendChatMessage(CmdSet& Set){ if(!(((PseuInstance*)parentMethod)->GetWSession() && ((PseuInstance*)parentMethod)->GetWSession()->IsValid())) { logerror("Invalid Script call: SCSendChatMessage: WorldSession not valid"); @@ -49,7 +49,7 @@ bool DefScriptPackage::SCSendChatMessage(CmdSet Set){ return true; } -bool DefScriptPackage::SCsavecache(CmdSet Set){ +DefReturnResult DefScriptPackage::SCsavecache(CmdSet& Set){ ((PseuInstance*)parentMethod)->SaveAllCache(); std::stringstream str; if(((PseuInstance*)parentMethod)->GetWSession() && ((PseuInstance*)parentMethod)->GetWSession()->IsValid()) @@ -66,7 +66,7 @@ bool DefScriptPackage::SCsavecache(CmdSet Set){ return true; } -bool DefScriptPackage::SCemote(CmdSet Set){ +DefReturnResult DefScriptPackage::SCemote(CmdSet& Set){ if(Set.defaultarg.empty()) return true; if(!(((PseuInstance*)parentMethod)->GetWSession() && ((PseuInstance*)parentMethod)->GetWSession()->IsValid())) @@ -79,7 +79,7 @@ bool DefScriptPackage::SCemote(CmdSet Set){ return true; } -bool DefScriptPackage::SCfollow(CmdSet Set){ +DefReturnResult DefScriptPackage::SCfollow(CmdSet& Set){ WorldSession *ws=((PseuInstance*)parentMethod)->GetWSession(); if(Set.defaultarg.empty()){ ws->SendChatMessage(CHAT_MSG_SAY,0,"Stopping! (Please give me a Playername to follow!)",""); @@ -97,7 +97,7 @@ bool DefScriptPackage::SCfollow(CmdSet Set){ } -bool DefScriptPackage::SCjoinchannel(CmdSet Set){ +DefReturnResult DefScriptPackage::SCjoinchannel(CmdSet& Set){ if(Set.defaultarg.empty()) return true; if(!(((PseuInstance*)parentMethod)->GetWSession() && ((PseuInstance*)parentMethod)->GetWSession()->IsValid())) @@ -109,7 +109,7 @@ bool DefScriptPackage::SCjoinchannel(CmdSet Set){ return true; } -bool DefScriptPackage::SCleavechannel(CmdSet Set){ +DefReturnResult DefScriptPackage::SCleavechannel(CmdSet& Set){ if(Set.defaultarg.empty()) return true; if(!(((PseuInstance*)parentMethod)->GetWSession() && ((PseuInstance*)parentMethod)->GetWSession()->IsValid())) @@ -121,7 +121,7 @@ bool DefScriptPackage::SCleavechannel(CmdSet Set){ return true; } -bool DefScriptPackage::SCloadconf(CmdSet Set){ +DefReturnResult DefScriptPackage::SCloadconf(CmdSet& Set){ if(Set.defaultarg.empty()) return true; std::string fn; @@ -136,37 +136,37 @@ bool DefScriptPackage::SCloadconf(CmdSet Set){ return true; } -bool DefScriptPackage::SCapplypermissions(CmdSet Set){ +DefReturnResult DefScriptPackage::SCapplypermissions(CmdSet& Set){ this->My_LoadUserPermissions(variables); return true; } -bool DefScriptPackage::SCapplyconf(CmdSet Set){ +DefReturnResult DefScriptPackage::SCapplyconf(CmdSet& Set){ ((PseuInstance*)parentMethod)->GetConf()->ApplyFromVarSet(variables); return true; } -bool DefScriptPackage::SClog(CmdSet Set){ +DefReturnResult DefScriptPackage::SClog(CmdSet& Set){ log(Set.defaultarg.c_str()); return true; } -bool DefScriptPackage::SClogdetail(CmdSet Set){ +DefReturnResult DefScriptPackage::SClogdetail(CmdSet& Set){ logdetail(Set.defaultarg.c_str()); return true; } -bool DefScriptPackage::SClogdebug(CmdSet Set){ +DefReturnResult DefScriptPackage::SClogdebug(CmdSet& Set){ logdebug(Set.defaultarg.c_str()); return true; } -bool DefScriptPackage::SClogerror(CmdSet Set){ +DefReturnResult DefScriptPackage::SClogerror(CmdSet& Set){ logerror(Set.defaultarg.c_str()); return true; } -bool DefScriptPackage::SCcastspell(CmdSet Set) +DefReturnResult DefScriptPackage::SCcastspell(CmdSet& Set) { if(Set.defaultarg.empty()) return true; @@ -188,7 +188,7 @@ bool DefScriptPackage::SCcastspell(CmdSet Set) return true; } -bool DefScriptPackage::SCqueryitem(CmdSet Set){ +DefReturnResult DefScriptPackage::SCqueryitem(CmdSet& Set){ uint32 id = atoi(Set.defaultarg.c_str()); if(!id) return true; @@ -202,7 +202,7 @@ bool DefScriptPackage::SCqueryitem(CmdSet Set){ return true; } -bool DefScriptPackage::SCtarget(CmdSet Set) +DefReturnResult DefScriptPackage::SCtarget(CmdSet& Set) { // TODO: special targets: _self _pet _nearest ... @@ -229,7 +229,7 @@ bool DefScriptPackage::SCtarget(CmdSet Set) return true; } -bool DefScriptPackage::SCloadscp(CmdSet Set) +DefReturnResult DefScriptPackage::SCloadscp(CmdSet& Set) { if(Set.arg[0].empty() || Set.defaultarg.empty()) return true; @@ -264,13 +264,10 @@ void DefScriptPackage::My_LoadUserPermissions(VarSet &vs) } } -bool DefScriptPackage::My_Run(std::string line, std::string username) +void DefScriptPackage::My_Run(std::string line, std::string username) { - DefXChgResult final=ReplaceVars(line,NULL,false); - CmdSet curSet=SplitLine(final.str); - uint8 scperm=0,usrperm=0; - + for (std::map::iterator i = my_usrPermissionMap.begin(); i != my_usrPermissionMap.end(); i++) { if(i->first == username) @@ -279,6 +276,21 @@ bool DefScriptPackage::My_Run(std::string line, std::string username) } } + // temp fix to prevent users from executing scripts via return values exploit. example: + // -out ?{say .shutdown} + // note that the following code can still be executed: + // -out ${q}?{say .shutdown} + // where var q = "?" + if(usrperm < 255 && line.find("?{")!=std::string::npos) + { + logerror("WARNING: %s wanted to exec \"%s\"",username.c_str(),line.c_str()); + return; + } + + DefXChgResult final=ReplaceVars(line,NULL,false); + CmdSet curSet; + SplitLine(curSet,final.str); + for (std::map::iterator i = scriptPermissionMap.begin(); i != scriptPermissionMap.end(); i++) { if(i->first == curSet.cmd) @@ -289,15 +301,14 @@ bool DefScriptPackage::My_Run(std::string line, std::string username) if(usrperm < scperm) { - CmdSet Set(NULL); + CmdSet Set; Set.arg[0] = username; Set.arg[1] = toString(usrperm); Set.arg[2] = toString(scperm); Set.arg[3] = curSet.cmd; RunScript("_nopermission",&Set); - return false; + return; } Interpret(curSet); - return true; -} \ No newline at end of file +} diff --git a/src/Client/PseuWoW.cpp b/src/Client/PseuWoW.cpp index 126480f..e3ac719 100644 --- a/src/Client/PseuWoW.cpp +++ b/src/Client/PseuWoW.cpp @@ -100,7 +100,8 @@ bool PseuInstance::Init(void) { _scp->variables.Set("@version",_ver); log("Loading DefScripts from folder '%s'",_scpdir.c_str()); - if(!_scp->RunScript("_startup",NULL)) + + if(!_scp->BoolRunScript("_startup",NULL)) { logerror("Error executing '_startup.def'"); SetError(); diff --git a/src/PseuWoW.vcproj b/src/PseuWoW.vcproj index ce6a9fe..8f75a85 100644 --- a/src/PseuWoW.vcproj +++ b/src/PseuWoW.vcproj @@ -239,9 +239,18 @@ Name="VCCustomBuildTool"/> + + + + + +