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