]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_ircv3_msgid.cpp
Add a CapReference class for the message-tags capability.
[user/henk/code/inspircd.git] / src / modules / m_ircv3_msgid.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2019 Sadie Powell <sadie@witchery.services>
5  *
6  * This file is part of InspIRCd.  InspIRCd is free software: you can
7  * redistribute it and/or modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation, version 2.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19
20 #include "inspircd.h"
21 #include "modules/ctctags.h"
22
23 class MsgIdTag : public ClientProtocol::MessageTagProvider
24 {
25  private:
26         CTCTags::CapReference ctctagcap;
27
28  public:
29         MsgIdTag(Module* mod)
30                 : ClientProtocol::MessageTagProvider(mod)
31                 , ctctagcap(mod)
32         {
33         }
34
35         ModResult OnProcessTag(User* user, const std::string& tagname, std::string& tagvalue) CXX11_OVERRIDE
36         {
37                 if (!irc::equals(tagname, "msgid"))
38                         return MOD_RES_PASSTHRU;
39
40                 // We should only allow this tag if it is added by a remote server.
41                 return IS_LOCAL(user) ? MOD_RES_DENY : MOD_RES_ALLOW;
42         }
43
44         bool ShouldSendTag(LocalUser* user, const ClientProtocol::MessageTagData& tagdata) CXX11_OVERRIDE
45         {
46                 return ctctagcap.get(user);
47         }
48 };
49
50 class MsgIdGenerator
51 {
52         uint64_t counter;
53         std::string strid;
54         const std::string::size_type baselen;
55
56  public:
57         MsgIdGenerator()
58                 : counter(0)
59                 , strid(InspIRCd::Format("%s~%lu~", ServerInstance->Config->GetSID().c_str(), ServerInstance->startup_time))
60                 , baselen(strid.length())
61         {
62         }
63
64         const std::string& GetNext()
65         {
66                 strid.erase(baselen);
67                 strid.append(ConvToStr(counter++));
68                 return strid;
69         }
70 };
71
72 class ModuleMsgId
73         : public Module
74         , public CTCTags::EventListener
75 {
76  private:
77         MsgIdTag tag;
78         MsgIdGenerator generator;
79
80         ModResult CopyMessageId(const ClientProtocol::TagMap& tags_in, ClientProtocol::TagMap& tags_out)
81         {
82                 ClientProtocol::TagMap::const_iterator iter = tags_in.find("msgid");
83                 if (iter != tags_in.end())
84                 {
85                         // If the remote server has sent a message identifier we should use that as
86                         // identifiers need to be the same on all sides of the network.
87                         tags_out.insert(*iter);
88                         return MOD_RES_PASSTHRU;
89                 }
90
91                 // Otherwise, we can just create a new message identifier.
92                 tags_out.insert(std::make_pair("msgid", ClientProtocol::MessageTagData(&tag, generator.GetNext())));
93                 return MOD_RES_PASSTHRU;
94         }
95
96  public:
97         ModuleMsgId()
98                 : CTCTags::EventListener(this)
99                 , tag(this)
100         {
101         }
102
103         ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) CXX11_OVERRIDE
104         {
105                 return CopyMessageId(details.tags_in, details.tags_out);
106         }
107
108         ModResult OnUserPreTagMessage(User* user, const MessageTarget& target, CTCTags::TagMessageDetails& details) CXX11_OVERRIDE
109         {
110                 return CopyMessageId(details.tags_in, details.tags_out);
111         }
112
113         Version GetVersion() CXX11_OVERRIDE
114         {
115                 return Version("Provides the msgid IRCv3 tag", VF_VENDOR);
116         }
117 };
118
119 MODULE_INIT(ModuleMsgId)