]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_services.cpp
Allocate id properly
[user/henk/code/inspircd.git] / src / modules / m_services.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 using namespace std;
18
19 #include <stdio.h>
20 #include "users.h"
21 #include "channels.h"
22 #include "modules.h"
23 #include <string>
24 #include "helperfuncs.h"
25 #include "hashcomp.h"
26
27 static bool kludgeme = false;
28
29 /* $ModDesc: Povides support for services +r user/chan modes and more */
30
31 class Channel_r : public ModeHandler
32 {
33         Server* Srv;
34  public:
35         Channel_r(Server* srv) : ModeHandler('r', 0, 0, false, MODETYPE_CHANNEL, false), Srv(srv) { }
36
37         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
38         {
39                 // only a u-lined server may add or remove the +r mode.
40                 if ((Srv->IsUlined(source->nick)) || (Srv->IsUlined(source->server)) || (!*source->server || (strchr(source->nick,'.'))))
41                 {
42                         log(DEBUG,"Allowing cmode +r, server and nick are: '%s','%s'",source->nick,source->server);
43                         channel->SetMode('r',adding);
44                         return MODEACTION_ALLOW;
45                 }
46                 else
47                 {
48                         log(DEBUG,"Only a server can set chanmode +r, server and nick are: '%s','%s'",source->nick,source->server);
49                         Srv->SendServ(source->fd,"500 "+std::string(source->nick)+" :Only a server may modify the +r channel mode");
50                         return MODEACTION_DENY;
51                 }
52         }
53 };
54
55 class User_r : public ModeHandler
56 {
57         Server* Srv;
58  public:
59         User_r(Server* srv) : ModeHandler('r', 0, 0, false, MODETYPE_USER, false), Srv(srv) { }
60
61         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
62         {
63                 if ((kludgeme) || (Srv->IsUlined(source->nick)) || (Srv->IsUlined(source->server)) || (!*source->server || (strchr(source->nick,'.'))))
64                 {
65                         log(DEBUG,"Allowing umode +r, server and nick are: '%s','%s'",source->nick,source->server);
66                         dest->SetMode('r',adding);
67                         return MODEACTION_ALLOW;
68                 }
69                 else
70                 {
71                         log(DEBUG,"Only a server can set umode +r, server and nick are: '%s','%s'",source->nick, source->server);
72                         Srv->SendServ(source->fd,"500 "+std::string(source->nick)+" :Only a server may modify the +r user mode");
73                         return MODEACTION_DENY;
74                 }
75         }
76 };
77
78 class Channel_R : public ModeHandler
79 {
80  public:
81         Channel_R() : ModeHandler('R', 0, 0, false, MODETYPE_CHANNEL, false) { }
82
83         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
84         {
85                 if (adding)
86                 {
87                         if (!channel->IsModeSet('R'))
88                         {
89                                 channel->SetMode('R',true);
90                                 return MODEACTION_ALLOW;
91                         }
92                 }
93                 else
94                 {
95                         if (channel->IsModeSet('R'))
96                         {
97                                 channel->SetMode('R',false);
98                                 return MODEACTION_ALLOW;
99                         }
100                 }
101
102                 return MODEACTION_DENY;
103         }
104 };
105
106 class User_R : public ModeHandler
107 {
108  public:
109         User_R() : ModeHandler('R', 0, 0, false, MODETYPE_USER, false) { }
110
111         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
112         {
113                 if (adding)
114                 {
115                         if (!dest->IsModeSet('R'))
116                         {
117                                 dest->SetMode('R',true);
118                                 return MODEACTION_ALLOW;
119                         }
120                 }
121                 else
122                 {
123                         if (dest->IsModeSet('R'))
124                         {
125                                 dest->SetMode('R',false);
126                                 return MODEACTION_ALLOW;
127                         }
128                 }
129
130                 return MODEACTION_DENY;
131         }
132 };
133
134 class Channel_M : public ModeHandler
135 {
136  public:
137         Channel_M() : ModeHandler('M', 0, 0, false, MODETYPE_CHANNEL, false) { }
138
139         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
140         {
141                 if (adding)
142                 {
143                         if (!channel->IsModeSet('M'))
144                         {
145                                 channel->SetMode('M',true);
146                                 return MODEACTION_ALLOW;
147                         }
148                 }
149                 else
150                 {
151                         if (channel->IsModeSet('M'))
152                         {
153                                 channel->SetMode('M',true);
154                                 return MODEACTION_ALLOW;
155                         }
156                 }
157
158                 return MODEACTION_DENY;
159         }
160 };
161
162 class ModuleServices : public Module
163 {
164         Server *Srv;
165         Channel_r* m1;
166         Channel_R* m2;
167         Channel_M* m3;
168         User_r* m4;
169         User_R* m5;
170  public:
171         ModuleServices(Server* Me)
172                 : Module::Module(Me)
173         {
174                 Srv = Me;
175                 m1 = new Channel_r(Me);
176                 m2 = new Channel_R();
177                 m3 = new Channel_M();
178                 m4 = new User_r(Me);
179                 m5 = new User_R();
180                 Srv->AddMode(m1, 'r');
181                 Srv->AddMode(m2, 'R');
182                 Srv->AddMode(m3, 'M');
183                 Srv->AddMode(m4, 'r');
184                 Srv->AddMode(m5, 'R');
185                 kludgeme = false;
186         }
187
188         virtual void On005Numeric(std::string &output)
189         {
190                 InsertMode(output, "rRM", 4);
191         }
192
193         /* <- :stitch.chatspike.net 307 w00t w00t :is a registered nick */
194         virtual void OnWhois(userrec* source, userrec* dest)
195         {
196                 if (dest->IsModeSet('r'))
197                 {
198                         /* user is registered */
199                         WriteServ(source->fd, "307 %s %s :is a registered nick", source->nick, dest->nick);
200                 }
201         }
202
203         void Implements(char* List)
204         {
205                 List[I_OnWhois] = List[I_OnUserPostNick] = List[I_OnUserPreMessage] = List[I_On005Numeric] = List[I_OnUserPreNotice] = List[I_OnUserPreJoin] = 1;
206         }
207
208         virtual void OnUserPostNick(userrec* user, const std::string &oldnick)
209         {
210                 /* On nickchange, if they have +r, remove it */
211                 if (user->IsModeSet('r'))
212                 {
213                         const char* modechange[2];
214                         modechange[0] = user->nick;
215                         modechange[1] = "-r";
216                         kludgeme = true;
217                         Srv->SendMode(modechange,2,user);
218                         kludgeme = false;
219                 }
220         }
221         
222         virtual int OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text, char status)
223         {
224                 if (target_type == TYPE_CHANNEL)
225                 {
226                         chanrec* c = (chanrec*)dest;
227                         if ((c->IsModeSet('M')) && (!user->IsModeSet('r')))
228                         {
229                                 if ((Srv->IsUlined(user->nick)) || (Srv->IsUlined(user->server)) || (!strcmp(user->server,"")))
230                                 {
231                                         // user is ulined, can speak regardless
232                                         return 0;
233                                 }
234                                 // user messaging a +M channel and is not registered
235                                 Srv->SendServ(user->fd,"477 "+std::string(user->nick)+" "+std::string(c->name)+" :You need a registered nickname to speak on this channel");
236                                 return 1;
237                         }
238                 }
239                 if (target_type == TYPE_USER)
240                 {
241                         userrec* u = (userrec*)dest;
242                         if ((u->IsModeSet('R')) && (user->IsModeSet('r')))
243                         {
244                                 if ((Srv->IsUlined(user->nick)) || (Srv->IsUlined(user->server)))
245                                 {
246                                         // user is ulined, can speak regardless
247                                         return 0;
248                                 }
249                                 // user messaging a +R user and is not registered
250                                 Srv->SendServ(user->fd,"477 "+std::string(user->nick)+" "+std::string(u->nick)+" :You need a registered nickname to message this user");
251                                 return 1;
252                         }
253                 }
254                 return 0;
255         }
256         
257         virtual int OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text, char status)
258         {
259                 return OnUserPreMessage(user,dest,target_type,text,status);
260         }
261         
262         virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname)
263         {
264                 if (chan)
265                 {
266                         if (chan->IsModeSet('R'))
267                         {
268                                 if (user->IsModeSet('r'))
269                                 {
270                                         if ((Srv->IsUlined(user->nick)) || (Srv->IsUlined(user->server)))
271                                         {
272                                                 // user is ulined, won't be stopped from joining
273                                                 return 0;
274                                         }
275                                         // joining a +R channel and not identified
276                                         Srv->SendServ(user->fd,"477 "+std::string(user->nick)+" "+std::string(chan->name)+" :You need a registered nickname to join this channel");
277                                         return 1;
278                                 }
279                         }
280                 }
281                 return 0;
282         }
283
284         virtual ~ModuleServices()
285         {
286                 DELETE(m1);
287                 DELETE(m2);
288                 DELETE(m3);
289                 DELETE(m4);
290                 DELETE(m5);
291         }
292         
293         virtual Version GetVersion()
294         {
295                 return Version(1,0,0,0,VF_STATIC|VF_VENDOR);
296         }
297 };
298
299
300 class ModuleServicesFactory : public ModuleFactory
301 {
302  public:
303         ModuleServicesFactory()
304         {
305         }
306         
307         ~ModuleServicesFactory()
308         {
309         }
310         
311         virtual Module * CreateModule(Server* Me)
312         {
313                 return new ModuleServices(Me);
314         }
315         
316 };
317
318
319 extern "C" void * init_module( void )
320 {
321         return new ModuleServicesFactory;
322 }
323