]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/coremods/core_channel/core_channel.cpp
Release v3.0.0 alpha 4.
[user/henk/code/inspircd.git] / src / coremods / core_channel / core_channel.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2014-2015 Attila Molnar <attilamolnar@hush.com>
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 "core_channel.h"
22 #include "invite.h"
23 #include "listmode.h"
24
25 class CoreModChannel : public Module, public CheckExemption::EventListener
26 {
27         Invite::APIImpl invapi;
28         CommandInvite cmdinvite;
29         CommandJoin cmdjoin;
30         CommandKick cmdkick;
31         CommandNames cmdnames;
32         CommandTopic cmdtopic;
33
34         ModeChannelBan banmode;
35         SimpleChannelModeHandler inviteonlymode;
36         ModeChannelKey keymode;
37         ModeChannelLimit limitmode;
38         SimpleChannelModeHandler moderatedmode;
39         SimpleChannelModeHandler noextmsgmode;
40         ModeChannelOp opmode;
41         SimpleChannelModeHandler privatemode;
42         SimpleChannelModeHandler secretmode;
43         SimpleChannelModeHandler topiclockmode;
44         ModeChannelVoice voicemode;
45
46         insp::flat_map<std::string, char> exemptions;
47
48         ModResult IsInvited(User* user, Channel* chan)
49         {
50                 LocalUser* localuser = IS_LOCAL(user);
51                 if ((localuser) && (invapi.IsInvited(localuser, chan)))
52                         return MOD_RES_ALLOW;
53                 return MOD_RES_PASSTHRU;
54         }
55
56  public:
57         CoreModChannel()
58                 : CheckExemption::EventListener(this)
59                 , invapi(this)
60                 , cmdinvite(this, invapi)
61                 , cmdjoin(this)
62                 , cmdkick(this)
63                 , cmdnames(this)
64                 , cmdtopic(this)
65                 , banmode(this)
66                 , inviteonlymode(this, "inviteonly", 'i')
67                 , keymode(this)
68                 , limitmode(this)
69                 , moderatedmode(this, "moderated", 'm')
70                 , noextmsgmode(this, "noextmsg", 'n')
71                 , opmode(this)
72                 , privatemode(this, "private", 'p')
73                 , secretmode(this, "secret", 's')
74                 , topiclockmode(this, "topiclock", 't')
75                 , voicemode(this)
76         {
77         }
78
79         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
80         {
81                 ConfigTag* optionstag = ServerInstance->Config->ConfValue("options");
82                 Implementation events[] = { I_OnCheckKey, I_OnCheckLimit, I_OnCheckChannelBan };
83                 if (optionstag->getBool("invitebypassmodes", true))
84                         ServerInstance->Modules.Attach(events, this, sizeof(events)/sizeof(Implementation));
85                 else
86                 {
87                         for (unsigned int i = 0; i < sizeof(events)/sizeof(Implementation); i++)
88                                 ServerInstance->Modules.Detach(events[i], this);
89                 }
90
91                 std::string current;
92                 irc::spacesepstream defaultstream(optionstag->getString("exemptchanops"));
93                 insp::flat_map<std::string, char> exempts;
94                 while (defaultstream.GetToken(current))
95                 {
96                         std::string::size_type pos = current.find(':');
97                         if (pos == std::string::npos || (pos + 2) > current.size())
98                                 throw ModuleException("Invalid exemptchanops value '" + current + "' at " + optionstag->getTagLocation());
99
100                         const std::string restriction = current.substr(0, pos);
101                         const char prefix = current[pos + 1];
102
103                         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Exempting prefix %c from %s", prefix, restriction.c_str());
104                         exempts[restriction] = prefix;
105                 }
106                 exemptions.swap(exempts);
107                 banmode.DoRehash();
108         }
109
110         void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
111         {
112                 // Build a map of limits to their mode character.
113                 insp::flat_map<int, std::string> limits;
114                 const ModeParser::ListModeList& listmodes = ServerInstance->Modes->GetListModes();
115                 for (ModeParser::ListModeList::const_iterator iter = listmodes.begin(); iter != listmodes.end(); ++iter)
116                 {
117                         const unsigned int limit = (*iter)->GetLowerLimit();
118                         limits[limit].push_back((*iter)->GetModeChar());
119                 }
120
121                 // Generate the MAXLIST token from the limits map.
122                 std::string& buffer = tokens["MAXLIST"];
123                 for (insp::flat_map<int, std::string>::const_iterator iter = limits.begin(); iter != limits.end(); ++iter)
124                 {
125                         if (!buffer.empty())
126                                 buffer.push_back(',');
127
128                         buffer.append(iter->second);
129                         buffer.push_back(':');
130                         buffer.append(ConvToStr(iter->first));
131                 }
132         }
133
134         void OnPostJoin(Membership* memb) CXX11_OVERRIDE
135         {
136                 Channel* const chan = memb->chan;
137                 LocalUser* const localuser = IS_LOCAL(memb->user);
138                 if (localuser)
139                 {
140                         // Remove existing invite, if any
141                         invapi.Remove(localuser, chan);
142
143                         if (chan->topicset)
144                                 Topic::ShowTopic(localuser, chan);
145
146                         // Show all members of the channel, including invisible (+i) users
147                         cmdnames.SendNames(localuser, chan, true);
148                 }
149         }
150
151         ModResult OnCheckKey(User* user, Channel* chan, const std::string& keygiven) CXX11_OVERRIDE
152         {
153                 // Hook only runs when being invited bypasses +bkl
154                 return IsInvited(user, chan);
155         }
156
157         ModResult OnCheckChannelBan(User* user, Channel* chan) CXX11_OVERRIDE
158         {
159                 // Hook only runs when being invited bypasses +bkl
160                 return IsInvited(user, chan);
161         }
162
163         ModResult OnCheckLimit(User* user, Channel* chan) CXX11_OVERRIDE
164         {
165                 // Hook only runs when being invited bypasses +bkl
166                 return IsInvited(user, chan);
167         }
168
169         ModResult OnCheckInvite(User* user, Channel* chan) CXX11_OVERRIDE
170         {
171                 // Hook always runs
172                 return IsInvited(user, chan);
173         }
174
175         void OnUserDisconnect(LocalUser* user) CXX11_OVERRIDE
176         {
177                 invapi.RemoveAll(user);
178         }
179
180         void OnChannelDelete(Channel* chan) CXX11_OVERRIDE
181         {
182                 // Make sure the channel won't appear in invite lists from now on, don't wait for cull to unset the ext
183                 invapi.RemoveAll(chan);
184         }
185
186         ModResult OnCheckExemption(User* user, Channel* chan, const std::string& restriction) CXX11_OVERRIDE
187         {
188                 if (!exemptions.count(restriction))
189                         return MOD_RES_PASSTHRU;
190
191                 unsigned int mypfx = chan->GetPrefixValue(user);
192                 char minmode = exemptions[restriction];
193
194                 PrefixMode* mh = ServerInstance->Modes->FindPrefixMode(minmode);
195                 if (mh && mypfx >= mh->GetPrefixRank())
196                         return MOD_RES_ALLOW;
197                 if (mh || minmode == '*')
198                         return MOD_RES_DENY;
199                 return MOD_RES_PASSTHRU;
200         }
201
202         void Prioritize() CXX11_OVERRIDE
203         {
204                 ServerInstance->Modules.SetPriority(this, I_OnPostJoin, PRIORITY_FIRST);
205         }
206
207         Version GetVersion() CXX11_OVERRIDE
208         {
209                 return Version("Provides the INVITE, JOIN, KICK, NAMES, and TOPIC commands", VF_VENDOR|VF_CORE);
210         }
211 };
212
213 MODULE_INIT(CoreModChannel)