From: Peter Powell Date: Wed, 2 Jan 2019 17:31:31 +0000 (+0000) Subject: Fix message tags not being broadcast across the network. X-Git-Url: https://git.netwichtig.de/gitweb/?a=commitdiff_plain;h=aafc03bdfc34c9426df44938403c92dbbbc0568e;p=user%2Fhenk%2Fcode%2Finspircd.git Fix message tags not being broadcast across the network. --- diff --git a/include/clientprotocol.h b/include/clientprotocol.h index 260e463eb..10b70e80b 100644 --- a/include/clientprotocol.h +++ b/include/clientprotocol.h @@ -549,7 +549,7 @@ class ClientProtocol::MessageTagProvider : public Events::ModuleEventListener * MOD_RES_PASSTHRU to make no decision. If no hooks accept a tag, the tag is rejected. * The default implementation returns MOD_RES_PASSTHRU. */ - virtual ModResult OnClientProtocolProcessTag(LocalUser* user, const std::string& tagname, std::string& tagvalue) + virtual ModResult OnClientProtocolProcessTag(User* user, const std::string& tagname, std::string& tagvalue) { return MOD_RES_PASSTHRU; } diff --git a/src/modules/m_spanningtree/commandbuilder.h b/src/modules/m_spanningtree/commandbuilder.h index 59de84052..4bbb60e47 100644 --- a/src/modules/m_spanningtree/commandbuilder.h +++ b/src/modules/m_spanningtree/commandbuilder.h @@ -119,6 +119,30 @@ class CmdBuilder return *this; } + CmdBuilder& push_tags(const ClientProtocol::TagMap& tags) + { + if (!tags.empty()) + { + char separator = '@'; + std::string taglist; + for (ClientProtocol::TagMap::const_iterator iter = tags.begin(); iter != tags.end(); ++iter) + { + taglist.push_back(separator); + separator = ';'; + + taglist.append(iter->first); + if (!iter->second.value.empty()) + { + taglist.push_back('='); + taglist.append(iter->second.value); + } + } + taglist.push_back(' '); + content.insert(0, taglist); + } + return *this; + } + template CmdBuilder& insert(const T& cont) { diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index 2a4e927a4..985762872 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -46,6 +46,7 @@ ModuleSpanningTree::ModuleSpanningTree() , currmembid(0) , eventprov(this, "event/server") , DNS(this, "DNS") + , tagevprov(this, "event/messagetag") , loopCall(false) { } @@ -410,6 +411,7 @@ void ModuleSpanningTree::OnUserPostMessage(User* user, const MessageTarget& targ if (!IS_LOCAL(d)) { CmdBuilder params(user, message_type); + params.push_tags(details.tags_out); params.push_back(d->uuid); params.push_last(details.text); params.Unicast(d); @@ -417,12 +419,13 @@ void ModuleSpanningTree::OnUserPostMessage(User* user, const MessageTarget& targ } else if (target.type == MessageTarget::TYPE_CHANNEL) { - Utils->SendChannelMessage(user->uuid, target.Get(), details.text, target.status, details.exemptions, message_type); + Utils->SendChannelMessage(user->uuid, target.Get(), details.text, target.status, details.tags_out, details.exemptions, message_type); } else if (target.type == MessageTarget::TYPE_SERVER) { const std::string* serverglob = target.Get(); CmdBuilder par(user, message_type); + par.push_tags(details.tags_out); par.push_back(*serverglob); par.push_last(details.text); par.Broadcast(); diff --git a/src/modules/m_spanningtree/main.h b/src/modules/m_spanningtree/main.h index 4f8875a02..fa2928687 100644 --- a/src/modules/m_spanningtree/main.h +++ b/src/modules/m_spanningtree/main.h @@ -83,6 +83,9 @@ class ModuleSpanningTree public: dynamic_reference DNS; + /** Event provider for message tags. */ + Events::ModuleEventProvider tagevprov; + ServerCommandManager CmdManager; /** Set to true if inside a spanningtree call, to prevent sending diff --git a/src/modules/m_spanningtree/postcommand.cpp b/src/modules/m_spanningtree/postcommand.cpp index c7b4707b3..448bb3b54 100644 --- a/src/modules/m_spanningtree/postcommand.cpp +++ b/src/modules/m_spanningtree/postcommand.cpp @@ -39,6 +39,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscm const bool encap = ((routing.type == ROUTE_TYPE_OPT_BCAST) || (routing.type == ROUTE_TYPE_OPT_UCAST)); CmdBuilder params(user, encap ? "ENCAP" : command.c_str()); + params.push_tags(parameters.GetTags()); TreeServer* sdest = NULL; if (routing.type == ROUTE_TYPE_OPT_BCAST) @@ -100,7 +101,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscm return; // TODO OnBuildExemptList hook was here CUList exempts; - SendChannelMessage(user->uuid, c, parameters[1], pfx, exempts, command.c_str(), origin ? origin->GetSocket() : NULL); + SendChannelMessage(user->uuid, c, parameters[1], pfx, parameters.GetTags(), exempts, command.c_str(), origin ? origin->GetSocket() : NULL); } else if (dest[0] == '$') { diff --git a/src/modules/m_spanningtree/protocolinterface.cpp b/src/modules/m_spanningtree/protocolinterface.cpp index e54a528d9..56b9370ad 100644 --- a/src/modules/m_spanningtree/protocolinterface.cpp +++ b/src/modules/m_spanningtree/protocolinterface.cpp @@ -111,7 +111,8 @@ void SpanningTreeProtocolInterface::SendMessage(Channel* target, char status, co { const char* cmd = (msgtype == MSG_PRIVMSG ? "PRIVMSG" : "NOTICE"); CUList exempt_list; - Utils->SendChannelMessage(ServerInstance->Config->GetSID(), target, text, status, exempt_list, cmd); + ClientProtocol::TagMap tags; + Utils->SendChannelMessage(ServerInstance->Config->GetSID(), target, text, status, tags, exempt_list, cmd); } void SpanningTreeProtocolInterface::SendMessage(User* target, const std::string& text, MessageType msgtype) diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h index 36dd8bb93..878b34ad7 100644 --- a/src/modules/m_spanningtree/treesocket.h +++ b/src/modules/m_spanningtree/treesocket.h @@ -294,13 +294,17 @@ class TreeSocket : public BufferedSocket /** Handle IRC line split */ - void Split(const std::string &line, std::string& prefix, std::string& command, CommandBase::Params& params); + void Split(const std::string& line, std::string& tags, std::string& prefix, std::string& command, CommandBase::Params& params); /** Process complete line from buffer */ void ProcessLine(std::string &line); - void ProcessConnectedLine(std::string& prefix, std::string& command, CommandBase::Params& params); + /** Process message tags received from a remote server. */ + void ProcessTag(User* source, const std::string& tag, ClientProtocol::TagMap& tags); + + /** Process a message for a fully connected server. */ + void ProcessConnectedLine(std::string& tags, std::string& prefix, std::string& command, CommandBase::Params& params); /** Handle socket timeout from connect() */ diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp index 293cdd695..9ab8fc490 100644 --- a/src/modules/m_spanningtree/treesocket2.cpp +++ b/src/modules/m_spanningtree/treesocket2.cpp @@ -38,52 +38,61 @@ void TreeSocket::Error(CommandBase::Params& params) SetError("received ERROR " + msg); } -void TreeSocket::Split(const std::string& line, std::string& prefix, std::string& command, CommandBase::Params& params) +void TreeSocket::Split(const std::string& line, std::string& tags, std::string& prefix, std::string& command, CommandBase::Params& params) { + std::string token; irc::tokenstream tokens(line); - if (!tokens.GetMiddle(prefix)) + if (!tokens.GetMiddle(token)) return; - if (prefix[0] == ':') + if (token[0] == '@') { - prefix.erase(prefix.begin()); - - if (prefix.empty()) + if (token.length() <= 1) { - this->SendError("BUG (?) Empty prefix received: " + line); + this->SendError("BUG: Received a message with empty tags: " + line); return; } - if (!tokens.GetMiddle(command)) + + tags.assign(token, 1, std::string::npos); + if (!tokens.GetMiddle(token)) { - this->SendError("BUG (?) Empty command received: " + line); + this->SendError("BUG: Received a message with no command: " + line); return; } } - else - { - command = prefix; - prefix.clear(); - } - if (command.empty()) - this->SendError("BUG (?) Empty command received: " + line); - std::string param; - while (tokens.GetTrailing(param)) + if (token[0] == ':') { - params.push_back(param); + if (token.length() <= 1) + { + this->SendError("BUG: Received a message with an empty prefix: " + line); + return; + } + + prefix.assign(token, 1, std::string::npos); + if (!tokens.GetMiddle(token)) + { + this->SendError("BUG: Received a message with no command: " + line); + return; + } } + + command.assign(token); + while (tokens.GetTrailing(token)) + params.push_back(token); } void TreeSocket::ProcessLine(std::string &line) { + std::string tags; std::string prefix; std::string command; CommandBase::Params params; ServerInstance->Logs->Log(MODNAME, LOG_RAWIO, "S[%d] I %s", this->GetFd(), line.c_str()); - Split(line, prefix, command, params); + Split(line, tags, prefix, command, params); if (command.empty()) return; @@ -207,7 +216,7 @@ void TreeSocket::ProcessLine(std::string &line) * Credentials have been exchanged, we've gotten their 'BURST' (or sent ours). * Anything from here on should be accepted a little more reasonably. */ - this->ProcessConnectedLine(prefix, command, params); + this->ProcessConnectedLine(tags, prefix, command, params); break; case DYING: break; @@ -263,7 +272,35 @@ User* TreeSocket::FindSource(const std::string& prefix, const std::string& comma return NULL; } -void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command, CommandBase::Params& params) +void TreeSocket::ProcessTag(User* source, const std::string& tag, ClientProtocol::TagMap& tags) +{ + std::string tagkey; + std::string tagval; + const std::string::size_type p = tag.find('='); + if (p != std::string::npos) + { + // Tag has a value + tagkey.assign(tag, 0, p); + tagval.assign(tag, p + 1, std::string::npos); + } + else + { + tagkey.assign(tag); + } + + const Events::ModuleEventProvider::SubscriberList& list = Utils->Creator->tagevprov.GetSubscribers(); + for (Events::ModuleEventProvider::SubscriberList::const_iterator i = list.begin(); i != list.end(); ++i) + { + ClientProtocol::MessageTagProvider* const tagprov = static_cast(*i); + const ModResult res = tagprov->OnClientProtocolProcessTag(source, tagkey, tagval); + if (res == MOD_RES_ALLOW) + tags.insert(std::make_pair(tagkey, ClientProtocol::MessageTagData(tagprov, tagval))); + else if (res == MOD_RES_DENY) + break; + } +} + +void TreeSocket::ProcessConnectedLine(std::string& taglist, std::string& prefix, std::string& command, CommandBase::Params& params) { User* who = FindSource(prefix, command); if (!who) @@ -344,6 +381,10 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command, else { ClientProtocol::TagMap tags; + std::string tag; + irc::sepstream tagstream(taglist, ';'); + while (tagstream.GetToken(tag)) + ProcessTag(who, tag, tags); res = cmd->Handle(who, CommandBase::Params(params, tags)); if (res == CMD_INVALID) throw ProtocolException("Error in command handler"); diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp index 1224b1cf4..42eb80de5 100644 --- a/src/modules/m_spanningtree/utils.cpp +++ b/src/modules/m_spanningtree/utils.cpp @@ -352,9 +352,10 @@ Link* SpanningTreeUtilities::FindLink(const std::string& name) return NULL; } -void SpanningTreeUtilities::SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const CUList& exempt_list, const char* message_type, TreeSocket* omit) +void SpanningTreeUtilities::SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const ClientProtocol::TagMap& tags, const CUList& exempt_list, const char* message_type, TreeSocket* omit) { CmdBuilder msg(prefix, message_type); + msg.push_tags(tags); msg.push_raw(' '); if (status != 0) msg.push_raw(status); diff --git a/src/modules/m_spanningtree/utils.h b/src/modules/m_spanningtree/utils.h index e83e1c839..c6f5822fe 100644 --- a/src/modules/m_spanningtree/utils.h +++ b/src/modules/m_spanningtree/utils.h @@ -172,7 +172,7 @@ class SpanningTreeUtilities : public classbase /** Sends a PRIVMSG or a NOTICE to a channel obeying an exempt list and an optional prefix */ - void SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const CUList& exempt_list, const char* message_type, TreeSocket* omit = NULL); + void SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const ClientProtocol::TagMap& tags, const CUList& exempt_list, const char* message_type, TreeSocket* omit = NULL); }; inline void SpanningTreeUtilities::DoOneToMany(const CmdBuilder& params)