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