]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_rline.cpp
7ea9d36b40739c7a86b4ee834c6874a4fbc5ba39
[user/henk/code/inspircd.git] / src / modules / m_rline.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2008 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 "inspircd.h"
15 #include "m_regex.h"
16 #include "xline.h"
17
18 static Module* rxengine = 0;
19 static Module* mymodule = 0; /* Needed to let RLine send request! */
20
21 /* $ModDesc: RLINE: Regexp user banning. */
22
23 class CoreExport RLine : public XLine
24 {
25  public:
26
27         /** Create a R-Line.
28          * @param s_time The set time
29          * @param d The duration of the xline
30          * @param src The sender of the xline
31          * @param re The reason of the xline
32          * @param regex Pattern to match with
33          * @
34          */
35         RLine(InspIRCd* Instance, time_t s_time, long d, const char* src, const char* re, const char* regexs) : XLine(Instance, s_time, d, src, re, "R")
36         {
37                 matchtext = regexs;
38
39                 if (!rxengine)
40                 {
41                         ServerInstance->SNO->WriteToSnoMask('x', "Cannot create regexes until engine is set to a loaded provider!");
42                         throw ModuleException("Regex engine not set or loaded!");
43                 }
44
45                 try
46                 {
47                         regex = RegexFactoryRequest(mymodule, rxengine, regexs).Create();
48                 }
49                 catch (ModuleException& ex)
50                 {
51                         ServerInstance->SNO->WriteToSnoMask('x', "Bad regex: %s", ex.GetReason());
52                         throw;
53                 }
54         }
55
56         /** Destructor
57          */
58         ~RLine()
59         {
60                 delete regex;
61         }
62
63         bool Matches(User *u)
64         {
65                 std::string compare = std::string(u->nick) + "!" + u->ident + "@" + u->host + " " + u->fullname;
66
67                 ServerInstance->Logs->Log("m_rline",DEBUG, "Matching " + matchtext + " against string " + compare);
68
69                 if (regex->Matches(compare))
70                 {
71                         // Bang. :D
72                         return true;
73                 }
74
75                 return false;
76         }
77
78         bool Matches(const std::string &compare)
79         {
80                 if (regex->Matches(compare))
81                 {
82                         // Bang. :D
83                         return true;
84                 }
85
86                 return false;
87         }
88
89         void Apply(User* u)
90         {
91                 DefaultApply(u, "R", true);
92         }
93
94         void DisplayExpiry()
95         {
96                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed R-Line %s (set by %s %ld seconds ago)", this->matchtext.c_str(), this->source, this->duration);
97         }
98
99         const char* Displayable()
100         {
101                 return matchtext.c_str();
102         }
103
104         std::string matchtext;
105
106         Regex *regex;
107 };
108
109
110 /** An XLineFactory specialized to generate RLine* pointers
111  */
112 class CoreExport RLineFactory : public XLineFactory
113 {
114  public:
115         RLineFactory(InspIRCd* Instance) : XLineFactory(Instance, "R") { }
116
117         /** Generate a RLine
118          */
119         XLine* Generate(time_t set_time, long duration, const char* source, const char* reason, const char* xline_specific_mask)
120         {
121                 return new RLine(ServerInstance, set_time, duration, source, reason, xline_specific_mask);
122         }
123 };
124
125 /** Handle /RLINE
126  * Syntax is same as other lines: RLINE regex_goes_here 1d :reason
127  */
128 class CommandRLine : public Command
129 {
130         std::string rxengine;
131
132  public:
133         CommandRLine (InspIRCd* Instance) : Command(Instance,"RLINE", "o", 1)
134         {
135                 this->source = "m_rline.so";
136         }
137
138         CmdResult Handle (const std::vector<std::string>& parameters, User *user)
139         {
140
141                 if (parameters.size() >= 3)
142                 {
143                         // Adding - XXX todo make this respect <insane> tag perhaps..
144
145                         long duration = ServerInstance->Duration(parameters[1]);
146                         RLine *r = NULL;
147
148                         try
149                         {
150                                 r = new RLine(ServerInstance, ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str());
151                         }
152                         catch (...)
153                         {
154                                 ; // Do nothing. If we get here, the regex was fucked up, and they already got told it fucked up.
155                         }
156
157                         if (r)
158                         {
159                                 if (ServerInstance->XLines->AddLine(r, user))
160                                 {
161                                         if (!duration)
162                                         {
163                                                 ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent R-Line for %s.", user->nick.c_str(), parameters[0].c_str());
164                                         }
165                                         else
166                                         {
167                                                 time_t c_requires_crap = duration + ServerInstance->Time();
168                                                 ServerInstance->SNO->WriteToSnoMask('x', "%s added timed R-Line for %s, expires on %s", user->nick.c_str(), parameters[0].c_str(),
169                                                                 ServerInstance->TimeString(c_requires_crap).c_str());
170                                         }
171
172                                         ServerInstance->XLines->ApplyLines();
173                                 }
174                                 else
175                                 {
176                                         delete r;
177                                         user->WriteServ("NOTICE %s :*** R-Line for %s already exists", user->nick.c_str(), parameters[0].c_str());
178                                 }
179                         }
180                 }
181                 else
182                 {
183                         if (ServerInstance->XLines->DelLine(parameters[0].c_str(), "R", user))
184                         {
185                                 ServerInstance->SNO->WriteToSnoMask('x',"%s Removed R-Line on %s.",user->nick.c_str(),parameters[0].c_str());
186                         }
187                         else
188                         {
189                                 // XXX todo implement stats
190                                 user->WriteServ("NOTICE %s :*** R-Line %s not found in list, try /stats g.",user->nick.c_str(),parameters[0].c_str());
191                         }
192                 }
193
194                 return CMD_SUCCESS;
195         }
196 };
197
198 class ModuleRLine : public Module
199 {
200  private:
201         CommandRLine *r;
202         RLineFactory *f;
203         bool MatchOnNickChange;
204         std::string RegexEngine;
205
206  public:
207         ModuleRLine(InspIRCd* Me) : Module(Me)
208         {
209                 mymodule = this;
210                 OnRehash(NULL, "");
211
212                 Me->Modules->UseInterface("RegularExpression");
213
214                 // Create a new command
215                 r = new CommandRLine(ServerInstance);
216                 ServerInstance->AddCommand(r);
217
218                 f = new RLineFactory(ServerInstance);
219                 ServerInstance->XLines->RegisterFactory(f);
220
221                 Implementation eventlist[] = { I_OnUserConnect, I_OnRehash, I_OnUserPostNick, I_OnLoadModule };
222                 ServerInstance->Modules->Attach(eventlist, this, 3);
223
224         }
225
226         virtual ~ModuleRLine()
227         {
228                 ServerInstance->Modules->DoneWithInterface("RegularExpression");
229                 ServerInstance->XLines->DelAll("R");
230                 ServerInstance->XLines->UnregisterFactory(f);
231         }
232
233         virtual Version GetVersion()
234         {
235                 return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION);
236         }
237
238         virtual void OnUserConnect(User* user)
239         {
240                 // Apply lines on user connect
241                 XLine *rl = ServerInstance->XLines->MatchesLine("R", user);
242
243                 if (rl)
244                 {
245                         // Bang. :P
246                         rl->Apply(user);
247                 }
248         }
249
250         virtual void OnRehash(User *user, const std::string &parameter)
251         {
252                 ConfigReader Conf(ServerInstance);
253
254                 MatchOnNickChange = Conf.ReadFlag("rline", "matchonnickchange", 0);
255
256                 std::string newrxengine;
257
258                 newrxengine = Conf.ReadValue("rline", "engine", 0);
259
260                 if (!RegexEngine.empty())
261                 {
262                         if (RegexEngine == newrxengine)
263                                 return;
264                         ServerInstance->SNO->WriteToSnoMask('x', "Dumping all R-Lines due to regex engine change (was '%s', now '%s')", RegexEngine.c_str(), newrxengine.c_str());
265                         ServerInstance->XLines->DelAll("R");
266                 }
267                 rxengine = 0;
268                 RegexEngine = newrxengine;
269                 modulelist* ml = ServerInstance->Modules->FindInterface("RegularExpression");
270                 if (ml)
271                 {
272                         for (modulelist::iterator i = ml->begin(); i != ml->end(); ++i)
273                         {
274                                 std::string rxname = RegexNameRequest(this, *i).Send();
275                                 if (rxname == newrxengine)
276                                 {
277                                         ServerInstance->SNO->WriteToSnoMask('x', "R-Line now using engine '%s'", RegexEngine.c_str());
278                                         rxengine = *i;
279                                 }
280                         }
281                 }
282                 if (!rxengine)
283                 {
284                         ServerInstance->SNO->WriteToSnoMask('x', "WARNING: Regex engine '%s' is not loaded - R-Line functionality disabled until this is corrected.", RegexEngine.c_str());
285                 }
286         }
287
288         virtual void OnLoadModule(Module* mod, const std::string& name)
289         {
290                 if (ServerInstance->Modules->ModuleHasInterface(mod, "RegularExpression"))
291                 {
292                         std::string rxname = RegexNameRequest(this, mod).Send();
293                         if (rxname == RegexEngine)
294                         {
295                                 ServerInstance->SNO->WriteToSnoMask('x', "R-Line now using engine '%s'", RegexEngine.c_str());
296                                 rxengine = mod;
297                         }
298                 }
299         }
300
301         virtual void OnUserPostNick(User *user, const std::string &oldnick)
302         {
303                 if (!IS_LOCAL(user))
304                         return;
305
306                 if (!MatchOnNickChange)
307                         return;
308
309                 XLine *rl = ServerInstance->XLines->MatchesLine("R", user);
310
311                 if (rl)
312                 {
313                         // Bang! :D
314                         rl->Apply(user);
315                 }
316         }
317
318 };
319
320 MODULE_INIT(ModuleRLine)
321