]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/extra/m_rline.cpp
fixed some indentation and spacing in modules
[user/henk/code/inspircd.git] / src / modules / extra / 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 <pcre.h>
16 #include "xline.h"
17
18 /* $ModDesc: RLINE: Regexp user banning. */
19 /* $CompileFlags: exec("pcre-config --cflags") */
20 /* $LinkerFlags: exec("pcre-config --libs") rpath("pcre-config --libs") -lpcre */
21
22 #ifdef WINDOWS
23 #pragma comment(lib, "pcre.lib")
24 #endif
25
26 class CoreExport RLine : public XLine
27 {
28  public:
29
30         /** Create a R-Line.
31          * @param s_time The set time
32          * @param d The duration of the xline
33          * @param src The sender of the xline
34          * @param re The reason of the xline
35          * @param regex Pattern to match with
36          * @
37          */
38         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")
39         {
40                 const char *error;
41                 int erroffset;
42
43                 matchtext = regexs;
44
45                 regex = pcre_compile(regexs, 0, &error, &erroffset, NULL);
46
47                 if (!regex)
48                 {
49                         ServerInstance->SNO->WriteToSnoMask('x',"Error in regular expression: %s at offset %d: %s\n", regexs, erroffset, error);
50                         throw ModuleException("Bad regex pattern.");
51                 }
52         }
53
54         /** Destructor
55          */
56         ~RLine()
57         {
58                 pcre_free(regex);
59         }
60
61         bool Matches(User *u)
62         {
63                 std::string compare = std::string(u->nick) + "!" + u->ident + "@" + u->host + " " + u->fullname;
64
65                 ServerInstance->Logs->Log("m_rline",DEBUG, "Matching " + matchtext + " against string " + compare);
66
67                 if (pcre_exec(regex, NULL, compare.c_str(), compare.length(), 0, 0, NULL, 0) > -1)
68                 {
69                         // Bang. :D
70                         return true;
71                 }
72
73                 return false;
74         }
75
76         bool Matches(const std::string &compare)
77         {
78                 if (pcre_exec(regex, NULL, compare.c_str(), compare.length(), 0, 0, NULL, 0) > -1)
79                 {
80                         // Bang. :D
81                         return true;
82                 }
83
84                 return false;
85         }
86
87         void Apply(User* u)
88         {
89                 DefaultApply(u, "R", true);
90         }
91
92         void DisplayExpiry()
93         {
94                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed R-Line %s (set by %s %ld seconds ago)", this->matchtext.c_str(), this->source, this->duration);
95         }
96
97         const char* Displayable()
98         {
99                 return matchtext.c_str();
100         }
101
102         std::string matchtext;
103
104         pcre *regex;
105 };
106
107
108 /** An XLineFactory specialized to generate RLine* pointers
109  */
110 class CoreExport RLineFactory : public XLineFactory
111 {
112  public:
113         RLineFactory(InspIRCd* Instance) : XLineFactory(Instance, "R") { }
114
115         /** Generate a RLine
116          */
117         XLine* Generate(time_t set_time, long duration, const char* source, const char* reason, const char* xline_specific_mask)
118         {
119                 return new RLine(ServerInstance, set_time, duration, source, reason, xline_specific_mask);
120         }
121 };
122
123 /** Handle /RLINE
124  * Syntax is same as other lines: RLINE regex_goes_here 1d :reason
125  */
126 class CommandRLine : public Command
127 {
128  public:
129         CommandRLine (InspIRCd* Instance) : Command(Instance,"RLINE", "o", 1)
130         {
131                 this->source = "m_rline.so";
132         }
133
134         CmdResult Handle (const std::vector<std::string>& parameters, User *user)
135         {
136
137                 if (parameters.size() >= 3)
138                 {
139                         // Adding - XXX todo make this respect <insane> tag perhaps..
140
141                         long duration = ServerInstance->Duration(parameters[1]);
142                         RLine *r = NULL;
143
144                         try
145                         {
146                                 r = new RLine(ServerInstance, ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str());
147                         }
148                         catch (...)
149                         {
150                                 ; // Do nothing. If we get here, the regex was fucked up, and they already got told it fucked up.
151                         }
152
153                         if (r)
154                         {
155                                 if (ServerInstance->XLines->AddLine(r, user))
156                                 {
157                                         if (!duration)
158                                         {
159                                                 ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent R-Line for %s.", user->nick.c_str(), parameters[0].c_str());
160                                         }
161                                         else
162                                         {
163                                                 time_t c_requires_crap = duration + ServerInstance->Time();
164                                                 ServerInstance->SNO->WriteToSnoMask('x', "%s added timed R-Line for %s, expires on %s", user->nick.c_str(), parameters[0].c_str(),
165                                                                 ServerInstance->TimeString(c_requires_crap).c_str());
166                                         }
167
168                                         ServerInstance->XLines->ApplyLines();
169                                 }
170                                 else
171                                 {
172                                         delete r;
173                                         user->WriteServ("NOTICE %s :*** R-Line for %s already exists", user->nick.c_str(), parameters[0].c_str());
174                                 }
175                         }
176                 }
177                 else
178                 {
179                         if (ServerInstance->XLines->DelLine(parameters[0].c_str(), "R", user))
180                         {
181                                 ServerInstance->SNO->WriteToSnoMask('x',"%s Removed R-Line on %s.",user->nick.c_str(),parameters[0].c_str());
182                         }
183                         else
184                         {
185                                 // XXX todo implement stats
186                                 user->WriteServ("NOTICE %s :*** R-Line %s not found in list, try /stats g.",user->nick.c_str(),parameters[0].c_str());
187                         }
188                 }
189
190                 return CMD_SUCCESS;
191         }
192 };
193
194 class ModuleRLine : public Module
195 {
196  private:
197         CommandRLine *r;
198         RLineFactory *f;
199         bool MatchOnNickChange;
200
201  public:
202         ModuleRLine(InspIRCd* Me) : Module(Me)
203         {
204                 OnRehash(NULL, "");
205
206                 // Create a new command
207                 r = new CommandRLine(ServerInstance);
208                 ServerInstance->AddCommand(r);
209
210                 f = new RLineFactory(ServerInstance);
211                 ServerInstance->XLines->RegisterFactory(f);
212
213                 Implementation eventlist[] = { I_OnUserConnect, I_OnRehash, I_OnUserPostNick };
214                 ServerInstance->Modules->Attach(eventlist, this, 3);
215
216         }
217
218         virtual ~ModuleRLine()
219         {
220                 ServerInstance->XLines->UnregisterFactory(f);
221         }
222
223         virtual Version GetVersion()
224         {
225                 return Version(1,2,0,0,VF_COMMON|VF_VENDOR,API_VERSION);
226         }
227
228         virtual void OnUserConnect(User* user)
229         {
230                 // Apply lines on user connect
231                 XLine *rl = ServerInstance->XLines->MatchesLine("R", user);
232
233                 if (rl)
234                 {
235                         // Bang. :P
236                         rl->Apply(user);
237                 }
238         }
239
240         virtual void OnRehash(User *user, const std::string &parameter)
241         {
242                 ConfigReader Conf(ServerInstance);
243
244                 MatchOnNickChange = Conf.ReadFlag("rline", "matchonnickchange", 1);
245         }
246
247         virtual void OnUserPostNick(User *user, const std::string &oldnick)
248         {
249                 if (!IS_LOCAL(user))
250                         return;
251
252                 if (!MatchOnNickChange)
253                         return;
254
255                 XLine *rl = ServerInstance->XLines->MatchesLine("R", user);
256
257                 if (rl)
258                 {
259                         // Bang! :D
260                         rl->Apply(user);
261                 }
262         }
263
264 };
265
266 MODULE_INIT(ModuleRLine)
267