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