summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorattilamolnar <attilamolnar@hush.com>2013-06-12 20:32:10 +0200
committerattilamolnar <attilamolnar@hush.com>2013-06-12 20:32:10 +0200
commitcfa32a6561e0152ebbd7135eaec9f7c794c170b1 (patch)
tree4c2d00aeee9de1014a336494b1e4ac3935f5b51b /src
parent98f3924960d849691abc81e0928dc43ad9233b01 (diff)
CommandParser::LoopCall() changes
- Change function to be static, return a bool - Do not filter duplicates when there are 2 lists (JOIN) - Remove validation of 'extra' parameter, caller must pass either a valid index or -1
Diffstat (limited to 'src')
-rw-r--r--src/command_parse.cpp57
-rw-r--r--src/commands/cmd_join.cpp4
-rw-r--r--src/commands/cmd_kick.cpp2
-rw-r--r--src/commands/cmd_kill.cpp2
-rw-r--r--src/commands/cmd_names.cpp2
-rw-r--r--src/commands/cmd_part.cpp2
-rw-r--r--src/commands/cmd_privmsg.cpp2
-rw-r--r--src/commands/cmd_whois.cpp2
-rw-r--r--src/modules/m_callerid.cpp2
9 files changed, 34 insertions, 41 deletions
diff --git a/src/command_parse.cpp b/src/command_parse.cpp
index e8d68c847..6331b5da4 100644
--- a/src/command_parse.cpp
+++ b/src/command_parse.cpp
@@ -44,67 +44,60 @@ int InspIRCd::PassCompare(Extensible* ex, const std::string &data, const std::st
return (data != input); // this seems back to front, but returns 0 if they *match*, 1 else
}
-/* LoopCall is used to call a command classes handler repeatedly based on the contents of a comma seperated list.
- * There are two overriden versions of this method, one of which takes two potential lists and the other takes one.
- * We need a version which takes two potential lists for JOIN, because a JOIN may contain two lists of items at once,
- * the channel names and their keys as follows:
- * JOIN #chan1,#chan2,#chan3 key1,,key3
- * Therefore, we need to deal with both lists concurrently. The first instance of this method does that by creating
- * two instances of irc::commasepstream and reading them both together until the first runs out of tokens.
- * The second version is much simpler and just has the one stream to read, and is used in NAMES, WHOIS, PRIVMSG etc.
- * Both will only parse until they reach ServerInstance->Config->MaxTargets number of targets, to stop abuse via spam.
- */
-int CommandParser::LoopCall(User* user, Command* CommandObj, const std::vector<std::string>& parameters, unsigned int splithere, int extra, bool usemax)
+bool CommandParser::LoopCall(User* user, Command* CommandObj, const std::vector<std::string>& parameters, unsigned int splithere, int extra, bool usemax)
{
if (splithere >= parameters.size())
- return 0;
-
- if (extra >= (signed)parameters.size())
- extra = -1;
+ return false;
- /* First check if we have more than one item in the list, if we don't we return zero here and the handler
+ /* First check if we have more than one item in the list, if we don't we return false here and the handler
* which called us just carries on as it was.
*/
if (parameters[splithere].find(',') == std::string::npos)
- return 0;
+ return false;
/** Some lame ircds will weed out dupes using some shitty O(n^2) algorithm.
* By using std::set (thanks for the idea w00t) we can cut this down a ton.
* ...VOOODOOOO!
+ *
+ * Only check for duplicates if there is one list (allow them in JOIN).
*/
std::set<irc::string> dupes;
+ bool check_dupes = (extra < 0);
- /* Create two lists, one for channel names, one for keys
+ /* Create two sepstreams, if we have only one list, then initialize the second sepstream with
+ * an empty string. The second parameter of the constructor of the sepstream tells whether
+ * or not to allow empty tokens.
+ * We allow empty keys, so "JOIN #a,#b ,bkey" will be interpreted as "JOIN #a", "JOIN #b bkey"
*/
irc::commasepstream items1(parameters[splithere]);
- irc::commasepstream items2(extra >= 0 ? parameters[extra] : "");
- std::string extrastuff;
+ irc::commasepstream items2(extra >= 0 ? parameters[extra] : "", true);
std::string item;
unsigned int max = 0;
- /* Attempt to iterate these lists and call the command objech
- * which called us, for every parameter pair until there are
- * no more left to parse.
+ /* Attempt to iterate these lists and call the command handler
+ * for every parameter or parameter pair until there are no more
+ * left to parse.
*/
while (items1.GetToken(item) && (!usemax || max++ < ServerInstance->Config->MaxTargets))
{
- if (dupes.find(item.c_str()) == dupes.end())
+ if ((!check_dupes) || (dupes.insert(item.c_str()).second))
{
std::vector<std::string> new_parameters(parameters);
-
- if (!items2.GetToken(extrastuff))
- extrastuff.clear();
-
new_parameters[splithere] = item;
+
if (extra >= 0)
- new_parameters[extra] = extrastuff;
+ {
+ // If we have two lists then get the next item from the second list.
+ // In case it runs out of elements then 'item' will be an empty string.
+ items2.GetToken(item);
+ new_parameters[extra] = item;
+ }
CommandObj->Handle(new_parameters, user);
-
- dupes.insert(item.c_str());
}
}
- return 1;
+
+ return true;
}
bool CommandParser::IsValidCommand(const std::string &commandname, unsigned int pcnt, User * user)
diff --git a/src/commands/cmd_join.cpp b/src/commands/cmd_join.cpp
index a88509bc2..9e2678b5d 100644
--- a/src/commands/cmd_join.cpp
+++ b/src/commands/cmd_join.cpp
@@ -52,7 +52,7 @@ CmdResult CommandJoin::HandleLocal(const std::vector<std::string>& parameters, L
{
if (parameters.size() > 1)
{
- if (ServerInstance->Parser->LoopCall(user, this, parameters, 0, 1, false))
+ if (CommandParser::LoopCall(user, this, parameters, 0, 1, false))
return CMD_SUCCESS;
if (ServerInstance->IsChannel(parameters[0]))
@@ -63,7 +63,7 @@ CmdResult CommandJoin::HandleLocal(const std::vector<std::string>& parameters, L
}
else
{
- if (ServerInstance->Parser->LoopCall(user, this, parameters, 0, -1, false))
+ if (CommandParser::LoopCall(user, this, parameters, 0, -1, false))
return CMD_SUCCESS;
if (ServerInstance->IsChannel(parameters[0]))
diff --git a/src/commands/cmd_kick.cpp b/src/commands/cmd_kick.cpp
index 016a14b2e..825cfebcb 100644
--- a/src/commands/cmd_kick.cpp
+++ b/src/commands/cmd_kick.cpp
@@ -48,7 +48,7 @@ CmdResult CommandKick::Handle (const std::vector<std::string>& parameters, User
Channel* c = ServerInstance->FindChan(parameters[0]);
User* u;
- if (ServerInstance->Parser->LoopCall(user, this, parameters, 1))
+ if (CommandParser::LoopCall(user, this, parameters, 1))
return CMD_SUCCESS;
if (IS_LOCAL(user))
diff --git a/src/commands/cmd_kill.cpp b/src/commands/cmd_kill.cpp
index 6bf657115..04a59f60a 100644
--- a/src/commands/cmd_kill.cpp
+++ b/src/commands/cmd_kill.cpp
@@ -57,7 +57,7 @@ class CommandKill : public Command
CmdResult CommandKill::Handle (const std::vector<std::string>& parameters, User *user)
{
/* Allow comma seperated lists of users for /KILL (thanks w00t) */
- if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ if (CommandParser::LoopCall(user, this, parameters, 0))
return CMD_SUCCESS;
User *u = ServerInstance->FindNick(parameters[0]);
diff --git a/src/commands/cmd_names.cpp b/src/commands/cmd_names.cpp
index 0c06b636f..1f0de91f1 100644
--- a/src/commands/cmd_names.cpp
+++ b/src/commands/cmd_names.cpp
@@ -52,7 +52,7 @@ CmdResult CommandNames::Handle (const std::vector<std::string>& parameters, User
return CMD_SUCCESS;
}
- if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ if (CommandParser::LoopCall(user, this, parameters, 0))
return CMD_SUCCESS;
c = ServerInstance->FindChan(parameters[0]);
diff --git a/src/commands/cmd_part.cpp b/src/commands/cmd_part.cpp
index aadb42d90..9b8d1d717 100644
--- a/src/commands/cmd_part.cpp
+++ b/src/commands/cmd_part.cpp
@@ -57,7 +57,7 @@ CmdResult CommandPart::Handle (const std::vector<std::string>& parameters, User
reason = parameters[1];
}
- if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ if (CommandParser::LoopCall(user, this, parameters, 0))
return CMD_SUCCESS;
Channel* c = ServerInstance->FindChan(parameters[0]);
diff --git a/src/commands/cmd_privmsg.cpp b/src/commands/cmd_privmsg.cpp
index eb9468bb9..7de3bf924 100644
--- a/src/commands/cmd_privmsg.cpp
+++ b/src/commands/cmd_privmsg.cpp
@@ -62,7 +62,7 @@ CmdResult MessageCommandBase::HandleMessage(const std::vector<std::string>& para
if (localuser)
localuser->idle_lastmsg = ServerInstance->Time();
- if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ if (CommandParser::LoopCall(user, this, parameters, 0))
return CMD_SUCCESS;
if (parameters[0][0] == '$')
diff --git a/src/commands/cmd_whois.cpp b/src/commands/cmd_whois.cpp
index de3d71152..9048184f6 100644
--- a/src/commands/cmd_whois.cpp
+++ b/src/commands/cmd_whois.cpp
@@ -195,7 +195,7 @@ CmdResult CommandWhois::HandleLocal(const std::vector<std::string>& parameters,
int userindex = 0;
unsigned long idle = 0, signon = 0;
- if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ if (CommandParser::LoopCall(user, this, parameters, 0))
return CMD_SUCCESS;
/*
diff --git a/src/modules/m_callerid.cpp b/src/modules/m_callerid.cpp
index 9cc9aaf5e..0fffe4061 100644
--- a/src/modules/m_callerid.cpp
+++ b/src/modules/m_callerid.cpp
@@ -189,7 +189,7 @@ public:
*/
CmdResult Handle(const std::vector<std::string> &parameters, User* user)
{
- if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ if (CommandParser::LoopCall(user, this, parameters, 0))
return CMD_SUCCESS;
/* Even if callerid mode is not set, we let them manage their ACCEPT list so that if they go +g they can
* have a list already setup. */