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