Anope IRC Services  Version 2.0
xline.cpp
Go to the documentation of this file.
1 /* XLine functions.
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  */
12 
13 #include "services.h"
14 #include "modules.h"
15 #include "xline.h"
16 #include "users.h"
17 #include "sockets.h"
18 #include "regexpr.h"
19 #include "config.h"
20 #include "commands.h"
21 #include "servers.h"
22 
23 /* List of XLine managers we check users against in XLineManager::CheckAll */
24 std::list<XLineManager *> XLineManager::XLineManagers;
26 
28 {
29  if (this->mask.length() >= 2 && this->mask[0] == '/' && this->mask[this->mask.length() - 1] == '/' && !Config->GetBlock("options")->Get<const Anope::string>("regexengine").empty())
30  {
31  Anope::string stripped_mask = this->mask.substr(1, this->mask.length() - 2);
32 
33  ServiceReference<RegexProvider> provider("Regex", Config->GetBlock("options")->Get<const Anope::string>("regexengine"));
34  if (provider)
35  {
36  try
37  {
38  this->regex = provider->Compile(stripped_mask);
39  }
40  catch (const RegexException &ex)
41  {
42  Log(LOG_DEBUG) << ex.GetReason();
43  }
44  }
45  }
46 
47  size_t nick_t = this->mask.find('!');
48  if (nick_t != Anope::string::npos)
49  nick = this->mask.substr(0, nick_t);
50 
51  size_t user_t = this->mask.find('!'), host_t = this->mask.find('@');
52  if (host_t != Anope::string::npos)
53  {
54  if (user_t != Anope::string::npos && host_t > user_t)
55  user = this->mask.substr(user_t + 1, host_t - user_t - 1);
56  else
57  user = this->mask.substr(0, host_t);
58  }
59 
60  size_t real_t = this->mask.find('#');
61  if (host_t != Anope::string::npos)
62  {
63  if (real_t != Anope::string::npos && real_t > host_t)
64  host = this->mask.substr(host_t + 1, real_t - host_t - 1);
65  else
66  host = this->mask.substr(host_t + 1);
67  }
68  else
69  {
70  if (real_t != Anope::string::npos)
71  host = this->mask.substr(0, real_t);
72  else
73  host = this->mask;
74  }
75 
76  if (real_t != Anope::string::npos)
77  real = this->mask.substr(real_t + 1);
78 
79  if (host.find('/') != Anope::string::npos)
80  {
81  c = new cidr(host);
82  if (!c->valid())
83  {
84  delete c;
85  c = NULL;
86  }
87  }
88 }
89 
90 XLine::XLine(const Anope::string &ma, const Anope::string &r, const Anope::string &uid) : Serializable("XLine"), mask(ma), by(Me->GetName()), created(0), expires(0), reason(r), id(uid)
91 {
92  regex = NULL;
93  manager = NULL;
94  c = NULL;
95 
96  this->Init();
97 }
98 
99 XLine::XLine(const Anope::string &ma, const Anope::string &b, const time_t ex, const Anope::string &r, const Anope::string &uid) : Serializable("XLine"), mask(ma), by(b), created(Anope::CurTime), expires(ex), reason(r), id(uid)
100 {
101  regex = NULL;
102  manager = NULL;
103  c = NULL;
104 
105  this->Init();
106 }
107 
109 {
110  delete regex;
111  delete c;
112 }
113 
115 {
116  return nick;
117 }
118 
120 {
121  return user;
122 }
123 
125 {
126  return host;
127 }
128 
130 {
131  return real;
132 }
133 
135 {
136  Anope::string r = this->reason;
137  if (!this->id.empty())
138  r += " (ID: " + this->id + ")";
139  return r;
140 }
141 
143 {
144  return !this->GetNick().empty() || !this->GetReal().empty();
145 }
146 
147 bool XLine::IsRegex() const
148 {
149  return !this->mask.empty() && this->mask[0] == '/' && this->mask[this->mask.length() - 1] == '/';
150 }
151 
153 {
154  data["mask"] << this->mask;
155  data["by"] << this->by;
156  data["created"] << this->created;
157  data["expires"] << this->expires;
158  data["reason"] << this->reason;
159  data["uid"] << this->id;
160  if (this->manager)
161  data["manager"] << this->manager->name;
162 }
163 
165 {
166  Anope::string smanager;
167 
168  data["manager"] >> smanager;
169 
170  ServiceReference<XLineManager> xlm("XLineManager", smanager);
171  if (!xlm)
172  return NULL;
173 
174  XLine *xl;
175  if (obj)
176  {
177  xl = anope_dynamic_static_cast<XLine *>(obj);
178  data["mask"] >> xl->mask;
179  data["by"] >> xl->by;
180  data["reason"] >> xl->reason;
181  data["uid"] >> xl->id;
182 
183  if (xlm != xl->manager)
184  {
185  xl->manager->DelXLine(xl);
186  xlm->AddXLine(xl);
187  }
188  }
189  else
190  {
191  Anope::string smask, sby, sreason, suid;
192  time_t expires;
193 
194  data["mask"] >> smask;
195  data["by"] >> sby;
196  data["reason"] >> sreason;
197  data["uid"] >> suid;
198  data["expires"] >> expires;
199 
200  xl = new XLine(smask, sby, expires, sreason, suid);
201  xlm->AddXLine(xl);
202  }
203 
204  data["created"] >> xl->created;
205  xl->manager = xlm;
206 
207  return xl;
208 }
209 
211 {
212  XLineManagers.push_back(xlm);
213 }
214 
216 {
217  std::list<XLineManager *>::iterator it = std::find(XLineManagers.begin(), XLineManagers.end(), xlm);
218 
219  if (it != XLineManagers.end())
220  XLineManagers.erase(it);
221 }
222 
224 {
225  for (std::list<XLineManager *>::iterator it = XLineManagers.begin(), it_end = XLineManagers.end(); it != it_end; ++it)
226  {
227  XLineManager *xlm = *it;
228 
229  if (xlm->CheckAllXLines(u))
230  break;
231  }
232 }
233 
235 {
236  Anope::string id;
237  int count = 0;
238  do
239  {
240  id.clear();
241 
242  if (++count > 10)
243  {
244  Log(LOG_DEBUG) << "Unable to generate XLine UID";
245  break;
246  }
247 
248  for (int i = 0; i < 10; ++i)
249  {
250  char c;
251  do
252  c = (rand() % 75) + 48;
253  while (!isupper(c) && !isdigit(c));
254  id += c;
255  }
256  }
257  while (XLinesByUID->count(id) > 0);
258 
259  return id;
260 }
261 
262 XLineManager::XLineManager(Module *creator, const Anope::string &xname, char t) : Service(creator, "XLineManager", xname), type(t), xlines("XLine")
263 {
264 }
265 
267 {
268  this->Clear();
269 }
270 
271 const char &XLineManager::Type()
272 {
273  return this->type;
274 }
275 
277 {
278  return this->xlines->size();
279 }
280 
281 const std::vector<XLine *> &XLineManager::GetList() const
282 {
283  return this->xlines;
284 }
285 
287 {
288  if (!x->id.empty())
289  XLinesByUID->insert(std::make_pair(x->id, x));
290  this->xlines->push_back(x);
291  x->manager = this;
292 }
293 
295 {
296  std::vector<XLine *>::iterator it = std::find(this->xlines->begin(), this->xlines->end(), x);
297 
298  if (!x->id.empty())
299  {
300  std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->find(x->id), it3 = XLinesByUID->upper_bound(x->id);
301  for (; it2 != XLinesByUID->end() && it2 != it3; ++it2)
302  if (it2->second == x)
303  {
304  XLinesByUID->erase(it2);
305  break;
306  }
307  }
308 
309  if (it != this->xlines->end())
310  {
311  this->SendDel(x);
312 
313  delete x;
314  this->xlines->erase(it);
315 
316  return true;
317  }
318 
319  return false;
320 }
321 
323 {
324  if (index >= this->xlines->size())
325  return NULL;
326 
327  XLine *x = this->xlines->at(index);
328  x->QueueUpdate();
329  return x;
330 }
331 
333 {
334  for (unsigned i = 0; i < this->xlines->size(); ++i)
335  {
336  XLine *x = this->xlines->at(i);
337  if (!x->id.empty())
338  XLinesByUID->erase(x->id);
339  delete x;
340  }
341  this->xlines->clear();
342 }
343 
344 bool XLineManager::CanAdd(CommandSource &source, const Anope::string &mask, time_t expires, const Anope::string &reason)
345 {
346  for (unsigned i = this->GetCount(); i > 0; --i)
347  {
348  XLine *x = this->GetEntry(i - 1);
349 
350  if (x->mask.equals_ci(mask))
351  {
352  if (!x->expires || x->expires >= expires)
353  {
354  if (x->reason != reason)
355  {
356  x->reason = reason;
357  source.Reply(_("Reason for %s updated."), x->mask.c_str());
358  }
359  else
360  source.Reply(_("%s already exists."), mask.c_str());
361  }
362  else
363  {
364  x->expires = expires;
365  if (x->reason != reason)
366  {
367  x->reason = reason;
368  source.Reply(_("Expiry and reason updated for %s."), x->mask.c_str());
369  }
370  else
371  source.Reply(_("Expiry for %s updated."), x->mask.c_str());
372  }
373 
374  return false;
375  }
376  else if (Anope::Match(mask, x->mask) && (!x->expires || x->expires >= expires))
377  {
378  source.Reply(_("%s is already covered by %s."), mask.c_str(), x->mask.c_str());
379  return false;
380  }
381  else if (Anope::Match(x->mask, mask) && (!expires || x->expires <= expires))
382  {
383  source.Reply(_("Removing %s because %s covers it."), x->mask.c_str(), mask.c_str());
384  this->DelXLine(x);
385  }
386  }
387 
388  return true;
389 }
390 
392 {
393  std::multimap<Anope::string, XLine *, ci::less>::iterator it = XLinesByUID->find(mask);
394  if (it != XLinesByUID->end())
395  for (std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->upper_bound(mask); it != it2; ++it)
396  if (it->second->manager == NULL || it->second->manager == this)
397  {
398  it->second->QueueUpdate();
399  return it->second;
400  }
401  for (unsigned i = 0, end = this->xlines->size(); i < end; ++i)
402  {
403  XLine *x = this->xlines->at(i);
404 
405  if (x->mask.equals_ci(mask))
406  {
407  x->QueueUpdate();
408  return x;
409  }
410  }
411 
412  return NULL;
413 }
414 
416 {
417  for (unsigned i = this->xlines->size(); i > 0; --i)
418  {
419  XLine *x = this->xlines->at(i - 1);
420 
421  if (x->expires && x->expires < Anope::CurTime)
422  {
423  this->OnExpire(x);
424  this->DelXLine(x);
425  continue;
426  }
427 
428  if (this->Check(u, x))
429  {
430  this->OnMatch(u, x);
431  return x;
432  }
433  }
434 
435  return NULL;
436 }
437 
439 {
440 }
441 
static void UnregisterXLineManager(XLineManager *xlm)
Definition: xline.cpp:215
Anope::string GetReason() const
Definition: xline.cpp:134
cidr * c
Definition: xline.h:23
const char & Type()
Definition: xline.cpp:271
Anope::string reason
Definition: xline.h:29
bool IsRegex() const
Definition: xline.cpp:147
Anope::string mask
Definition: xline.h:24
XLineManager * manager
Definition: xline.h:30
void clear()
Definition: anope.h:187
static void CheckAll(User *u)
Definition: xline.cpp:223
Anope::string real
Definition: xline.h:21
Anope::string nick
Definition: xline.h:21
virtual ~XLineManager()
Definition: xline.cpp:266
char type
Definition: xline.h:55
void Clear()
Definition: xline.cpp:332
~XLine()
Definition: xline.cpp:108
void QueueUpdate()
Definition: serialize.cpp:83
Definition: users.h:34
void Init()
Definition: xline.cpp:27
XLine * GetEntry(unsigned index)
Definition: xline.cpp:322
bool equals_ci(const char *_str) const
Definition: anope.h:78
const Anope::string & GetUser() const
Definition: xline.cpp:119
Definition: sockets.h:87
CoreExport time_t CurTime
Definition: main.cpp:41
const Anope::string & GetNick() const
Definition: xline.cpp:114
string substr(size_type pos=0, size_type n=npos) const
Definition: anope.h:277
size_t GetCount() const
Definition: xline.cpp:276
virtual void OnExpire(const XLine *x)
Definition: xline.cpp:438
const Anope::string & GetReal() const
Definition: xline.cpp:129
size_type length() const
Definition: anope.h:131
Definition: Config.cs:26
CoreExport bool Match(const string &str, const string &mask, bool case_sensitive=false, bool use_regex=false)
Definition: misc.cpp:407
static const size_type npos
Definition: anope.h:44
void Reply(const char *message,...)
Definition: command.cpp:96
Regex * regex
Definition: xline.h:25
XLine(const Anope::string &mask, const Anope::string &reason="", const Anope::string &uid="")
Definition: xline.cpp:90
const std::vector< XLine * > & GetList() const
Definition: xline.cpp:281
bool DelXLine(XLine *x)
Definition: xline.cpp:294
Anope::string user
Definition: xline.h:21
Anope::string by
Definition: xline.h:26
time_t expires
Definition: xline.h:28
virtual bool Check(User *u, const XLine *x)=0
bool empty() const
Definition: anope.h:126
Anope::string id
Definition: xline.h:31
bool valid() const
Definition: sockets.cpp:317
virtual Regex * Compile(const Anope::string &)=0
Anope::string host
Definition: xline.h:21
static std::list< XLineManager * > XLineManagers
Definition: xline.h:62
static Serializable * Unserialize(Serializable *obj, Serialize::Data &data)
Definition: xline.cpp:164
Anope::string name
Definition: service.h:88
Serialize::Checker< std::vector< XLine * > > xlines
Definition: xline.h:57
XLine * HasEntry(const Anope::string &mask)
Definition: xline.cpp:391
XLineManager(Module *creator, const Anope::string &name, char t)
Definition: xline.cpp:262
Definition: xline.h:18
T anope_dynamic_static_cast(O ptr)
Definition: anope.h:774
virtual void SendDel(XLine *x)=0
CoreExport Server * Me
Definition: servers.cpp:24
virtual const Anope::string & GetReason() const
Definition: anope.h:672
const char * c_str() const
Definition: anope.h:117
Definition: logger.h:53
void Serialize(Serialize::Data &data) const anope_override
Definition: xline.cpp:152
void AddXLine(XLine *x)
Definition: xline.cpp:286
static Anope::string GenerateUID()
Definition: xline.cpp:234
bool CanAdd(CommandSource &source, const Anope::string &mask, time_t expires, const Anope::string &reason)
Definition: xline.cpp:344
time_t created
Definition: xline.h:27
size_type find(const string &_str, size_type pos=0) const
Definition: anope.h:192
const Anope::string & GetHost() const
Definition: xline.cpp:124
XLine * CheckAllXLines(User *u)
Definition: xline.cpp:415
#define _(x)
Definition: services.h:50
static Serialize::Checker< std::multimap< Anope::string, XLine *, ci::less > > XLinesByUID
Definition: xline.h:59
virtual void OnMatch(User *u, XLine *x)=0
bool HasNickOrReal() const
Definition: xline.cpp:142
Definition: anope.h:20
static void RegisterXLineManager(XLineManager *xlm)
Definition: xline.cpp:210