]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_rline.cpp
Header update: 2007 -> 2008
[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 <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 CoreException("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->Log(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 %d 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 char** parameters, int pcnt, User *user)
135         {
136
137                 if (pcnt >= 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, parameters[2], parameters[0]);
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, parameters[0]);
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, parameters[0],
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, parameters[0]);
174                                 }
175                         }
176                 }
177                 else
178                 {
179                         if (ServerInstance->XLines->DelLine(parameters[0], "R", user))
180                         {
181                                 ServerInstance->SNO->WriteToSnoMask('x',"%s Removed R-Line on %s.",user->nick,parameters[0]);
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,parameters[0]);
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  public:
200         ModuleRLine(InspIRCd* Me) : Module(Me)
201         {
202                 // Create a new command
203                 r = new CommandRLine(ServerInstance);
204                 ServerInstance->AddCommand(r);
205
206                 f = new RLineFactory(ServerInstance);
207                 ServerInstance->XLines->RegisterFactory(f);
208         }
209
210         virtual ~ModuleRLine()
211         {
212                 ServerInstance->XLines->UnregisterFactory(f);
213         }
214
215         virtual Version GetVersion()
216         {
217                 return Version(1,1,0,0,VF_COMMON|VF_VENDOR,API_VERSION);
218         }
219 };
220
221 MODULE_INIT(ModuleRLine)
222