]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_messageflood.cpp
delete operator tracking in debug mode (using a macro -- live with it.)
[user/henk/code/inspircd.git] / src / modules / m_messageflood.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 <map>
21 #include "users.h"
22 #include "channels.h"
23 #include "modules.h"
24 #include "helperfuncs.h"
25
26 /* $ModDesc: Provides channel mode +f (message flood protection) */
27
28 class floodsettings
29 {
30  public:
31         bool ban;
32         int secs;
33         int lines;
34         time_t reset;
35         std::map<userrec*,int> counters;
36
37         floodsettings() : ban(0), secs(0), lines(0) {};
38         floodsettings(bool a, int b, int c) : ban(a), secs(b), lines(c)
39         {
40                 reset = time(NULL) + secs;
41                 log(DEBUG,"Create new floodsettings: %lu %lu",time(NULL),reset);
42         };
43
44         void addmessage(userrec* who)
45         {
46                 std::map<userrec*,int>::iterator iter = counters.find(who);
47                 if (iter != counters.end())
48                 {
49                         iter->second++;
50                         log(DEBUG,"Count for %s is now %d",who->nick,iter->second);
51                 }
52                 else
53                 {
54                         counters[who] = 1;
55                         log(DEBUG,"Count for %s is now *1*",who->nick);
56                 }
57                 if (time(NULL) > reset)
58                 {
59                         log(DEBUG,"floodsettings timer Resetting.");
60                         counters.clear();
61                         reset = time(NULL) + secs;
62                 }
63         }
64
65         bool shouldkick(userrec* who)
66         {
67                 std::map<userrec*,int>::iterator iter = counters.find(who);
68                 if (iter != counters.end())
69                 {
70                         log(DEBUG,"should kick? %d, %d",iter->second,this->lines);
71                         return (iter->second >= this->lines);
72                 }
73                 else return false;
74         }
75
76         void clear(userrec* who)
77         {
78                 std::map<userrec*,int>::iterator iter = counters.find(who);
79                 if (iter != counters.end())
80                 {
81                         counters.erase(iter);
82                 }
83         }
84 };
85
86 class ModuleMsgFlood : public Module
87 {
88         Server *Srv;
89         
90  public:
91  
92         ModuleMsgFlood(Server* Me)
93                 : Module::Module(Me)
94         {
95                 Srv = Me;
96                 Srv->AddExtendedMode('f',MT_CHANNEL,false,1,0);
97         }
98         
99         virtual int OnExtendedMode(userrec* user, void* target, char modechar, int type, bool mode_on, string_list &params)
100         {
101                 if ((modechar == 'f') && (type == MT_CHANNEL))
102                 {
103                         if (mode_on)
104                         {
105                                 std::string FloodParams = params[0];
106                                 chanrec* c = (chanrec*)target;
107                                 char ndata[MAXBUF];
108                                 char* data = ndata;
109                                 strlcpy(ndata,FloodParams.c_str(),MAXBUF);
110                                 char* lines = data;
111                                 char* secs = NULL;
112                                 bool ban = false;
113                                 if (*data == '*')
114                                 {
115                                         ban = true;
116                                         lines++;
117                                 }
118                                 else
119                                 {
120                                         ban = false;
121                                 }
122                                 while (*data)
123                                 {
124                                         if (*data == ':')
125                                         {
126                                                 *data = 0;
127                                                 data++;
128                                                 secs = data;
129                                                 break;
130                                         }
131                                         else data++;
132                                 }
133                                 if (secs)
134                                 {
135                                         /* Set up the flood parameters for this channel */
136                                         int nlines = atoi(lines);
137                                         int nsecs = atoi(secs);
138                                         if ((nlines<1) || (nsecs<1))
139                                         {
140                                                 WriteServ(user->fd,"608 %s %s :Invalid flood parameter",user->nick,c->name);
141                                                 return 0;
142                                         }
143                                         else
144                                         {
145                                                 if (!c->GetExt("flood"))
146                                                 {
147                                                         floodsettings *f = new floodsettings(ban,nsecs,nlines);
148                                                         c->Extend("flood",(char*)f);
149                                                 }
150                                         }
151                                         return 1;
152                                 }
153                                 else
154                                 {
155                                         WriteServ(user->fd,"608 %s %s :Invalid flood parameter",user->nick,c->name);
156                                         return 0;
157                                 }
158                                 
159                         }
160                         else
161                         {
162                                 chanrec* c = (chanrec*)target;
163                                 if (c->GetExt("flood"))
164                                 {
165                                         floodsettings *f = (floodsettings*)c->GetExt("flood");
166                                         DELETE(f);
167                                         c->Shrink("flood");
168                                 }
169                         }
170                         return 1;
171                 }
172                 return 0;
173         }
174
175         void ProcessMessages(userrec* user,chanrec* dest, const std::string &text)
176         {
177                 if (IS_LOCAL(user))
178                 {
179                         floodsettings *f = (floodsettings*)dest->GetExt("flood");
180                         if (f)
181                         {
182                                 f->addmessage(user);
183                                 if (f->shouldkick(user))
184                                 {
185                                         /* Youre outttta here! */
186                                         f->clear(user);
187                                         if (f->ban)
188                                         {
189                                                 char* parameters[3];
190                                                 parameters[0] = dest->name;
191                                                 parameters[1] = "+b";
192                                                 parameters[2] = user->MakeWildHost();
193                                                 Srv->SendMode(parameters,3,user);
194                                         }
195                                         Srv->KickUser(NULL, user, dest, "Channel flood triggered (mode +f)");
196                                 }
197                         }
198                 }
199         }
200
201         virtual void OnUserMessage(userrec* user, void* dest, int target_type, const std::string &text, char status)
202         {
203                 if (target_type == TYPE_CHANNEL)
204                 {
205                         ProcessMessages(user,(chanrec*)dest,text);
206                 }
207         }
208
209         virtual void OnUserNotice(userrec* user, void* dest, int target_type, const std::string &text, char status)
210         {
211                 if (target_type == TYPE_CHANNEL)
212                 {
213                         ProcessMessages(user,(chanrec*)dest,text);
214                 }
215         }
216
217         void OnChannelDelete(chanrec* chan)
218         {
219                 if (chan->GetExt("flood"))
220                 {
221                         floodsettings *f = (floodsettings*)chan->GetExt("flood");
222                         DELETE(f);
223                         chan->Shrink("flood");
224                 }
225         }
226
227         void Implements(char* List)
228         {
229                 List[I_On005Numeric] = List[I_OnExtendedMode] = List[I_OnChannelDelete] = List[I_OnUserNotice] = List[I_OnUserMessage] = 1;
230         }
231
232         virtual void On005Numeric(std::string &output)
233         {
234                 InsertMode(output, "f", 3);
235         }
236
237         virtual ~ModuleMsgFlood()
238         {
239         }
240         
241         virtual Version GetVersion()
242         {
243                 return Version(1,0,0,0,VF_STATIC|VF_VENDOR);
244         }
245 };
246
247
248 class ModuleMsgFloodFactory : public ModuleFactory
249 {
250  public:
251         ModuleMsgFloodFactory()
252         {
253         }
254         
255         ~ModuleMsgFloodFactory()
256         {
257         }
258         
259         virtual Module * CreateModule(Server* Me)
260         {
261                 return new ModuleMsgFlood(Me);
262         }
263         
264 };
265
266
267 extern "C" void * init_module( void )
268 {
269         return new ModuleMsgFloodFactory;
270 }
271