X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fcoremods%2Fcore_privmsg.cpp;h=dae770abef57588601c00ff5f625e8a592af3e4e;hb=33180223e318c304892b3fa8640f90f1ddf6f4b4;hp=2daeef3ad6636ac6d852b1b1df4596eb111c7c42;hpb=58a0a7e01422e62de1565a8eb0a1febdc463d04d;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/coremods/core_privmsg.cpp b/src/coremods/core_privmsg.cpp index 2daeef3ad..dae770abe 100644 --- a/src/coremods/core_privmsg.cpp +++ b/src/coremods/core_privmsg.cpp @@ -21,6 +21,74 @@ #include "inspircd.h" +class MessageDetailsImpl : public MessageDetails +{ +public: + MessageDetailsImpl(MessageType mt, const std::string& msg, const ClientProtocol::TagMap& tags) + : MessageDetails(mt, msg, tags) + { + } + + bool IsCTCP(std::string& name, std::string& body) const CXX11_OVERRIDE + { + if (!this->IsCTCP()) + return false; + + size_t end_of_name = text.find(' ', 2); + size_t end_of_ctcp = *text.rbegin() == '\x1' ? 1 : 0; + if (end_of_name == std::string::npos) + { + // The CTCP only contains a name. + name.assign(text, 1, text.length() - 1 - end_of_ctcp); + body.clear(); + return true; + } + + // The CTCP contains a name and a body. + name.assign(text, 1, end_of_name - 1); + + size_t start_of_body = text.find_first_not_of(' ', end_of_name + 1); + if (start_of_body == std::string::npos) + { + // The CTCP body is provided but empty. + body.clear(); + return true; + } + + // The CTCP body provided was non-empty. + body.assign(text, start_of_body, text.length() - start_of_body - end_of_ctcp); + return true; + } + + bool IsCTCP(std::string& name) const CXX11_OVERRIDE + { + if (!this->IsCTCP()) + return false; + + size_t end_of_name = text.find(' ', 2); + if (end_of_name == std::string::npos) + { + // The CTCP only contains a name. + size_t end_of_ctcp = *text.rbegin() == '\x1' ? 1 : 0; + name.assign(text, 1, text.length() - 1 - end_of_ctcp); + return true; + } + + // The CTCP contains a name and a body. + name.assign(text, 1, end_of_name - 1); + return true; + } + + bool IsCTCP() const CXX11_OVERRIDE + { + // According to draft-oakley-irc-ctcp-02 a valid CTCP must begin with SOH and + // contain at least one octet which is not NUL, SOH, CR, LF, or SPACE. As most + // of these are restricted at the protocol level we only need to check for SOH + // and SPACE. + return (text.length() >= 2) && (text[0] == '\x1') && (text[1] != '\x1') && (text[1] != ' '); + } +}; + class MessageCommandBase : public Command { ChanModeReference moderatedmode; @@ -80,10 +148,6 @@ CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters User *dest; Channel *chan; - LocalUser* localuser = IS_LOCAL(user); - if (localuser) - localuser->idle_lastmsg = ServerInstance->Time(); - if (CommandParser::LoopCall(user, this, parameters, 0)) return CMD_SUCCESS; @@ -94,7 +158,7 @@ CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters std::string servername(parameters[0], 1); MessageTarget msgtarget(&servername); - MessageDetails msgdetails(mt, parameters[1], parameters.GetTags()); + MessageDetailsImpl msgdetails(mt, parameters[1], parameters.GetTags()); ModResult MOD_RESULT; FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, msgtarget, msgdetails)); @@ -127,7 +191,7 @@ CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters if (chan) { - if (localuser && chan->GetPrefixValue(user) < VOICE_VALUE) + if (IS_LOCAL(user) && chan->GetPrefixValue(user) < VOICE_VALUE) { if (chan->IsModeSet(noextmsgmode) && !chan->HasUser(user)) { @@ -153,7 +217,7 @@ CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters } MessageTarget msgtarget(chan, status); - MessageDetails msgdetails(mt, parameters[1], parameters.GetTags()); + MessageDetailsImpl msgdetails(mt, parameters[1], parameters.GetTags()); msgdetails.exemptions.insert(user); ModResult MOD_RESULT; @@ -191,7 +255,7 @@ CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters const char* destnick = parameters[0].c_str(); - if (localuser) + if (IS_LOCAL(user)) { const char* targetserver = strchr(destnick, '@'); @@ -229,7 +293,7 @@ CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters } MessageTarget msgtarget(dest); - MessageDetails msgdetails(mt, parameters[1], parameters.GetTags()); + MessageDetailsImpl msgdetails(mt, parameters[1], parameters.GetTags()); ModResult MOD_RESULT; @@ -289,6 +353,20 @@ class ModuleCoreMessage : public Module { } + void OnUserPostMessage(User* user, const MessageTarget& target, const MessageDetails& details) CXX11_OVERRIDE + { + // We only handle the idle times of local users. + LocalUser* luser = IS_LOCAL(user); + if (!luser) + return; + + // We don't update the idle time when a CTCP reply is sent. + if (details.type == MSG_NOTICE && details.IsCTCP()) + return; + + luser->idle_lastmsg = ServerInstance->Time(); + } + Version GetVersion() CXX11_OVERRIDE { return Version("PRIVMSG, NOTICE", VF_CORE|VF_VENDOR);