diff options
author | Peter Powell <petpow@saberuk.com> | 2018-08-10 09:04:30 +0100 |
---|---|---|
committer | Peter Powell <petpow@saberuk.com> | 2018-08-10 20:04:56 +0100 |
commit | 02838a09396a3626b61263791570e96324563fa0 (patch) | |
tree | 2978bacea011256f66f799bf5b8f91dc8590a398 | |
parent | 8b418f081f7ecbfdd51c84fae2298f927155fac0 (diff) |
Move message parsing to ProcessBuffer and fix edge cases in it.
-rw-r--r-- | include/command_parse.h | 9 | ||||
-rw-r--r-- | src/command_parse.cpp | 60 | ||||
-rw-r--r-- | src/hashcomp.cpp | 5 | ||||
-rw-r--r-- | src/modules/m_passforward.cpp | 2 | ||||
-rw-r--r-- | src/users.cpp | 2 |
5 files changed, 47 insertions, 31 deletions
diff --git a/include/command_parse.h b/include/command_parse.h index 8324e5e25..f5cb47620 100644 --- a/include/command_parse.h +++ b/include/command_parse.h @@ -34,10 +34,11 @@ class CoreExport CommandParser private: /** Process a command from a user. - * @param user The user to parse the command for - * @param cmd The command string to process + * @param user The user to parse the command for. + * @param command The name of the command. + * @param parameters The parameters to the command. */ - void ProcessCommand(LocalUser* user, std::string& cmd); + void ProcessCommand(LocalUser* user, std::string& command, Command::Params& parameters); /** Command list, a hash_map of command names to Command* */ @@ -116,7 +117,7 @@ class CoreExport CommandParser * @param buffer The buffer line to process * @param user The user to whom this line belongs */ - void ProcessBuffer(std::string &buffer,LocalUser *user); + void ProcessBuffer(LocalUser* user, const std::string& buffer); /** Add a new command to the commands hash * @param f The new Command to add to the list diff --git a/src/command_parse.cpp b/src/command_parse.cpp index fb8ea2565..c133c475e 100644 --- a/src/command_parse.cpp +++ b/src/command_parse.cpp @@ -159,26 +159,8 @@ CmdResult CommandParser::CallHandler(const std::string& commandname, const Comma return CMD_INVALID; } -void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd) +void CommandParser::ProcessCommand(LocalUser* user, std::string& command, Command::Params& command_p) { - CommandBase::Params command_p; - irc::tokenstream tokens(cmd); - std::string command, token; - tokens.GetMiddle(command); - - /* A client sent a nick prefix on their command (ick) - * rhapsody and some braindead bouncers do this -- - * the rfc says they shouldnt but also says the ircd should - * discard it if they do. - */ - if (command[0] == ':') - tokens.GetMiddle(command); - - while (tokens.GetTrailing(token)) - command_p.push_back(token); - - std::transform(command.begin(), command.end(), command.begin(), ::toupper); - /* find the command, check it exists */ Command* handler = GetHandler(command); @@ -385,13 +367,47 @@ void Command::RegisterService() throw ModuleException("Command already exists: " + name); } -void CommandParser::ProcessBuffer(std::string &buffer,LocalUser *user) +void CommandParser::ProcessBuffer(LocalUser* user, const std::string& buffer) { - if (buffer.empty()) + size_t start = buffer.find_first_not_of(" "); + if (start == std::string::npos) + { + // Discourage the user from flooding the server. + user->CommandFloodPenalty += 2000; return; + } ServerInstance->Logs->Log("USERINPUT", LOG_RAWIO, "C[%s] I %s", user->uuid.c_str(), buffer.c_str()); - ProcessCommand(user,buffer); + + irc::tokenstream tokens(buffer, start); + std::string command; + CommandBase::Params parameters; + + // Get the command name. This will always exist because of the check + // at the start of the function. + tokens.GetMiddle(command); + + // If this exists then the client sent a prefix as part of their + // message. Section 2.3 of RFC 1459 technically says we should only + // allow the nick of the client here but in practise everyone just + // ignores it so we will copy them. + if (command[0] == ':' && !tokens.GetMiddle(command)) + { + // Discourage the user from flooding the server. + user->CommandFloodPenalty += 2000; + return; + } + + // We upper-case the command name to ensure consistency internally. + std::transform(command.begin(), command.end(), command.begin(), ::toupper); + + // Build the parameter map. We intentionally do not respect the RFC 1459 + // thirteen parameter limit here. + std::string parameter; + while (tokens.GetTrailing(parameter)) + parameters.push_back(parameter); + + ProcessCommand(user, command, parameters); } bool CommandParser::AddCommand(Command *f) diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp index 47c36b91b..8febcbb5f 100644 --- a/src/hashcomp.cpp +++ b/src/hashcomp.cpp @@ -212,7 +212,7 @@ bool irc::tokenstream::GetMiddle(std::string& token) size_t separator = message.find(' ', position); if (separator == std::string::npos) { - token.assign(message, position); + token.assign(message, position, std::string::npos); position = message.length(); return true; } @@ -234,9 +234,8 @@ bool irc::tokenstream::GetTrailing(std::string& token) // If this is true then we have a <trailing> token! if (message[position] == ':') { - token.assign(message, position + 1); + token.assign(message, position + 1, std::string::npos); position = message.length(); - ServerInstance->Logs->Log("HASHCOMP", LOG_DEBUG, "TRAILING %s next (none)", token.c_str()); return true; } diff --git a/src/modules/m_passforward.cpp b/src/modules/m_passforward.cpp index 3050dba0b..e3f8624fc 100644 --- a/src/modules/m_passforward.cpp +++ b/src/modules/m_passforward.cpp @@ -96,7 +96,7 @@ class ModulePassForward : public Module tmp.clear(); FormatStr(tmp,forwardcmd, user); - ServerInstance->Parser.ProcessBuffer(tmp,user); + ServerInstance->Parser.ProcessBuffer(user, tmp); } }; diff --git a/src/users.cpp b/src/users.cpp index 52e1f3e95..737a3fa5c 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -285,7 +285,7 @@ void UserIOHandler::OnDataReady() user->bytes_in += qpos; user->cmds_in++; - ServerInstance->Parser.ProcessBuffer(line, user); + ServerInstance->Parser.ProcessBuffer(user, line); if (user->quitting) return; |