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