From ecd5b4082a7ef4ae89116761c77285ed77b7a794 Mon Sep 17 00:00:00 2001 From: brain Date: Wed, 6 Sep 2006 18:20:02 +0000 Subject: Finish off the fix for bug #136 (a biggie for such a simple thing) git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@5151 e03df62e-2008-0410-955e-edbf42e46eb7 --- include/command_parse.h | 8 ++++++-- include/modules.h | 19 ++++++++++++++++--- src/cmd_modules.cpp | 3 ++- src/command_parse.cpp | 13 ++++++------- src/modules.cpp | 1 + src/modules/m_spanningtree.cpp | 22 ++++++++++++++++------ 6 files changed, 47 insertions(+), 19 deletions(-) diff --git a/include/command_parse.h b/include/command_parse.h index 635db619c..40c3425fb 100644 --- a/include/command_parse.h +++ b/include/command_parse.h @@ -96,9 +96,13 @@ class CommandParser : public classbase * @param parameters Parameter list as an array of array of char (that's not a typo). * @param pcnt The number of items in the parameters list * @param user The user to call the handler on behalf of - * @return This method will return true if the command handler was found and called + * @return This method will return CMD_SUCCESS if the command handler was found and called, + * and the command completeld successfully. It will return CMD_FAILURE if the command handler was found + * and called, but the command did not complete successfully, and it will return CMD_INVALID if the + * command simply did not exist at all or the wrong number of parameters were given, or the user + * was not privilaged enough to execute the command. */ - bool CallHandler(const std::string &commandname,const char** parameters, int pcnt, userrec *user); + CmdResult CallHandler(const std::string &commandname,const char** parameters, int pcnt, userrec *user); /** This function returns true if a command is valid with the given number of parameters and user. * @param commandname The command name to check diff --git a/include/modules.h b/include/modules.h index 2754a42c2..c497155ad 100644 --- a/include/modules.h +++ b/include/modules.h @@ -342,7 +342,7 @@ enum Implementation { I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUse I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnStats, I_OnChangeLocalUserHost, I_OnChangeLocalUserGecos, I_OnLocalTopicChange, I_OnPostLocalTopicChange, I_OnEvent, I_OnRequest, I_OnOperCompre, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan, I_OnDelBan, I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketWrite, I_OnRawSocketRead, I_OnChangeLocalUserGECOS, I_OnUserRegister, - I_OnOperCompare, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnCancelAway, I_OnUserList }; + I_OnOperCompare, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnCancelAway, I_OnUserList, I_OnPostCommand }; /** Base class for all InspIRCd modules * This class is the base class for InspIRCd modules. All modules must inherit from this class, @@ -985,8 +985,8 @@ class Module : public Extensible /** Called whenever any command is about to be executed. * This event occurs for all registered commands, wether they are registered in the core, - * or another module, but it will not occur for invalid commands (e.g. ones which do not - * exist within the command table). By returning 1 from this method you may prevent the + * or another module, and for invalid commands. Invalid commands may only be sent to this + * function when the value of validated is false. By returning 1 from this method you may prevent the * command being executed. If you do this, no output is created by the core, and it is * down to your module to produce any output neccessary. * Note that unless you return 1, you should not destroy any structures (e.g. by using @@ -1001,6 +1001,19 @@ class Module : public Extensible */ virtual int OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, bool validated); + /** Called after any command has been executed. + * This event occurs for all registered commands, wether they are registered in the core, + * or another module, but it will not occur for invalid commands (e.g. ones which do not + * exist within the command table). The result code returned by the command handler is + * provided. + * @param command The command being executed + * @param parameters An array of array of characters containing the parameters for the command + * @param pcnt The nuimber of parameters passed to the command + * @param user the user issuing the command + * @param result The return code given by the command handler, one of CMD_SUCCESS or CMD_FAILURE + */ + virtual void OnPostCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, CmdResult result); + /** Called to check if a user who is connecting can now be allowed to register * If any modules return false for this function, the user is held in the waiting * state until all modules return true. For example a module which implements ident diff --git a/src/cmd_modules.cpp b/src/cmd_modules.cpp index fe6fa0258..f3f12eaed 100644 --- a/src/cmd_modules.cpp +++ b/src/cmd_modules.cpp @@ -33,7 +33,8 @@ char* itab[] = { "OnCheckKey", "OnCheckLimit", "OnCheckBan", "OnStats", "OnChangeLocalUserHost", "OnChangeLocalUserGecos", "OnLocalTopicChange", "OnPostLocalTopicChange", "OnEvent", "OnRequest", "OnOperCompre", "OnGlobalOper", "OnPostConnect", "OnAddBan", "OnDelBan", "OnRawSocketAccept", "OnRawSocketClose", "OnRawSocketWrite", "OnRawSocketRead", "OnChangeLocalUserGECOS", "OnUserRegister", - "OnOperCompare", "OnChannelDelete", "OnPostOper", "OnSyncOtherMetaData", "OnSetAway", "OnCancelAway", "OnNamesList", NULL + "OnOperCompare", "OnChannelDelete", "OnPostOper", "OnSyncOtherMetaData", "OnSetAway", "OnCancelAway", "OnNamesList", + "OnPostCommand", NULL }; diff --git a/src/command_parse.cpp b/src/command_parse.cpp index 4c58d9b60..11f4b4635 100644 --- a/src/command_parse.cpp +++ b/src/command_parse.cpp @@ -284,7 +284,7 @@ bool CommandParser::IsValidCommand(const std::string &commandname, int pcnt, use // calls a handler function for a command -bool CommandParser::CallHandler(const std::string &commandname,const char** parameters, int pcnt, userrec *user) +CmdResult CommandParser::CallHandler(const std::string &commandname,const char** parameters, int pcnt, userrec *user) { nspace::hash_map::iterator n = cmdlist.find(commandname); @@ -298,19 +298,17 @@ bool CommandParser::CallHandler(const std::string &commandname,const char** para { if ((user->HasPermission(commandname)) || (!IS_LOCAL(user))) { - n->second->Handle(parameters,pcnt,user); - return true; + return n->second->Handle(parameters,pcnt,user); } } else { - n->second->Handle(parameters,pcnt,user); - return true; + return n->second->Handle(parameters,pcnt,user); } } } } - return false; + return CMD_INVALID; } void CommandParser::ProcessCommand(userrec *user, std::string &cmd) @@ -383,8 +381,9 @@ void CommandParser::ProcessCommand(userrec *user, std::string &cmd) * command handler call, as the handler * may free the user structure! */ + CmdResult result = cm->second->Handle(command_p,items,user); - cm->second->Handle(command_p,items,user); + FOREACH_MOD(I_OnPostCommand,OnPostCommand(command, command_p, items, user, result)); return; } else diff --git a/src/modules.cpp b/src/modules.cpp index d3db06d45..f5e83c093 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -132,6 +132,7 @@ void Module::OnLoadModule(Module* mod,const std::string &name) { }; void Module::OnUnloadModule(Module* mod,const std::string &name) { }; void Module::OnBackgroundTimer(time_t curtime) { }; int Module::OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, bool validated) { return 0; }; +void Module::OnPostCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, CmdResult result) { }; bool Module::OnCheckReady(userrec* user) { return true; }; void Module::OnUserRegister(userrec* user) { }; int Module::OnUserPreKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason) { return 0; }; diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp index b9113dfc5..c102209c5 100644 --- a/src/modules/m_spanningtree.cpp +++ b/src/modules/m_spanningtree.cpp @@ -3185,10 +3185,17 @@ class TreeSocket : public InspSocket { strparams[q] = params[q].c_str(); } - if (!this->Instance->CallCommandHandler(command.c_str(), strparams, params.size(), who)) + switch (this->Instance->CallCommandHandler(command.c_str(), strparams, params.size(), who)) { - this->WriteLine("ERROR :Unrecognised command '"+std::string(command.c_str())+"' -- possibly loaded mismatched modules"); - return false; + case CMD_INVALID: + this->WriteLine("ERROR :Unrecognised command '"+std::string(command.c_str())+"' -- possibly loaded mismatched modules"); + return false; + break; + case CMD_FAILURE: + return true; + break; + default: + break; } } else @@ -4279,7 +4286,11 @@ class ModuleSpanningTree : public Module this->HandleVersion(parameters,pcnt,user); return 1; } - else if (ServerInstance->IsValidModuleCommand(command, pcnt, user)) + } + + virtual void OnPostCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, CmdResult result) + { + if ((result == CMD_SUCCESS) && (ServerInstance->IsValidModuleCommand(command, pcnt, user))) { // this bit of code cleverly routes all module commands // to all remote severs *automatically* so that modules @@ -4302,7 +4313,6 @@ class ModuleSpanningTree : public Module ServerInstance->Log(DEBUG,"Globally route '%s'",command.c_str()); DoOneToMany(user->nick,command,params); } - return 0; } virtual void OnGetServerDescription(const std::string &servername,std::string &description) @@ -4830,7 +4840,7 @@ class ModuleSpanningTree : public Module List[I_OnUserQuit] = List[I_OnUserPostNick] = List[I_OnUserKick] = List[I_OnRemoteKill] = List[I_OnRehash] = 1; List[I_OnOper] = List[I_OnAddGLine] = List[I_OnAddZLine] = List[I_OnAddQLine] = List[I_OnAddELine] = 1; List[I_OnDelGLine] = List[I_OnDelZLine] = List[I_OnDelQLine] = List[I_OnDelELine] = List[I_ProtoSendMode] = List[I_OnMode] = 1; - List[I_OnStats] = List[I_ProtoSendMetaData] = List[I_OnEvent] = List[I_OnSetAway] = List[I_OnCancelAway] = 1; + List[I_OnStats] = List[I_ProtoSendMetaData] = List[I_OnEvent] = List[I_OnSetAway] = List[I_OnCancelAway] = List[I_OnPostCommand] = 1; } /* It is IMPORTANT that m_spanningtree is the last module in the chain -- cgit v1.2.3