]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/command_parse.cpp
Forward-port: Fix an uninitialised variable in ConfigReader::GetError()
[user/henk/code/inspircd.git] / src / command_parse.cpp
index 4d03681b63e0cf68aa84066c69bb3105b9d21754..3373f714f6330e566f52081f439388a89c44caa6 100644 (file)
  * ---------------------------------------------------
  */
 
-/* $Core: libIRCDcommand_parse */
+/* $Core */
 
 #include "inspircd.h"
-#include "wildcard.h"
 #include "xline.h"
 #include "socketengine.h"
 #include "socket.h"
@@ -278,25 +277,79 @@ bool CommandParser::ProcessCommand(User *user, std::string &cmd)
 
        std::transform(command.begin(), command.end(), command.begin(), ::toupper);
                
-       int MOD_RESULT = 0;
-       FOREACH_RESULT(I_OnPreCommand,OnPreCommand(command, command_p, user, false, cmd));
-       if (MOD_RESULT == 1) {
-               return true;
-       }
-
        /* find the command, check it exists */
        Commandtable::iterator cm = cmdlist.find(command);
        
        if (cm == cmdlist.end())
        {
-               if (user->registered == REG_ALL)
+               int MOD_RESULT = 0;
+               FOREACH_RESULT(I_OnPreCommand,OnPreCommand(command, command_p, user, false, cmd));
+               if (MOD_RESULT == 1)
+                       return true;
+
+               /*
+                * This double lookup is in case a module (abbreviation) wishes to change a command.
+                * Sure, the double lookup is a bit painful, but bear in mind this only happens for unknowns anyway.
+                *
+                * Thanks dz for making me actually understand why this is necessary!
+                * -- w00t
+                */
+               cm = cmdlist.find(command);
+               if (cm == cmdlist.end())
                {
-                       user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s %s :Unknown command",user->nick.c_str(),command.c_str());
+                       if (user->registered == REG_ALL)
+                               user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s %s :Unknown command",user->nick.c_str(),command.c_str());
+                       ServerInstance->stats->statsUnknown++;
+                       return true;
                }
-               ServerInstance->stats->statsUnknown++;
-               return true;
        }
 
+       if (cm->second->max_params && command_p.size() > cm->second->max_params)
+       {
+               /*
+                * command_p input (assuming max_params 1):
+                *      this
+                *      is
+                *      a
+                *      test
+                */
+               std::string lparam = "";
+
+               /*
+                * The '-1' here is a clever trick, we'll go backwards throwing everything into a temporary param
+                * and then just toss that into the array.
+                * -- w00t
+                */
+               while (command_p.size() > (cm->second->max_params - 1))
+               {
+                       // BE CAREFUL: .end() returns past the end of the vector, hence decrement.
+                       std::vector<std::string>::iterator it = --command_p.end();
+               
+                       lparam.insert(0, " " + *(it));
+                       command_p.erase(it); // remove last element
+               }
+
+               /* we now have (each iteration):
+                *      ' test'
+                *      ' a test'
+                *      ' is a test' <-- final string
+                * ...now remove the ' ' at the start...
+                */
+               lparam.erase(lparam.begin());
+
+               /* param is now 'is a test', which is exactly what we wanted! */
+               command_p.push_back(lparam);
+       }
+
+       /*
+        * We call OnPreCommand here seperately if the command exists, so the magic above can
+        * truncate to max_params if necessary. -- w00t
+        */
+       int MOD_RESULT = 0;
+       FOREACH_RESULT(I_OnPreCommand,OnPreCommand(command, command_p, user, false, cmd));
+       if (MOD_RESULT == 1)
+               return true;
+
        /* Modify the user's penalty */
        bool do_more = true;
        if (!user->ExemptFromPenalty)
@@ -327,7 +380,16 @@ bool CommandParser::ProcessCommand(User *user, std::string &cmd)
        if ((user->registered == REG_ALL) && (!IS_OPER(user)) && (cm->second->IsDisabled()))
        {
                /* command is disabled! */
-               user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s %s :This command has been disabled.",user->nick.c_str(),command.c_str());
+               if (ServerInstance->Config->DisabledDontExist)
+               {
+                       user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s %s :Unknown command",user->nick.c_str(),command.c_str());
+               }
+               else
+               {
+                       user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s %s :This command has been disabled.",
+                                                                               user->nick.c_str(), command.c_str());
+               }
+
                ServerInstance->SNO->WriteToSnoMask('d', "%s denied for %s (%s@%s)",
                                command.c_str(), user->nick.c_str(), user->ident.c_str(), user->host.c_str());
                return do_more;
@@ -531,7 +593,13 @@ const char* CommandParser::LoadCommand(const char* name)
 
 void CommandParser::SetupCommandTable(User* user)
 {
-       RFCCommands.clear();
+       for (SharedObjectList::iterator command = RFCCommands.begin(); command != RFCCommands.end(); command++)
+       {
+               Command *cmdptr = cmdlist.find(command->first)->second;
+               cmdlist.erase(cmdlist.find(command->first));
+               RFCCommands.erase(command);
+               delete cmdptr;
+       }
 
        if (!user)
        {
@@ -545,7 +613,7 @@ void CommandParser::SetupCommandTable(User* user)
                dirent* entry = NULL;
                while (0 != (entry = readdir(library)))
                {
-                       if (match(entry->d_name, "cmd_*.so"))
+                       if (InspIRCd::Match(entry->d_name, "cmd_*.so"))
                        {
                                if (!user)
                                {