]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_ircv3_msgid.cpp
8b56ba6c7a8cd5f32f0b832fdc423fe8b9c8c91b
[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/cap.h"
22 #include "modules/ctctags.h"
23
24 class MsgIdTag : public ClientProtocol::MessageTagProvider
25 {
26  private:
27         Cap::Reference ctctagcap;
28
29  public:
30         MsgIdTag(Module* mod)
31                 : ClientProtocol::MessageTagProvider(mod)
32                 , ctctagcap(mod, "message-tags")
33         {
34         }
35
36         ModResult OnProcessTag(User* user, const std::string& tagname, std::string& tagvalue) CXX11_OVERRIDE
37         {
38                 if (!irc::equals(tagname, "msgid"))
39                         return MOD_RES_PASSTHRU;
40
41                 // We should only allow this tag if it is added by a remote server.
42                 return IS_LOCAL(user) ? MOD_RES_DENY : MOD_RES_ALLOW;
43         }
44
45         bool ShouldSendTag(LocalUser* user, const ClientProtocol::MessageTagData& tagdata) CXX11_OVERRIDE
46         {
47                 return ctctagcap.get(user);
48         }
49 };
50
51 class MsgIdGenerator
52 {
53         uint64_t counter;
54         std::string strid;
55         const std::string::size_type baselen;
56
57  public:
58         MsgIdGenerator()
59                 : counter(0)
60                 , strid(InspIRCd::Format("%s~%lu~", ServerInstance->Config->GetSID().c_str(), ServerInstance->startup_time))
61                 , baselen(strid.length())
62         {
63         }
64
65         const std::string& GetNext()
66         {
67                 strid.erase(baselen);
68                 strid.append(ConvToStr(counter++));
69                 return strid;
70         }
71 };
72
73 class ModuleMsgId
74         : public Module
75         , public CTCTags::EventListener
76 {
77  private:
78         MsgIdTag tag;
79         MsgIdGenerator generator;
80
81         ModResult CopyMessageId(const ClientProtocol::TagMap& tags_in, ClientProtocol::TagMap& tags_out)
82         {
83                 ClientProtocol::TagMap::const_iterator iter = tags_in.find("msgid");
84                 if (iter != tags_in.end())
85                 {
86                         // If the remote server has sent a message identifier we should use that as
87                         // identifiers need to be the same on all sides of the network.
88                         tags_out.insert(*iter);
89                         return MOD_RES_PASSTHRU;
90                 }
91
92                 // Otherwise, we can just create a new message identifier.
93                 tags_out.insert(std::make_pair("msgid", ClientProtocol::MessageTagData(&tag, generator.GetNext())));
94                 return MOD_RES_PASSTHRU;
95         }
96
97  public:
98         ModuleMsgId()
99                 : CTCTags::EventListener(this)
100                 , tag(this)
101         {
102         }
103
104         ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) CXX11_OVERRIDE
105         {
106                 return CopyMessageId(details.tags_in, details.tags_out);
107         }
108
109         ModResult OnUserPreTagMessage(User* user, const MessageTarget& target, CTCTags::TagMessageDetails& details) CXX11_OVERRIDE
110         {
111                 return CopyMessageId(details.tags_in, details.tags_out);
112         }
113
114         Version GetVersion() CXX11_OVERRIDE
115         {
116                 return Version("Provides the msgid IRCv3 tag", VF_VENDOR);
117         }
118 };
119
120 MODULE_INIT(ModuleMsgId)