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