Anope IRC Services  Version 2.0
os_sxline.cpp
Go to the documentation of this file.
1 /* OperServ core 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 #include "module.h"
13 
15 {
19  unsigned deleted;
20  public:
21  SXLineDelCallback(XLineManager *x, Command *c, CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, true), xlm(x), command(c), source(_source), deleted(0)
22  {
23  }
24 
26  {
27  if (!deleted)
28  source.Reply(_("No matching entries on the %s list."), source.command.c_str());
29  else if (deleted == 1)
30  source.Reply(_("Deleted 1 entry from the %s list."), source.command.c_str());
31  else
32  source.Reply(_("Deleted %d entries from the %s list."), deleted, source.command.c_str());
33  }
34 
35  void HandleNumber(unsigned number) anope_override
36  {
37  if (!number)
38  return;
39 
40  XLine *x = this->xlm->GetEntry(number - 1);
41 
42  if (!x)
43  return;
44 
45  Log(LOG_ADMIN, source, command) << "to remove " << x->mask << " from the list";
46 
47  ++deleted;
48  DoDel(this->xlm, source, x);
49  }
50 
51  static void DoDel(XLineManager *xlm, CommandSource &source, XLine *x)
52  {
53  xlm->DelXLine(x);
54  }
55 };
56 
58 {
59  private:
60  virtual XLineManager* xlm() = 0;
61 
62  virtual void OnAdd(CommandSource &source, const std::vector<Anope::string> &params) = 0;
63 
64  void OnDel(CommandSource &source, const std::vector<Anope::string> &params)
65  {
66 
67  if (!this->xlm() || this->xlm()->GetList().empty())
68  {
69  source.Reply(_("%s list is empty."), source.command.c_str());
70  return;
71  }
72 
73  const Anope::string &mask = params.size() > 1 ? params[1] : "";
74 
75  if (mask.empty())
76  {
77  this->OnSyntaxError(source, "DEL");
78  return;
79  }
80 
81  if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
82  {
83  SXLineDelCallback list(this->xlm(), this, source, mask);
84  list.Process();
85  }
86  else
87  {
88  XLine *x = this->xlm()->HasEntry(mask);
89 
90  if (!x)
91  {
92  source.Reply(_("\002%s\002 not found on the %s list."), mask.c_str(), source.command.c_str());
93  return;
94  }
95 
96  FOREACH_MOD(OnDelXLine, (source, x, this->xlm()));
97 
98  SXLineDelCallback::DoDel(this->xlm(), source, x);
99  source.Reply(_("\002%s\002 deleted from the %s list."), mask.c_str(), source.command.c_str());
100  Log(LOG_ADMIN, source, this) << "to remove " << mask << " from the list";
101  }
102 
103  if (Anope::ReadOnly)
104  source.Reply(READ_ONLY_MODE);
105 
106  return;
107  }
108 
109  void ProcessList(CommandSource &source, const std::vector<Anope::string> &params, ListFormatter &list)
110  {
111  if (!this->xlm() || this->xlm()->GetList().empty())
112  {
113  source.Reply(_("%s list is empty."), source.command.c_str());
114  return;
115  }
116 
117  const Anope::string &mask = params.size() > 1 ? params[1] : "";
118 
119  if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
120  {
121  class SXLineListCallback : public NumberList
122  {
123  XLineManager *xlm;
124  CommandSource &source;
125  ListFormatter &list;
126  public:
127  SXLineListCallback(XLineManager *x, CommandSource &_source, ListFormatter &_list, const Anope::string &numlist) : NumberList(numlist, false), xlm(x), source(_source), list(_list)
128  {
129  }
130 
131  void HandleNumber(unsigned number) anope_override
132  {
133  if (!number)
134  return;
135 
136  const XLine *x = this->xlm->GetEntry(number - 1);
137 
138  if (!x)
139  return;
140 
142  entry["Number"] = stringify(number);
143  entry["Mask"] = x->mask;
144  entry["By"] = x->by;
145  entry["Created"] = Anope::strftime(x->created, NULL, true);
146  entry["Expires"] = Anope::Expires(x->expires, source.nc);
147  entry["Reason"] = x->reason;
148  list.AddEntry(entry);
149  }
150  }
151  sl_list(this->xlm(), source, list, mask);
152  sl_list.Process();
153  }
154  else
155  {
156  for (unsigned i = 0, end = this->xlm()->GetCount(); i < end; ++i)
157  {
158  const XLine *x = this->xlm()->GetEntry(i);
159 
160  if (mask.empty() || mask.equals_ci(x->mask) || mask == x->id || Anope::Match(x->mask, mask, false, true))
161  {
163  entry["Number"] = stringify(i + 1);
164  entry["Mask"] = x->mask;
165  entry["By"] = x->by;
166  entry["Created"] = Anope::strftime(x->created, NULL, true);
167  entry["Expires"] = Anope::Expires(x->expires, source.nc);
168  entry["Reason"] = x->reason;
169  list.AddEntry(entry);
170  }
171  }
172  }
173 
174  if (list.IsEmpty())
175  source.Reply(_("No matching entries on the %s list."), source.command.c_str());
176  else
177  {
178  source.Reply(_("Current %s list:"), source.command.c_str());
179 
180  std::vector<Anope::string> replies;
181  list.Process(replies);
182 
183  for (unsigned i = 0; i < replies.size(); ++i)
184  source.Reply(replies[i]);
185  }
186  }
187 
188  void OnList(CommandSource &source, const std::vector<Anope::string> &params)
189  {
190  ListFormatter list(source.GetAccount());
191  list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Reason"));
192 
193  this->ProcessList(source, params, list);
194  }
195 
196  void OnView(CommandSource &source, const std::vector<Anope::string> &params)
197  {
198  ListFormatter list(source.GetAccount());
199  list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("By")).AddColumn(_("Created")).AddColumn(_("Expires")).AddColumn(_("Reason"));
200  this->ProcessList(source, params, list);
201  }
202 
203  void OnClear(CommandSource &source)
204  {
205  FOREACH_MOD(OnDelXLine, (source, NULL, this->xlm()));
206 
207  for (unsigned i = this->xlm()->GetCount(); i > 0; --i)
208  {
209  XLine *x = this->xlm()->GetEntry(i - 1);
210  this->xlm()->DelXLine(x);
211  }
212 
213  Log(LOG_ADMIN, source, this) << "to CLEAR the list";
214  source.Reply(_("The %s list has been cleared."), source.command.c_str());
215  if (Anope::ReadOnly)
216  source.Reply(READ_ONLY_MODE);
217 
218  return;
219  }
220  public:
221  CommandOSSXLineBase(Module *creator, const Anope::string &cmd) : Command(creator, cmd, 1, 4)
222  {
223  }
224 
226  {
227  return Anope::printf(Language::Translate(source.GetAccount(), _("Manipulate the %s list")), source.command.upper().c_str());
228  }
229 
230  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
231  {
232  const Anope::string &cmd = params[0];
233 
234  if (cmd.equals_ci("ADD"))
235  return this->OnAdd(source, params);
236  else if (cmd.equals_ci("DEL"))
237  return this->OnDel(source, params);
238  else if (cmd.equals_ci("LIST"))
239  return this->OnList(source, params);
240  else if (cmd.equals_ci("VIEW"))
241  return this->OnView(source, params);
242  else if (cmd.equals_ci("CLEAR"))
243  return this->OnClear(source);
244  else
245  this->OnSyntaxError(source, "");
246 
247  return;
248  }
249 
250  virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) = 0;
251 };
252 
254 {
256  {
257  return this->snlines;
258  }
259 
260  void OnAdd(CommandSource &source, const std::vector<Anope::string> &params) anope_override
261  {
262  if (!this->xlm())
263  return;
264 
265  unsigned last_param = 2;
266  Anope::string param, expiry;
267 
268  param = params.size() > 1 ? params[1] : "";
269  if (!param.empty() && param[0] == '+')
270  {
271  expiry = param;
272  param = params.size() > 2 ? params[2] : "";
273  last_param = 3;
274  }
275 
276  time_t expires = !expiry.empty() ? Anope::DoTime(expiry) : Config->GetModule("operserv")->Get<time_t>("snlineexpiry", "30d");
277  /* If the expiry given does not contain a final letter, it's in days,
278  * said the doc. Ah well.
279  */
280  if (!expiry.empty() && isdigit(expiry[expiry.length() - 1]))
281  expires *= 86400;
282  /* Do not allow less than a minute expiry time */
283  if (expires && expires < 60)
284  {
285  source.Reply(BAD_EXPIRY_TIME);
286  return;
287  }
288  else if (expires > 0)
289  expires += Anope::CurTime;
290 
291  if (param.empty())
292  {
293  this->OnSyntaxError(source, "ADD");
294  return;
295  }
296 
297  Anope::string rest = param;
298  if (params.size() > last_param)
299  rest += " " + params[last_param];
300 
301  if (rest.find(':') == Anope::string::npos)
302  {
303  this->OnSyntaxError(source, "ADD");
304  return;
305  }
306 
307  sepstream sep(rest, ':');
308  Anope::string mask;
309  sep.GetToken(mask);
310  Anope::string reason = sep.GetRemaining();
311 
312  if (mask.empty() || reason.empty())
313  {
314  this->OnSyntaxError(source, "ADD");
315  return;
316  }
317 
318  if (mask[0] == '/' && mask[mask.length() - 1] == '/')
319  {
320  const Anope::string &regexengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine");
321 
322  if (regexengine.empty())
323  {
324  source.Reply(_("Regex is disabled."));
325  return;
326  }
327 
328  ServiceReference<RegexProvider> provider("Regex", regexengine);
329  if (!provider)
330  {
331  source.Reply(_("Unable to find regex engine %s."), regexengine.c_str());
332  return;
333  }
334 
335  try
336  {
337  Anope::string stripped_mask = mask.substr(1, mask.length() - 2);
338  delete provider->Compile(stripped_mask);
339  }
340  catch (const RegexException &ex)
341  {
342  source.Reply("%s", ex.GetReason().c_str());
343  return;
344  }
345  }
346 
347  /* Clean up the last character of the mask if it is a space
348  * See bug #761
349  */
350  unsigned masklen = mask.length();
351  if (mask[masklen - 1] == ' ')
352  mask.erase(masklen - 1);
353 
354  if (!this->xlm()->CanAdd(source, mask, expires, reason))
355  return;
356  else if (mask.find_first_not_of("/.*?") == Anope::string::npos)
357  {
358  source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str());
359  return;
360  }
361 
362  if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
363  reason = "[" + source.GetNick() + "] " + reason;
364 
365  XLine *x = new XLine(mask, source.GetNick(), expires, reason);
366  if (Config->GetModule("operserv")->Get<bool>("akillids"))
368 
369  unsigned int affected = 0;
370  for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
371  if (this->xlm()->Check(it->second, x))
372  ++affected;
373  float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0;
374 
375  if (percent > 95)
376  {
377  source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str());
378  Log(LOG_ADMIN, source, this) << "tried to " << source.command << " " << percent << "% of the network (" << affected << " users)";
379  delete x;
380  return;
381  }
382 
383  EventReturn MOD_RESULT;
384  FOREACH_RESULT(OnAddXLine, MOD_RESULT, (source, x, this->xlm()));
385  if (MOD_RESULT == EVENT_STOP)
386  {
387  delete x;
388  return;
389  }
390 
391  this->xlm()->AddXLine(x);
392 
393  if (Config->GetModule("operserv")->Get<bool>("killonsnline", "yes"))
394  {
395  Anope::string rreason = "G-Lined: " + reason;
396 
397  for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
398  {
399  User *user = it->second;
400 
401  if (!user->HasMode("OPER") && user->server != Me && this->xlm()->Check(user, x))
402  user->Kill(Me->GetName(), rreason);
403  }
404 
405  this->xlm()->Send(NULL, x);
406  }
407 
408  source.Reply(_("\002%s\002 added to the %s list."), mask.c_str(), source.command.c_str());
409  Log(LOG_ADMIN, source, this) << "on " << mask << " (" << reason << "), expires in " << (expires ? Anope::Duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]";
410  if (Anope::ReadOnly)
411  source.Reply(READ_ONLY_MODE);
412  }
413 
415  public:
416  CommandOSSNLine(Module *creator) : CommandOSSXLineBase(creator, "operserv/snline"), snlines("XLineManager", "xlinemanager/snline")
417  {
418  this->SetSyntax(_("ADD [+\037expiry\037] \037mask\037:\037reason\037"));
419  this->SetSyntax(_("DEL {\037mask\037 | \037entry-num\037 | \037list\037 | \037id\037}"));
420  this->SetSyntax(_("LIST [\037mask\037 | \037list\037 | \037id\037]"));
421  this->SetSyntax(_("VIEW [\037mask\037 | \037list\037 | \037id\037]"));
422  this->SetSyntax("CLEAR");
423  }
424 
425  bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
426  {
427  this->SendSyntax(source);
428  source.Reply(" ");
429  source.Reply(_("Allows Services Operators to manipulate the SNLINE list. If\n"
430  "a user with a realname matching an SNLINE mask attempts to\n"
431  "connect, Services will not allow it to pursue his IRC\n"
432  "session."));
433  source.Reply(_(" \n"
434  "\002SNLINE ADD\002 adds the given realname mask to the SNLINE\n"
435  "list for the given reason (which \002must\002 be given).\n"
436  "\037expiry\037 is specified as an integer followed by one of \037d\037\n"
437  "(days), \037h\037 (hours), or \037m\037 (minutes). Combinations (such as\n"
438  "\0371h30m\037) are not permitted. If a unit specifier is not\n"
439  "included, the default is days (so \037+30\037 by itself means 30\n"
440  "days). To add an SNLINE which does not expire, use \037+0\037. If the\n"
441  "realname mask to be added starts with a \037+\037, an expiry time must\n"
442  "be given, even if it is the same as the default. The\n"
443  "current SNLINE default expiry time can be found with the\n"
444  "\002STATS AKILL\002 command.\n"
445  " \n"
446  "\002Note\002: because the realname mask may contain spaces, the\n"
447  "separator between it and the reason is a colon."));
448  const Anope::string &regexengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine");
449  if (!regexengine.empty())
450  {
451  source.Reply(" ");
452  source.Reply(_("Regex matches are also supported using the %s engine.\n"
453  "Enclose your mask in // if this is desired."), regexengine.c_str());
454  }
455  source.Reply(_(" \n"
456  "The \002SNLINE DEL\002 command removes the given mask from the\n"
457  "SNLINE list if it is present. If a list of entry numbers is\n"
458  "given, those entries are deleted. (See the example for LIST\n"
459  "below.)\n"
460  " \n"
461  "The \002SNLINE LIST\002 command displays the SNLINE list.\n"
462  "If a wildcard mask is given, only those entries matching the\n"
463  "mask are displayed. If a list of entry numbers is given,\n"
464  "only those entries are shown; for example:\n"
465  " \002SNLINE LIST 2-5,7-9\002\n"
466  " Lists SNLINE entries numbered 2 through 5 and 7\n"
467  " through 9.\n"
468  " \n"
469  "\002SNLINE VIEW\002 is a more verbose version of \002SNLINE LIST\002, and\n"
470  "will show who added an SNLINE, the date it was added, and when\n"
471  "it expires, as well as the realname mask and reason.\n"
472  " \n"
473  "\002SNLINE CLEAR\002 clears all entries of the SNLINE list."));
474  return true;
475  }
476 };
477 
479 {
481  {
482  return this->sqlines;
483  }
484 
485  void OnAdd(CommandSource &source, const std::vector<Anope::string> &params) anope_override
486  {
487  if (!this->xlm())
488  return;
489 
490  unsigned last_param = 2;
491  Anope::string expiry, mask;
492 
493  mask = params.size() > 1 ? params[1] : "";
494  if (!mask.empty() && mask[0] == '+')
495  {
496  expiry = mask;
497  mask = params.size() > 2 ? params[2] : "";
498  last_param = 3;
499  }
500 
501  time_t expires = !expiry.empty() ? Anope::DoTime(expiry) : Config->GetModule("operserv")->Get<time_t>("sqlineexpiry", "30d");
502  /* If the expiry given does not contain a final letter, it's in days,
503  * said the doc. Ah well.
504  */
505  if (!expiry.empty() && isdigit(expiry[expiry.length() - 1]))
506  expires *= 86400;
507  /* Do not allow less than a minute expiry time */
508  if (expires && expires < 60)
509  {
510  source.Reply(BAD_EXPIRY_TIME);
511  return;
512  }
513  else if (expires > 0)
514  expires += Anope::CurTime;
515 
516  if (params.size() <= last_param)
517  {
518  this->OnSyntaxError(source, "ADD");
519  return;
520  }
521 
522  Anope::string reason = params[last_param];
523  if (last_param == 2 && params.size() > 3)
524  reason += " " + params[3];
525 
526  if (mask.empty() || reason.empty())
527  {
528  this->OnSyntaxError(source, "ADD");
529  return;
530  }
531 
532  if (mask[0] == '/' && mask[mask.length() - 1] == '/')
533  {
534  const Anope::string &regexengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine");
535 
536  if (regexengine.empty())
537  {
538  source.Reply(_("Regex is disabled."));
539  return;
540  }
541 
542  ServiceReference<RegexProvider> provider("Regex", regexengine);
543  if (!provider)
544  {
545  source.Reply(_("Unable to find regex engine %s."), regexengine.c_str());
546  return;
547  }
548 
549  try
550  {
551  Anope::string stripped_mask = mask.substr(1, mask.length() - 2);
552  delete provider->Compile(stripped_mask);
553  }
554  catch (const RegexException &ex)
555  {
556  source.Reply("%s", ex.GetReason().c_str());
557  return;
558  }
559  }
560 
561  if (!this->sqlines->CanAdd(source, mask, expires, reason))
562  return;
563  else if (mask.find_first_not_of("./?*") == Anope::string::npos)
564  {
565  source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str());
566  return;
567  }
568 
569  if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
570  reason = "[" + source.GetNick() + "] " + reason;
571 
572  XLine *x = new XLine(mask, source.GetNick(), expires, reason);
573  if (Config->GetModule("operserv")->Get<bool>("akillids"))
575 
576  unsigned int affected = 0;
577  for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
578  if (this->xlm()->Check(it->second, x))
579  ++affected;
580  float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0;
581 
582  if (percent > 95)
583  {
584  source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str());
585  Log(LOG_ADMIN, source, this) << "tried to SQLine " << percent << "% of the network (" << affected << " users)";
586  delete x;
587  return;
588  }
589 
590  EventReturn MOD_RESULT;
591  FOREACH_RESULT(OnAddXLine, MOD_RESULT, (source, x, this->xlm()));
592  if (MOD_RESULT == EVENT_STOP)
593  {
594  delete x;
595  return;
596  }
597 
598  this->xlm()->AddXLine(x);
599 
600  if (Config->GetModule("operserv")->Get<bool>("killonsqline", "yes"))
601  {
602  Anope::string rreason = "Q-Lined: " + reason;
603 
604  if (mask[0] == '#')
605  {
606  for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit)
607  {
608  Channel *c = cit->second;
609 
610  if (!Anope::Match(c->name, mask, false, true))
611  continue;
612 
613  std::vector<User *> users;
614  for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it)
615  {
616  ChanUserContainer *uc = it->second;
617  User *user = uc->user;
618 
619  if (!user->HasMode("OPER") && user->server != Me)
620  users.push_back(user);
621  }
622 
623  for (unsigned i = 0; i < users.size(); ++i)
624  c->Kick(NULL, users[i], "%s", reason.c_str());
625  }
626  }
627  else
628  {
629  for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
630  {
631  User *user = it->second;
632 
633  if (!user->HasMode("OPER") && user->server != Me && this->xlm()->Check(user, x))
634  user->Kill(Me->GetName(), rreason);
635  }
636  }
637 
638  this->xlm()->Send(NULL, x);
639  }
640 
641  source.Reply(_("\002%s\002 added to the %s list."), mask.c_str(), source.command.c_str());
642  Log(LOG_ADMIN, source, this) << "on " << mask << " (" << reason << "), expires in " << (expires ? Anope::Duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]";
643  if (Anope::ReadOnly)
644  source.Reply(READ_ONLY_MODE);
645  }
646 
648  public:
649  CommandOSSQLine(Module *creator) : CommandOSSXLineBase(creator, "operserv/sqline"), sqlines("XLineManager", "xlinemanager/sqline")
650  {
651  this->SetSyntax(_("ADD [+\037expiry\037] \037mask\037 \037reason\037"));
652  this->SetSyntax(_("DEL {\037mask\037 | \037entry-num\037 | \037list\037 | \037id\037}"));
653  this->SetSyntax(_("LIST [\037mask\037 | \037list\037 | \037id\037]"));
654  this->SetSyntax(_("VIEW [\037mask\037 | \037list\037 | \037id\037]"));
655  this->SetSyntax("CLEAR");
656  }
657 
658  bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
659  {
660  this->SendSyntax(source);
661  source.Reply(" ");
662  source.Reply(_("Allows Services Operators to manipulate the SQLINE list. If\n"
663  "a user with a nick matching an SQLINE mask attempts to\n"
664  "connect, Services will not allow it to pursue his IRC\n"
665  "session.\n"
666  "If the first character of the mask is #, services will\n"
667  "prevent the use of matching channels."));
668  source.Reply(_(" \n"
669  "\002SQLINE ADD\002 adds the given (nick's) mask to the SQLINE\n"
670  "list for the given reason (which \002must\002 be given).\n"
671  "\037expiry\037 is specified as an integer followed by one of \037d\037\n"
672  "(days), \037h\037 (hours), or \037m\037 (minutes). Combinations (such as\n"
673  "\0371h30m\037) are not permitted. If a unit specifier is not\n"
674  "included, the default is days (so \037+30\037 by itself means 30\n"
675  "days). To add an SQLINE which does not expire, use \037+0\037.\n"
676  "If the mask to be added starts with a \037+\037, an expiry time\n"
677  "must be given, even if it is the same as the default. The\n"
678  "current SQLINE default expiry time can be found with the\n"
679  "\002STATS AKILL\002 command."));
680  const Anope::string &regexengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine");
681  if (!regexengine.empty())
682  {
683  source.Reply(" ");
684  source.Reply(_("Regex matches are also supported using the %s engine.\n"
685  "Enclose your mask in // if this is desired."), regexengine.c_str());
686  }
687  source.Reply(_(" \n"
688  "The \002SQLINE DEL\002 command removes the given mask from the\n"
689  "SQLINE list if it is present. If a list of entry numbers is\n"
690  "given, those entries are deleted. (See the example for LIST\n"
691  "below.)\n"
692  " \n"
693  "The \002SQLINE LIST\002 command displays the SQLINE list.\n"
694  "If a wildcard mask is given, only those entries matching the\n"
695  "mask are displayed. If a list of entry numbers is given,\n"
696  "only those entries are shown; for example:\n"
697  " \002SQLINE LIST 2-5,7-9\002\n"
698  " Lists SQLINE entries numbered 2 through 5 and 7\n"
699  " through 9.\n"
700  " \n"
701  "\002SQLINE VIEW\002 is a more verbose version of \002SQLINE LIST\002, and\n"
702  "will show who added an SQLINE, the date it was added, and when\n"
703  "it expires, as well as the mask and reason.\n"
704  " \n"
705  "\002SQLINE CLEAR\002 clears all entries of the SQLINE list."));
706  return true;
707  }
708 };
709 
710 class OSSXLine : public Module
711 {
714 
715  public:
716  OSSXLine(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
717  commandossnline(this), commandossqline(this)
718  {
719  }
720 };
721 
bool HasMode(const Anope::string &name) const
Definition: users.cpp:513
void ProcessList(CommandSource &source, const std::vector< Anope::string > &params, ListFormatter &list)
Definition: os_sxline.cpp:109
CoreExport bool ReadOnly
Definition: main.cpp:28
void Kill(const MessageSource &source, const Anope::string &reason)
Definition: users.cpp:729
void OnAdd(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: os_sxline.cpp:260
Anope::string reason
Definition: xline.h:29
Anope::string mask
Definition: xline.h:24
CommandOSSNLine commandossnline
Definition: os_sxline.cpp:712
void OnAdd(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: os_sxline.cpp:485
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
Definition: os_sxline.cpp:425
CommandOSSQLine commandossqline
Definition: os_sxline.cpp:713
virtual void OnAdd(CommandSource &source, const std::vector< Anope::string > &params)=0
CommandOSSXLineBase(Module *creator, const Anope::string &cmd)
Definition: os_sxline.cpp:221
CoreExport string printf(const char *fmt,...)
Definition: misc.cpp:536
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: os_sxline.cpp:230
void Process(std::vector< Anope::string > &)
Definition: misc.cpp:144
XLineManager * xlm
Definition: os_sxline.cpp:16
Definition: users.h:34
void OnDel(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_sxline.cpp:64
void AddEntry(const ListEntry &entry)
Definition: misc.cpp:134
string upper() const
Definition: anope.h:266
const Anope::string GetDesc(CommandSource &source) const anope_override
Definition: os_sxline.cpp:225
XLine * GetEntry(unsigned index)
Definition: xline.cpp:322
#define READ_ONLY_MODE
Definition: language.h:71
#define FOREACH_RESULT(ename, ret, args)
Definition: modules.h:95
Command * command
Definition: os_sxline.cpp:17
bool equals_ci(const char *_str) const
Definition: anope.h:78
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
Definition: os_sxline.cpp:658
Anope::string name
Definition: channels.h:44
CoreExport time_t CurTime
Definition: main.cpp:41
ServiceReference< XLineManager > snlines
Definition: os_sxline.cpp:414
#define FOREACH_MOD(ename, args)
Definition: modules.h:62
iterator erase(const iterator &i)
Definition: anope.h:155
string substr(size_type pos=0, size_type n=npos) const
Definition: anope.h:277
CommandOSSNLine(Module *creator)
Definition: os_sxline.cpp:416
std::map< Anope::string, Anope::string > ListEntry
Definition: lists.h:68
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
virtual void OnSyntaxError(CommandSource &source, const Anope::string &subcommand)
Definition: command.cpp:191
static const size_type npos
Definition: anope.h:44
Anope::string command
Definition: commands.h:69
bool IsEmpty() const
Definition: misc.cpp:139
CoreExport time_t DoTime(const Anope::string &s)
Definition: misc.cpp:275
void Reply(const char *message,...)
Definition: command.cpp:96
CommandSource & source
Definition: os_sxline.cpp:18
bool DelXLine(XLine *x)
Definition: xline.cpp:294
Anope::string by
Definition: xline.h:26
time_t expires
Definition: xline.h:28
virtual bool Check(User *u, const XLine *x)=0
static void DoDel(XLineManager *xlm, CommandSource &source, XLine *x)
Definition: os_sxline.cpp:51
ServiceReference< XLineManager > sqlines
Definition: os_sxline.cpp:647
#define anope_override
Definition: services.h:56
bool empty() const
Definition: anope.h:126
Anope::string id
Definition: xline.h:31
XLineManager * xlm()
Definition: os_sxline.cpp:480
SXLineDelCallback(XLineManager *x, Command *c, CommandSource &_source, const Anope::string &numlist)
Definition: os_sxline.cpp:21
virtual Regex * Compile(const Anope::string &)=0
void OnClear(CommandSource &source)
Definition: os_sxline.cpp:203
const Anope::string GetRemaining()
Definition: hashcomp.cpp:156
EventReturn
Definition: modules.h:129
#define MODULE_INIT(x)
Definition: modules.h:45
Server * server
Definition: users.h:77
CoreExport channel_map ChannelList
Definition: channels.cpp:29
XLineManager * xlm()
Definition: os_sxline.cpp:255
CoreExport const char * Translate(const char *string)
Definition: language.cpp:59
ChanUserList users
Definition: channels.h:56
void SetSyntax(const Anope::string &s)
Definition: command.cpp:140
void Process()
Definition: misc.cpp:98
size_type find_first_not_of(const string &_str, size_type pos=0) const
Definition: anope.h:205
void OnView(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_sxline.cpp:196
Anope::string stringify(const T &x)
Definition: anope.h:710
virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand)=0
unsigned deleted
Definition: os_sxline.cpp:19
virtual void Send(User *u, XLine *x)=0
virtual XLineManager * xlm()=0
XLine * HasEntry(const Anope::string &mask)
Definition: xline.cpp:391
bool Kick(BotInfo *bi, User *u, const char *reason=NULL,...)
Definition: channels.cpp:762
const Anope::string & GetName() const
Definition: servers.cpp:175
#define USERHOST_MASK_TOO_WIDE
Definition: language.h:70
void OnList(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_sxline.cpp:188
Definition: xline.h:18
bool GetToken(Anope::string &token)
Definition: hashcomp.cpp:99
CommandOSSQLine(Module *creator)
Definition: os_sxline.cpp:649
Reference< NickCore > nc
Definition: commands.h:61
CoreExport Server * Me
Definition: servers.cpp:24
virtual const Anope::string & GetReason() const
Definition: anope.h:672
CoreExport user_map UserListByNick
Definition: users.cpp:28
void SendSyntax(CommandSource &)
Definition: command.cpp:145
NickCore * GetAccount()
Definition: command.cpp:36
const char * c_str() const
Definition: anope.h:117
Definition: logger.h:53
CoreExport Anope::string Duration(time_t seconds, const NickCore *nc=NULL)
Definition: misc.cpp:315
void HandleNumber(unsigned number) anope_override
Definition: os_sxline.cpp:35
#define BAD_EXPIRY_TIME
Definition: language.h:69
CoreExport Anope::string strftime(time_t t, const NickCore *nc=NULL, bool short_output=false)
Definition: misc.cpp:356
void AddXLine(XLine *x)
Definition: xline.cpp:286
static Anope::string GenerateUID()
Definition: xline.cpp:234
time_t created
Definition: xline.h:27
size_type find(const string &_str, size_type pos=0) const
Definition: anope.h:192
#define _(x)
Definition: services.h:50
CoreExport Anope::string Expires(time_t seconds, const NickCore *nc=NULL)
Definition: misc.cpp:371
ListFormatter & AddColumn(const Anope::string &name)
Definition: misc.cpp:128
OSSXLine(const Anope::string &modname, const Anope::string &creator)
Definition: os_sxline.cpp:716