]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_override.cpp
Tidy up strlens which are not required
[user/henk/code/inspircd.git] / src / modules / m_override.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #include "users.h"
18 #include "channels.h"
19 #include "modules.h"
20 #include "configreader.h"
21 #include "inspircd.h"
22 #include "wildcard.h"
23
24 /* $ModDesc: Provides support for unreal-style oper-override */
25
26 typedef std::map<std::string,std::string> override_t;
27
28 class ModuleOverride : public Module
29 {
30         
31         override_t overrides;
32         bool NoisyOverride;
33         bool OverriddenMode;
34         int OverOps, OverDeops, OverVoices, OverDevoices, OverHalfops, OverDehalfops;
35
36  public:
37  
38         ModuleOverride(InspIRCd* Me)
39                 : Module::Module(Me)
40         {               
41                 // read our config options (main config file)
42                 OnRehash("");
43                 ServerInstance->SNO->EnableSnomask('O',"OVERRIDE");
44                 OverriddenMode = false;
45                 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
46         }
47         
48         virtual void OnRehash(const std::string &parameter)
49         {
50                 // on a rehash we delete our classes for good measure and create them again.
51                 ConfigReader* Conf = new ConfigReader(ServerInstance);
52                 
53                 // re-read our config options on a rehash
54                 NoisyOverride = Conf->ReadFlag("override","noisy",0);
55                 overrides.clear();
56                 for (int j =0; j < Conf->Enumerate("type"); j++)
57                 {
58                         std::string typen = Conf->ReadValue("type","name",j);
59                         std::string tokenlist = Conf->ReadValue("type","override",j);
60                         overrides[typen] = tokenlist;
61                 }
62                 
63                 DELETE(Conf);
64         }
65
66         void Implements(char* List)
67         {
68                 List[I_OnRehash] = List[I_OnAccessCheck] = List[I_On005Numeric] = List[I_OnUserPreJoin] = List[I_OnUserPreKick] = List[I_OnPostCommand] = 1;
69         }
70
71         virtual void OnPostCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, CmdResult result, const std::string &original_line)
72         {
73                 if ((NoisyOverride) && (OverriddenMode) && (irc::string(command.c_str()) == "MODE") && (result == CMD_SUCCESS))
74                 {
75                         int Total = OverOps + OverDeops + OverVoices + OverDevoices + OverHalfops + OverDehalfops;
76
77                         ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" Overriding modes: "+ServerInstance->Modes->GetLastParse()+" "+(Total ? "[Detail: " : "")+
78                                         (OverOps ? ConvToStr(OverOps)+" op"+(OverOps != 1 ? "s" : "")+" " : "")+
79                                         (OverDeops ? ConvToStr(OverDeops)+" deop"+(OverDeops != 1 ? "s" : "")+" " : "")+
80                                         (OverVoices ? ConvToStr(OverVoices)+" voice"+(OverVoices != 1 ? "s" : "")+" " : "")+
81                                         (OverDevoices ? ConvToStr(OverDevoices)+" devoice"+(OverDevoices != 1 ? "s" : "")+" " : "")+
82                                         (OverHalfops ? ConvToStr(OverHalfops)+" halfop"+(OverHalfops != 1 ? "s" : "")+" " : "")+
83                                         (OverDehalfops ? ConvToStr(OverDehalfops)+" dehalfop"+(OverDehalfops != 1 ? "s" : "") : "")
84                                         +(Total ? "]" : ""));
85
86                         OverriddenMode = false;
87                         OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
88                 }
89         }
90
91         virtual void On005Numeric(std::string &output)
92         {
93                 output.append(" OVERRIDE");
94         }
95
96         virtual bool CanOverride(userrec* source, char* token)
97         {
98                 // checks to see if the oper's type has <type:override>
99                 override_t::iterator j = overrides.find(source->oper);
100                 
101                 if (j != overrides.end())
102                 {
103                         // its defined, return its value as a boolean for if the token is set
104                         return (j->second.find(token, 0) != std::string::npos);
105                 }
106                 
107                 // its not defined at all, count as false
108                 return false;
109         }
110
111         virtual int OnUserPreKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason)
112         {
113                 if ((*source->oper) && (CanOverride(source,"KICK")))
114                 {
115                         if (((chan->GetStatus(source) == STATUS_HOP) && (chan->GetStatus(user) == STATUS_OP)) || (chan->GetStatus(source) < STATUS_VOICE))
116                         {
117                                 ServerInstance->SNO->WriteToSnoMask('O',std::string(source->nick)+" Override-Kicked "+std::string(user->nick)+" on "+std::string(chan->name)+" ("+reason+")");
118                         }
119                         /* Returning -1 explicitly allows the kick */
120                         return -1;
121                 }
122                 return 0;
123         }
124         
125         virtual int OnAccessCheck(userrec* source,userrec* dest,chanrec* channel,int access_type)
126         {
127                 if (*source->oper)
128                 {
129                         if (source && channel)
130                         {
131                                 // Fix by brain - allow the change if they arent on channel - rely on boolean short-circuit
132                                 // to not check the other items in the statement if they arent on the channel
133                                 int mode = channel->GetStatus(source);
134                                 switch (access_type)
135                                 {
136                                         case AC_DEOP:
137                                                 ServerInstance->Log(DEBUG,"Override access check AC_DEOP");
138                                                 if (CanOverride(source,"MODEDEOP"))
139                                                 {
140                                                         if (NoisyOverride)
141                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
142                                                                 OverDeops++;
143                                                         return ACR_ALLOW;
144                                                 }
145                                                 else
146                                                 {
147                                                         return ACR_DEFAULT;
148                                                 }
149                                         break;
150                                         case AC_OP:
151                                                 ServerInstance->Log(DEBUG,"Override access check AC_OP");
152                                                 if (CanOverride(source,"MODEOP"))
153                                                 {
154                                                         if (NoisyOverride)
155                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
156                                                                 OverOps++;
157                                                         return ACR_ALLOW;
158                                                 }
159                                                 else
160                                                 {
161                                                         return ACR_DEFAULT;
162                                                 }
163                                         break;
164                                         case AC_VOICE:
165                                                 ServerInstance->Log(DEBUG,"Override access check AC_VOICE");
166                                                 if (CanOverride(source,"MODEVOICE"))
167                                                 {
168                                                         if (NoisyOverride)
169                                                         if ((!channel->HasUser(source)) || (mode < STATUS_HOP))
170                                                                 OverVoices++;
171                                                         return ACR_ALLOW;
172                                                 }
173                                                 else
174                                                 {
175                                                         return ACR_DEFAULT;
176                                                 }
177                                         break;
178                                         case AC_DEVOICE:
179                                                 ServerInstance->Log(DEBUG,"Override access check AC_DEVOICE");
180                                                 if (CanOverride(source,"MODEDEVOICE"))
181                                                 {
182                                                         if (NoisyOverride)
183                                                         if ((!channel->HasUser(source)) || (mode < STATUS_HOP))
184                                                                 OverDevoices++;
185                                                         return ACR_ALLOW;
186                                                 }
187                                                 else
188                                                 {
189                                                         return ACR_DEFAULT;
190                                                 }
191                                         break;
192                                         case AC_HALFOP:
193                                                 ServerInstance->Log(DEBUG,"Override access check AC_HALFOP");
194                                                 if (CanOverride(source,"MODEHALFOP"))
195                                                 {
196                                                         if (NoisyOverride)
197                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
198                                                                 OverHalfops++;
199                                                         return ACR_ALLOW;
200                                                 }
201                                                 else
202                                                 {
203                                                         return ACR_DEFAULT;
204                                                 }
205                                         break;
206                                         case AC_DEHALFOP:
207                                                 ServerInstance->Log(DEBUG,"Override access check AC_DEHALFOP");
208                                                 if (CanOverride(source,"MODEDEHALFOP"))
209                                                 {
210                                                         if (NoisyOverride)
211                                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
212                                                                 OverDehalfops++;
213                                                         return ACR_ALLOW;
214                                                 }
215                                                 else
216                                                 {
217                                                         return ACR_DEFAULT;
218                                                 }
219                                         break;
220                                 }
221                         
222                                 if (CanOverride(source,"OTHERMODE"))
223                                 {
224                                         if (NoisyOverride)
225                                         if ((!channel->HasUser(source)) || (mode < STATUS_OP))
226                                         {
227                                                 ServerInstance->Log(DEBUG,"Overridden mode");
228                                                 OverriddenMode = true;
229                                                 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
230                                         }
231                                         return ACR_ALLOW;
232                                 }
233                                 else
234                                 {
235                                         return ACR_DEFAULT;
236                                 }
237                         }
238                 }
239
240                 return ACR_DEFAULT;
241         }
242         
243         virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname, std::string &privs)
244         {
245                 if (*user->oper)
246                 {
247                         if (chan)
248                         {
249                                 if ((chan->modes[CM_INVITEONLY]) && (CanOverride(user,"INVITE")))
250                                 {
251                                         if (NoisyOverride)
252                                         {
253                                                 irc::string x = chan->name;
254                                                 if (!user->IsInvited(x))
255                                                 {
256                                                         /* XXX - Ugly cast for a parameter that isn't used? :< - Om */
257                                                         chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass invite-only", cname, user->nick);
258                                                 }
259                                         }
260                                         ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +i on "+std::string(cname));
261                                         return -1;
262                                 }
263                                 
264                                 if ((chan->key[0]) && (CanOverride(user,"KEY")))
265                                 {
266                                         if (NoisyOverride)
267                                                 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass the channel key", cname, user->nick);
268                                         ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +k on "+std::string(cname));
269                                         return -1;
270                                 }
271                                         
272                                 if ((chan->limit > 0) && (chan->GetUserCounter() >=  chan->limit) && (CanOverride(user,"LIMIT")))
273                                 {
274                                         if (NoisyOverride)
275                                                 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass the channel limit", cname, user->nick);
276                                         ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +l on "+std::string(cname));
277                                         return -1;
278                                 }
279
280                                 if (CanOverride(user,"BANWALK"))
281                                 {
282                                         if (chan->IsBanned(user))
283                                         {
284                                                 if (NoisyOverride)
285                                                 {
286                                                         chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass channel ban", cname, user->nick);
287                                                         ServerInstance->SNO->WriteToSnoMask('O',"%s used oper-override to bypass channel ban", cname, user->nick);
288                                                 }
289                                         }
290                                         return -1;
291                                 }
292                         }
293                 }
294                 return 0;
295         }
296         
297         virtual ~ModuleOverride()
298         {
299                 ServerInstance->SNO->DisableSnomask('O');
300         }
301         
302         virtual Version GetVersion()
303         {
304                 return Version(1,0,0,1,VF_VENDOR,API_VERSION);
305         }
306 };
307
308
309 class ModuleOverrideFactory : public ModuleFactory
310 {
311  public:
312         ModuleOverrideFactory()
313         {
314         }
315         
316         ~ModuleOverrideFactory()
317         {
318         }
319         
320         virtual Module * CreateModule(InspIRCd* Me)
321         {
322                 return new ModuleOverride(Me);
323         }
324         
325 };
326
327
328 extern "C" void * init_module( void )
329 {
330         return new ModuleOverrideFactory;
331 }