diff options
-rw-r--r-- | include/command_parse.h | 3 | ||||
-rw-r--r-- | include/hashcomp.h | 13 | ||||
-rw-r--r-- | src/cmd_join.cpp | 25 | ||||
-rw-r--r-- | src/cmd_names.cpp | 3 | ||||
-rw-r--r-- | src/cmd_notice.cpp | 2 | ||||
-rw-r--r-- | src/cmd_part.cpp | 7 | ||||
-rw-r--r-- | src/cmd_privmsg.cpp | 3 | ||||
-rw-r--r-- | src/cmd_whois.cpp | 3 | ||||
-rw-r--r-- | src/command_parse.cpp | 205 | ||||
-rw-r--r-- | src/hashcomp.cpp | 28 |
10 files changed, 98 insertions, 194 deletions
diff --git a/include/command_parse.h b/include/command_parse.h index 15e0f1446..800f2beeb 100644 --- a/include/command_parse.h +++ b/include/command_parse.h @@ -36,7 +36,8 @@ class CommandParser : public classbase CommandParser(); bool CallHandler(const std::string &commandname,const char** parameters, int pcnt, userrec *user); bool IsValidCommand(const std::string &commandname, int pcnt, userrec * user); - int LoopCall(command_t *fn, const char** parameters, int pcnt, userrec *u, int start, int end, int joins); + int LoopCall(userrec* user, command_t* CommandObj, const char** parameters, int pcnt, unsigned int splithere, unsigned int extra); + int LoopCall(userrec* user, command_t* CommandObj, const char** parameters, int pcnt, unsigned int splithere); void ProcessBuffer(std::string &buffer,userrec *user); bool RemoveCommands(const char* source); bool CreateCommand(command_t *f); diff --git a/include/hashcomp.h b/include/hashcomp.h index 22e9f1470..f6c9368d6 100644 --- a/include/hashcomp.h +++ b/include/hashcomp.h @@ -93,6 +93,19 @@ namespace irc const std::string GetToken(); }; + class commasepstream + { + private: + std::string tokens; + std::string::iterator last_starting_position; + std::string::iterator n; + public: + commasepstream(const std::string &source); + ~commasepstream(); + + const std::string GetToken(); + }; + /** The irc_char_traits class is used for RFC-style comparison of strings. * This class is used to implement irc::string, a case-insensitive, RFC- diff --git a/src/cmd_join.cpp b/src/cmd_join.cpp index fc63283e5..728038c2e 100644 --- a/src/cmd_join.cpp +++ b/src/cmd_join.cpp @@ -24,15 +24,28 @@ extern InspIRCd* ServerInstance; void cmd_join::Handle (const char** parameters, int pcnt, userrec *user) { - if (ServerInstance->Parser->LoopCall(this, parameters, pcnt, user, 0, 0, 1)) - return; - - if (IsValidChannelName(parameters[0])) + if (pcnt > 1) { - add_channel(user, parameters[0], parameters[1], false); + if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0, 1)) + return; + + if (IsValidChannelName(parameters[0])) + { + add_channel(user, parameters[0], parameters[1], false); + return; + } } else { - WriteServ(user->fd,"403 %s %s :Invalid channel name",user->nick, parameters[0]); + if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0)) + return; + + if (IsValidChannelName(parameters[0])) + { + add_channel(user, parameters[0], "", false); + return; + } } + + WriteServ(user->fd,"403 %s %s :Invalid channel name",user->nick, parameters[0]); } diff --git a/src/cmd_names.cpp b/src/cmd_names.cpp index d25e7c5e6..ca0ded549 100644 --- a/src/cmd_names.cpp +++ b/src/cmd_names.cpp @@ -32,8 +32,9 @@ void cmd_names::Handle (const char** parameters, int pcnt, userrec *user) return; } - if (ServerInstance->Parser->LoopCall(this,parameters,pcnt,user,0,pcnt-1,0)) + if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0)) return; + c = FindChan(parameters[0]); if (c) { diff --git a/src/cmd_notice.cpp b/src/cmd_notice.cpp index 434594df9..b9bd536d0 100644 --- a/src/cmd_notice.cpp +++ b/src/cmd_notice.cpp @@ -43,7 +43,7 @@ void cmd_notice::Handle (const char** parameters, int pcnt, userrec *user) user->idle_lastmsg = TIME; - if (ServerInstance->Parser->LoopCall(this,parameters,pcnt,user,0,pcnt-2,0)) + if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0)) return; if ((parameters[0][0] == '$') && ((*user->oper) || (is_uline(user->server)))) { diff --git a/src/cmd_part.cpp b/src/cmd_part.cpp index 44c158205..39a962140 100644 --- a/src/cmd_part.cpp +++ b/src/cmd_part.cpp @@ -24,16 +24,15 @@ extern InspIRCd* ServerInstance; void cmd_part::Handle (const char** parameters, int pcnt, userrec *user) { + if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0)) + return; + if (pcnt > 1) { - if (ServerInstance->Parser->LoopCall(this,parameters,pcnt,user,0,pcnt-2,0)) - return; del_channel(user,parameters[0],parameters[1],false); } else { - if (ServerInstance->Parser->LoopCall(this,parameters,pcnt,user,0,pcnt-1,0)) - return; del_channel(user,parameters[0],NULL,false); } } diff --git a/src/cmd_privmsg.cpp b/src/cmd_privmsg.cpp index e74495bb6..30d766e82 100644 --- a/src/cmd_privmsg.cpp +++ b/src/cmd_privmsg.cpp @@ -40,8 +40,9 @@ void cmd_privmsg::Handle (const char** parameters, int pcnt, userrec *user) user->idle_lastmsg = TIME; - if (ServerInstance->Parser->LoopCall(this,parameters,pcnt,user,0,pcnt-2,0)) + if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0)) return; + if ((parameters[0][0] == '$') && ((*user->oper) || (is_uline(user->server)))) { // notice to server mask diff --git a/src/cmd_whois.cpp b/src/cmd_whois.cpp index e44757e6d..1f4a402b2 100644 --- a/src/cmd_whois.cpp +++ b/src/cmd_whois.cpp @@ -104,8 +104,9 @@ void do_whois(userrec* user, userrec* dest,unsigned long signon, unsigned long i void cmd_whois::Handle (const char** parameters, int pcnt, userrec *user) { userrec *dest; - if (ServerInstance->Parser->LoopCall(this,parameters,pcnt,user,0,pcnt-1,0)) + if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0)) return; + dest = Find(parameters[0]); if (dest) { diff --git a/src/command_parse.cpp b/src/command_parse.cpp index 9170e3941..af96deaa8 100644 --- a/src/command_parse.cpp +++ b/src/command_parse.cpp @@ -98,198 +98,45 @@ cmd_pass* command_pass; * before the actual list as well. This code is used by many functions which * can function as "one to list" (see the RFC) */ -int CommandParser::LoopCall(command_t* fn, const char** parameters, int pcnt, userrec *u, int start, int end, int joins) +int CommandParser::LoopCall(userrec* user, command_t* CommandObj, const char** parameters, int pcnt, unsigned int splithere, unsigned int extra) { - /* Copy of the parameter list, because like strltok, we make a bit of - * a mess of the parameter string we're given, and we want to keep this - * private. - */ - char paramlist[MAXBUF]; - /* Temporary variable used to hold one split parameter - */ - char *param; - /* Parameter list, we can have up to 32 of these - */ - const char *pars[32]; - /* Seperated items, e.g. holds the #one and #two from "#one,#two" - */ - const char *sep_items[32]; - /* Seperated keys, holds the 'two' and 'three' of "two,three" - */ - const char *sep_keys[32]; - /* Misc. counters, the total values hold the total number of - * seperated items in sep_items (total) and the total number of - * seperated items in sep_keys (total2) - */ - int j = 0, q = 0, total = 0, total2 = 0; - /* A temporary copy of the comma seperated key list (see the description - * of the paramlist variable) - */ - char keylist[MAXBUF]; - /* Exactly what it says. Its nothing. We point invalid parameters at this. - */ - char nothing = 0; - - /* First, initialize our arrays */ - for (int i = 0; i < 32; i++) - sep_items[i] = sep_keys[i] = NULL; - - /* Now find all parameters that are NULL, maybe above pcnt, - * and for safety, point them at 'nothing' - */ - for (int i = 0; i < 10; i++) - { - if (!parameters[i]) - { - parameters[i] = ¬hing; - } - } - /* Check if we're doing JOIN handling. JOIN has two lists in - * it, potentially, if we have keys, so this is a special-case - * to handle the keys if they are provided. - */ - if (joins) + /*if ((unsigned int)j > Config->MaxTargets) { - if (pcnt > 1) /* we have a key to copy */ - { - strlcpy(keylist,parameters[1],MAXBUF); - } + WriteServ(u->fd,"407 %s %s :Too many targets in list, message not delivered.",u->nick,sep_items[j-1]); + return 1; } - - /* There's nothing to split! We don't do anything - */ - if (!parameters[start] || (!strchr(parameters[start],','))) - { + fn->Handle(pars,pcnt-(end-start),u); + return 1;*/ + if (!strchr(parameters[splithere],',')) return 0; - } - /* This function can handle multiple comma seperated - * lists as one, which is a feature no actual commands - * have yet -- this is futureproofing in case we encounter - * a command that does. - */ - *paramlist = 0; + irc::commasepstream items1(parameters[splithere]); + irc::commasepstream items2(parameters[extra]); + std::string item = ""; - for (int i = start; i <= end; i++) + while ((item = items1.GetToken()) != "") { - if (parameters[i]) - { - strlcat(paramlist,parameters[i],MAXBUF); - } - } - - /* Now we split off paramlist into seperate parameters using - * pointer voodoo, this parameter list goes into sep_items - */ - j = 0; - param = paramlist; - - for (char* i = paramlist; *i; i++) - { - /* Found an item */ - if (*i == ',') - { - *i = '\0'; - sep_items[j++] = param; - /* Iterate along to next item, if there is one */ - param = i+1; - if ((unsigned int)j > Config->MaxTargets) - { - /* BZZT! Too many items */ - WriteServ(u->fd,"407 %s %s :Too many targets in list, message not delivered.",u->nick,sep_items[j-1]); - return 1; - } - } - } - sep_items[j++] = param; - total = j; - - /* We add this extra comma here just to ensure we get all the keys - * in the event the user gave a malformed key string (yes, you guessed - * it, this is a mirc-ism) - */ - if ((joins) && (*keylist) && (total>0)) // more than one channel and is joining - { - charlcat(keylist,',',MAXBUF); + std::string extrastuff = items2.GetToken(); + parameters[splithere] = item.c_str(); + parameters[extra] = extrastuff.c_str(); + CommandObj->Handle(parameters,pcnt,user); } + return 1; +} - /* If we're doing JOIN handling (e.g. we've had to kludge for two - * lists being handled at once, real smart by the way JRO </sarcasm>) - * and we also have keys, we must seperate out this key list into - * our char** list sep_keys for later use. - */ - if ((joins) && (*keylist)) - { - /* There is more than one key */ - if (strchr(keylist,',')) - { - j = 0; - param = keylist; - for (char* i = keylist; *i; i++) - { - if (*i == ',') - { - *i = '\0'; - sep_keys[j++] = param; - param = i+1; - } - } +int CommandParser::LoopCall(userrec* user, command_t* CommandObj, const char** parameters, int pcnt, unsigned int splithere) +{ + if (!strchr(parameters[splithere],',')) + return 0; - sep_keys[j++] = param; - total2 = j; - } - } + irc::commasepstream items1(parameters[splithere]); + std::string item = ""; - /* Now the easier bit. We call the command class's Handle function - * X times, where x is the number of parameters we've 'collated'. - */ - for (j = 0; j < total; j++) + while ((item = items1.GetToken()) != "") { - if (sep_items[j]) - { - pars[0] = sep_items[j]; - } - - for (q = end; q < pcnt-1; q++) - { - if (parameters[q+1]) - { - pars[q-end+1] = parameters[q+1]; - } - } - - if ((joins) && (parameters[1])) - { - if (pcnt > 1) - { - pars[1] = sep_keys[j]; - } - else - { - pars[1] = NULL; - } - } - - /* repeatedly call the function with the hacked parameter list */ - if ((joins) && (pcnt > 1)) - { - if (pars[1]) - { - /* pars[1] already set up and containing key from sep_keys[j] */ - fn->Handle(pars,2,u); - } - else - { - pars[1] = parameters[1]; - fn->Handle(pars,2,u); - } - } - else - { - fn->Handle(pars,pcnt-(end-start),u); - } + parameters[splithere] = item.c_str(); + CommandObj->Handle(parameters,pcnt,user); } - return 1; } diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp index 5e6d2c077..34f53ea28 100644 --- a/src/hashcomp.cpp +++ b/src/hashcomp.cpp @@ -219,3 +219,31 @@ const std::string irc::tokenstream::GetToken() } return ""; } + +irc::commasepstream::commasepstream(const std::string &source) : tokens(source) +{ + last_starting_position = tokens.begin(); + n = tokens.begin(); +} + +const std::string irc::commasepstream::GetToken() +{ + std::string::iterator lsp = last_starting_position; + + while (n != tokens.end()) + { + if ((*n == ',') || (n+1 == tokens.end())) + { + last_starting_position = n+1; + return std::string(lsp, n+1 == tokens.end() ? n+1 : n++); + } + + n++; + } + + return ""; +} + +irc::commasepstream::~commasepstream() +{ +} |