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