]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_chanprotect.cpp
Added comments
[user/henk/code/inspircd.git] / src / modules / m_chanprotect.cpp
1 #include <stdio.h>
2
3 #include "users.h"
4 #include "channels.h"
5 #include "modules.h"
6
7 /* $ModDesc: Provides channel modes +a and +q */
8
9 char dummyvalue[] = "on";
10
11 class ModuleChanProtect : public Module
12 {
13         Server *Srv;
14         bool FirstInGetsFounder;
15         ConfigReader *Conf;
16         
17  public:
18  
19         ModuleChanProtect()
20         {
21         
22                 // here we initialise our module. Use new to create new instances of the required
23                 // classes.
24                 
25                 Srv = new Server;
26                 Conf = new ConfigReader;
27                 
28                 // set up our modes. We're using listmodes and not normal extmodes here.
29                 // listmodes only need one parameter as everything else is assumed by the
30                 // nature of the mode thats being created.
31                 Srv->AddExtendedListMode('a');
32                 Srv->AddExtendedListMode('q');
33                 
34                 // read our config options (main config file)
35                 std::string val = Conf->ReadValue("options","noservices",0);
36                 FirstInGetsFounder = ((val == "yes") || (val == "1") || (val == "true"));
37         }
38         
39         virtual void OnRehash()
40         {
41                 // on a rehash we delete our classes for good measure and create them again.
42                 delete Conf;
43                 Conf = new ConfigReader;
44                 // re-read our config options on a rehash
45                 std::string val = Conf->ReadValue("options","noservices",0);
46                 FirstInGetsFounder = ((val == "yes") || (val == "1") || (val == "true"));
47         }
48         
49         virtual void OnUserJoin(userrec* user, chanrec* channel)
50         {
51                 // if the user is the first user into the channel, mark them as the founder, but only if
52                 // the config option for it is set
53                 if (FirstInGetsFounder)
54                 {
55                         if (Srv->CountUsers(channel) == 1)
56                         {
57                                 // we're using Extensible::Extend to add data into user objects.
58                                 // this way is best as it adds data thats accessible to other modules
59                                 // (so long as you document your code properly) without breaking anything
60                                 // because its encapsulated neatly in a map.
61                                 if (user->Extend("cm_founder_"+std::string(channel->name),dummyvalue))
62                                 {
63                                         Srv->Log(DEBUG,"Marked user "+std::string(user->nick)+" as founder for "+std::string(channel->name));
64                                 }
65                         }
66                 }
67         }
68         
69         virtual int OnAccessCheck(userrec* source,userrec* dest,chanrec* channel,int access_type)
70         {
71                 // here we perform access checks, this is the important bit that actually stops kicking/deopping
72                 // etc of protected users. There are many types of access check, we're going to handle
73                 // a relatively small number of them relevent to our module using a switch statement.
74         
75                 // don't allow action if:
76                 // (A) Theyre founder (no matter what)
77                 // (B) Theyre protected, and you're not
78                 // always allow the action if:
79                 // (A) The source is ulined
80                 
81                 
82                 // firstly, if a ulined nick, or a server, is setting the mode, then allow them to set the mode
83                 // without any access checks, we're not worthy :p
84                 if ((Srv->IsUlined(source->nick)) || (Srv->IsUlined(source->server)) || (!strcmp(source->server,"")))
85                 {
86                         return ACR_ALLOW;
87                 }
88
89                 switch (access_type)
90                 {
91                         // a user has been deopped. Do we let them? hmmm...
92                         case AC_DEOP:
93                                 if (dest->GetExt("cm_founder_"+std::string(channel->name)))
94                                 {
95                                         Srv->SendServ(source->fd,"482 "+std::string(source->nick)+" "+std::string(channel->name)+" :Can't deop "+std::string(dest->nick)+" as the're a channel founder");
96                                         return ACR_DENY;
97                                 }
98                                 if ((dest->GetExt("cm_protect_"+std::string(channel->name))) && (!source->GetExt("cm_protect_"+std::string(channel->name))))
99                                 {
100                                         Srv->SendServ(source->fd,"482 "+std::string(source->nick)+" "+std::string(channel->name)+" :Can't deop "+std::string(dest->nick)+" as the're protected (+a)");
101                                         return ACR_DENY;
102                                 }
103                         break;
104
105                         // a user is being kicked. do we chop off the end of the army boot?
106                         case AC_KICK:
107                                 if (dest->GetExt("cm_founder_"+std::string(channel->name)))
108                                 {
109                                         Srv->SendServ(source->fd,"482 "+std::string(source->nick)+" "+std::string(channel->name)+" :Can't kick "+std::string(dest->nick)+" as the're a channel founder");
110                                         return ACR_DENY;
111                                 }
112                                 if ((dest->GetExt("cm_protect_"+std::string(channel->name))) && (!source->GetExt("cm_protect_"+std::string(channel->name))))
113                                 {
114                                         Srv->SendServ(source->fd,"482 "+std::string(source->nick)+" "+std::string(channel->name)+" :Can't kick "+std::string(dest->nick)+" as the're protected (+a)");
115                                         return ACR_DENY;
116                                 }
117                         break;
118
119                         // a user is being dehalfopped. Yes, we do disallow -h of a +ha user
120                         case AC_DEHALFOP:
121                                 if (dest->GetExt("cm_founder_"+std::string(channel->name)))
122                                 {
123                                         Srv->SendServ(source->fd,"482 "+std::string(source->nick)+" "+std::string(channel->name)+" :Can't de-halfop "+std::string(dest->nick)+" as the're a channel founder");
124                                         return ACR_DENY;
125                                 }
126                                 if ((dest->GetExt("cm_protect_"+std::string(channel->name))) && (!source->GetExt("cm_protect_"+std::string(channel->name))))
127                                 {
128                                         Srv->SendServ(source->fd,"482 "+std::string(source->nick)+" "+std::string(channel->name)+" :Can't de-halfop "+std::string(dest->nick)+" as the're protected (+a)");
129                                         return ACR_DENY;
130                                 }
131                         break;
132
133                         // same with devoice.
134                         case AC_DEVOICE:
135                                 if (dest->GetExt("cm_founder_"+std::string(channel->name)))
136                                 {
137                                         Srv->SendServ(source->fd,"482 "+std::string(source->nick)+" "+std::string(channel->name)+" :Can't devoice "+std::string(dest->nick)+" as the're a channel founder");
138                                         return ACR_DENY;
139                                 }
140                                 if ((dest->GetExt("cm_protect_"+std::string(channel->name))) && (!source->GetExt("cm_protect_"+std::string(channel->name))))
141                                 {
142                                         Srv->SendServ(source->fd,"482 "+std::string(source->nick)+" "+std::string(channel->name)+" :Can't devoice "+std::string(dest->nick)+" as the're protected (+a)");
143                                         return ACR_DENY;
144                                 }
145                         break;
146                 }
147                 
148                 // we dont know what this access check is, or dont care. just carry on, nothing to see here.
149                 return ACR_DEFAULT;
150         }
151         
152         virtual int OnExtendedMode(userrec* user, void* target, char modechar, int type, bool mode_on, string_list &params)
153         {
154                 // not out mode, bail
155                 if ((modechar == 'q') && (type == MT_CHANNEL))
156                 {
157                         // set up parameters
158                         chanrec* chan = (chanrec*)target;
159                         userrec* theuser = Srv->FindNick(params[0]);
160                 
161                         // cant find the user given as the parameter, eat the mode change.
162                         if (!theuser)
163                                 return -1;
164                         
165                         // given user isnt even on the channel, eat the mode change
166                         if (!Srv->IsOnChannel(theuser,chan))
167                                 return -1;
168                         
169                         // source is a server, or ulined, we'll let them +-q the user.
170                         if ((Srv->IsUlined(user->nick)) || (Srv->IsUlined(user->server)) || (!strcmp(user->server,"")))
171                         {
172                                 if (mode_on)
173                                 {
174                                         if (!theuser->GetExt("cm_founder_"+std::string(chan->name)))
175                                         {
176                                                 theuser->Extend("cm_founder_"+std::string(chan->name),dummyvalue);
177                                                 return 1;
178                                         }
179                                 }
180                                 else
181                                 {
182                                         if (theuser->GetExt("cm_founder_"+std::string(chan->name)))
183                                         {
184                                                 theuser->Shrink("cm_founder_"+std::string(chan->name));
185                                                 return 1;
186                                         }
187                                 }       
188
189                                 return -1;
190                         }
191                         else
192                         {
193                                 // whoops, someones being naughty!
194                                 WriteServ(user->fd,"482 %s %s :Only servers may set channel mode +q",user->nick, chan->name);
195                                 return -1;
196                         }
197                 }
198                 if ((modechar == 'a') && (type == MT_CHANNEL))
199                 {
200                         // set up parameters
201                         chanrec* chan = (chanrec*)target;
202                         userrec* theuser = Srv->FindNick(params[0]);
203                 
204                         // cant find the user given as the parameter, eat the mode change.
205                         if (!theuser)
206                                 return -1;
207                         
208                         // given user isnt even on the channel, eat the mode change
209                         if (!Srv->IsOnChannel(theuser,chan))
210                                 return -1;
211
212                         // source has +q, is a server, or ulined, we'll let them +-a the user.
213                         if ((Srv->IsUlined(user->nick)) || (Srv->IsUlined(user->server)) || (!strcmp(user->server,"")) || (user->GetExt("cm_founder_"+std::string(chan->name))))
214                         {
215                                 if (mode_on)
216                                 {
217                                         if (!theuser->GetExt("cm_protect_"+std::string(chan->name)))
218                                         {
219                                                 theuser->Extend("cm_protect_"+std::string(chan->name),dummyvalue);
220                                                 return 1;
221                                         }
222                                 }
223                                 else
224                                 {
225                                         if (theuser->GetExt("cm_protect_"+std::string(chan->name)))
226                                         {
227                                                 theuser->Shrink("cm_protect_"+std::string(chan->name));
228                                                 return 1;
229                                         }
230                                 }       
231
232                                 return -1;
233                         }
234                         else
235                         {
236                                 // bzzzt, wrong answer!
237                                 WriteServ(user->fd,"482 %s %s :You are not a channel founder",user->nick, chan->name);
238                                 return -1;
239                         }
240                 }
241                 return 0;
242         }
243         
244         virtual ~ModuleChanProtect()
245         {
246                 delete Conf;
247                 delete Srv;
248         }
249         
250         virtual Version GetVersion()
251         {
252                 return Version(1,0,0,0);
253         }
254         
255         virtual string_list OnChannelSync(chanrec* chan)
256         {
257                 // this is called when the server is linking into a net and wants to sync channel data.
258                 // we should send our mode changes for the channel here to ensure that other servers
259                 // know whos +q/+a on the channel.
260                 chanuserlist cl = Srv->GetUsers(chan);
261                 string_list commands;
262                 for (int i = 0; i < cl.size(); i++)
263                 {
264                         if (cl[i]->GetExt("cm_founder_"+std::string(chan->name)))
265                         {
266                                 commands.push_back("M "+std::string(chan->name)+" +q "+std::string(cl[i]->nick));
267                         }
268                         if (cl[i]->GetExt("cm_protect_"+std::string(chan->name)))
269                         {
270                                 commands.push_back("M "+std::string(chan->name)+" +a "+std::string(cl[i]->nick));
271                         }
272                 }
273                 return commands;
274         }
275
276 };
277
278
279 class ModuleChanProtectFactory : public ModuleFactory
280 {
281  public:
282         ModuleChanProtectFactory()
283         {
284         }
285         
286         ~ModuleChanProtectFactory()
287         {
288         }
289         
290         virtual Module * CreateModule()
291         {
292                 return new ModuleChanProtect;
293         }
294         
295 };
296
297
298 extern "C" void * init_module( void )
299 {
300         return new ModuleChanProtectFactory;
301 }
302