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