Anope IRC Services  Version 2.0
os_ignore.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 #include "modules/os_ignore.h"
14 
16 {
17  IgnoreDataImpl() : Serializable("IgnoreData") { }
19  void Serialize(Serialize::Data &data) const anope_override;
21 };
22 
24 {
25  if (ignore_service)
26  ignore_service->DelIgnore(this);
27 }
28 
30 {
31  data["mask"] << this->mask;
32  data["creator"] << this->creator;
33  data["reason"] << this->reason;
34  data["time"] << this->time;
35 }
36 
38 {
39  if (!ignore_service)
40  return NULL;
41 
42  IgnoreDataImpl *ign;
43  if (obj)
45  else
46  {
47  ign = new IgnoreDataImpl();
48  ignore_service->AddIgnore(ign);
49  }
50 
51  data["mask"] >> ign->mask;
52  data["creator"] >> ign->creator;
53  data["reason"] >> ign->reason;
54  data["time"] >> ign->time;
55 
56  return ign;
57 }
58 
59 
61 {
63 
64  public:
65  OSIgnoreService(Module *o) : IgnoreService(o), ignores("IgnoreData") { }
66 
68  {
69  ignores->push_back(ign);
70  }
71 
73  {
74  std::vector<IgnoreData *>::iterator it = std::find(ignores->begin(), ignores->end(), ign);
75  if (it != ignores->end())
76  ignores->erase(it);
77  }
78 
80  {
81  for (unsigned i = ignores->size(); i > 0; --i)
82  {
83  IgnoreData *ign = ignores->at(i - 1);
84  delete ign;
85  }
86  }
87 
89  {
90  return new IgnoreDataImpl();
91  }
92 
94  {
95  User *u = User::Find(mask, true);
96  std::vector<IgnoreData *>::iterator ign = this->ignores->begin(), ign_end = this->ignores->end();
97 
98  if (u)
99  {
100  for (; ign != ign_end; ++ign)
101  {
102  Entry ignore_mask("", (*ign)->mask);
103  if (ignore_mask.Matches(u, true))
104  break;
105  }
106  }
107  else
108  {
109  size_t user, host;
110  Anope::string tmp;
111  /* We didn't get a user.. generate a valid mask. */
112  if ((host = mask.find('@')) != Anope::string::npos)
113  {
114  if ((user = mask.find('!')) != Anope::string::npos)
115  {
116  /* this should never happen */
117  if (user > host)
118  return NULL;
119  tmp = mask;
120  }
121  else
122  /* We have user@host. Add nick wildcard. */
123  tmp = "*!" + mask;
124  }
125  /* We only got a nick.. */
126  else
127  tmp = mask + "!*@*";
128 
129  for (; ign != ign_end; ++ign)
130  if (Anope::Match(tmp, (*ign)->mask, false, true))
131  break;
132  }
133 
134  /* Check whether the entry has timed out */
135  if (ign != ign_end)
136  {
137  IgnoreData *id = *ign;
138 
139  if (id->time && !Anope::NoExpire && id->time <= Anope::CurTime)
140  {
141  Log(LOG_NORMAL, "expire/ignore", Config->GetClient("OperServ")) << "Expiring ignore entry " << id->mask;
142  delete id;
143  }
144  else
145  return id;
146  }
147 
148  return NULL;
149  }
150 
151  std::vector<IgnoreData *> &GetIgnores() anope_override
152  {
153  return *ignores;
154  }
155 };
156 
157 class CommandOSIgnore : public Command
158 {
159  private:
161  {
162  /* If it s an existing user, we ignore the hostmask. */
163  User *u = User::Find(mask, true);
164  if (u)
165  return "*!*@" + u->host;
166 
167  size_t host = mask.find('@');
168  /* Determine whether we get a nick or a mask. */
169  if (host != Anope::string::npos)
170  {
171  size_t user = mask.find('!');
172  /* Check whether we have a nick too.. */
173  if (user != Anope::string::npos)
174  {
175  if (user > host)
176  /* this should never happen */
177  return "";
178  else
179  return mask;
180  }
181  else
182  /* We have user@host. Add nick wildcard. */
183  return "*!" + mask;
184  }
185 
186  /* We only got a nick.. */
187  return mask + "!*@*";
188  }
189 
190  void DoAdd(CommandSource &source, const std::vector<Anope::string> &params)
191  {
192  if (!ignore_service)
193  return;
194 
195  const Anope::string &time = params.size() > 1 ? params[1] : "";
196  const Anope::string &nick = params.size() > 2 ? params[2] : "";
197  const Anope::string &reason = params.size() > 3 ? params[3] : "";
198 
199  if (time.empty() || nick.empty())
200  {
201  this->OnSyntaxError(source, "ADD");
202  return;
203  }
204  else
205  {
206  time_t t = Anope::DoTime(time);
207 
208  if (t <= -1)
209  {
210  source.Reply(BAD_EXPIRY_TIME);
211  return;
212  }
213 
214  Anope::string mask = RealMask(nick);
215  if (mask.empty())
216  {
217  source.Reply(BAD_USERHOST_MASK);
218  return;
219  }
220 
221  if (Anope::ReadOnly)
222  source.Reply(READ_ONLY_MODE);
223 
224  IgnoreData *ign = new IgnoreDataImpl();
225  ign->mask = mask;
226  ign->creator = source.GetNick();
227  ign->reason = reason;
228  ign->time = t ? Anope::CurTime + t : 0;
229 
230  ignore_service->AddIgnore(ign);
231  if (!t)
232  {
233  source.Reply(_("\002%s\002 will now permanently be ignored."), mask.c_str());
234  Log(LOG_ADMIN, source, this) << "to add a permanent ignore for " << mask;
235  }
236  else
237  {
238  source.Reply(_("\002%s\002 will now be ignored for \002%s\002."), mask.c_str(), Anope::Duration(t, source.GetAccount()).c_str());
239  Log(LOG_ADMIN, source, this) << "to add an ignore on " << mask << " for " << Anope::Duration(t);
240  }
241  }
242  }
243 
244  void DoList(CommandSource &source)
245  {
246  if (!ignore_service)
247  return;
248 
249  std::vector<IgnoreData *> &ignores = ignore_service->GetIgnores();
250  for (unsigned i = ignores.size(); i > 0; --i)
251  {
252  IgnoreData *id = ignores[i - 1];
253 
254  if (id->time && !Anope::NoExpire && id->time <= Anope::CurTime)
255  {
256  Log(LOG_NORMAL, "expire/ignore", Config->GetClient("OperServ")) << "Expiring ignore entry " << id->mask;
257  delete id;
258  }
259  }
260 
261  if (ignores.empty())
262  source.Reply(_("Ignore list is empty."));
263  else
264  {
265  ListFormatter list(source.GetAccount());
266  list.AddColumn(_("Mask")).AddColumn(_("Creator")).AddColumn(_("Reason")).AddColumn(_("Expires"));
267 
268  for (unsigned i = ignores.size(); i > 0; --i)
269  {
270  const IgnoreData *ignore = ignores[i - 1];
271 
273  entry["Mask"] = ignore->mask;
274  entry["Creator"] = ignore->creator;
275  entry["Reason"] = ignore->reason;
276  entry["Expires"] = Anope::Expires(ignore->time, source.GetAccount());
277  list.AddEntry(entry);
278  }
279 
280  source.Reply(_("Services ignore list:"));
281 
282  std::vector<Anope::string> replies;
283  list.Process(replies);
284 
285  for (unsigned i = 0; i < replies.size(); ++i)
286  source.Reply(replies[i]);
287  }
288  }
289 
290  void DoDel(CommandSource &source, const std::vector<Anope::string> &params)
291  {
292  if (!ignore_service)
293  return;
294 
295  const Anope::string nick = params.size() > 1 ? params[1] : "";
296  if (nick.empty())
297  {
298  this->OnSyntaxError(source, "DEL");
299  return;
300  }
301 
302  Anope::string mask = RealMask(nick);
303  if (mask.empty())
304  {
305  source.Reply(BAD_USERHOST_MASK);
306  return;
307  }
308 
309  IgnoreData *ign = ignore_service->Find(mask);
310  if (ign)
311  {
312  if (Anope::ReadOnly)
313  source.Reply(READ_ONLY_MODE);
314 
315  Log(LOG_ADMIN, source, this) << "to remove an ignore on " << mask;
316  source.Reply(_("\002%s\002 will no longer be ignored."), mask.c_str());
317  delete ign;
318  }
319  else
320  source.Reply(_("\002%s\002 not found on ignore list."), mask.c_str());
321  }
322 
323  void DoClear(CommandSource &source)
324  {
325  if (!ignore_service)
326  return;
327 
328  if (Anope::ReadOnly)
329  source.Reply(READ_ONLY_MODE);
330 
331  ignore_service->ClearIgnores();
332  Log(LOG_ADMIN, source, this) << "to CLEAR the list";
333  source.Reply(_("Ignore list has been cleared."));
334 
335  return;
336  }
337 
338  public:
339  CommandOSIgnore(Module *creator) : Command(creator, "operserv/ignore", 1, 4)
340  {
341  this->SetDesc(_("Modify the Services ignore list"));
342  this->SetSyntax(_("ADD \037expiry\037 {\037nick\037|\037mask\037} [\037reason\037]"));
343  this->SetSyntax(_("DEL {\037nick\037|\037mask\037}"));
344  this->SetSyntax("LIST");
345  this->SetSyntax("CLEAR");
346  }
347 
348  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
349  {
350  const Anope::string &cmd = params[0];
351 
352  if (cmd.equals_ci("ADD"))
353  return this->DoAdd(source, params);
354  else if (cmd.equals_ci("LIST"))
355  return this->DoList(source);
356  else if (cmd.equals_ci("DEL"))
357  return this->DoDel(source, params);
358  else if (cmd.equals_ci("CLEAR"))
359  return this->DoClear(source);
360  else
361  this->OnSyntaxError(source, "");
362 
363  return;
364  }
365 
366  bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
367  {
368  this->SendSyntax(source);
369  source.Reply(" ");
370  source.Reply(_("Allows Services Operators to make Services ignore a nick or mask\n"
371  "for a certain time or until the next restart. The default\n"
372  "time format is seconds. You can specify it by using units.\n"
373  "Valid units are: \037s\037 for seconds, \037m\037 for minutes,\n"
374  "\037h\037 for hours and \037d\037 for days.\n"
375  "Combinations of these units are not permitted.\n"
376  "To make Services permanently ignore the user, type 0 as time.\n"
377  "When adding a \037mask\037, it should be in the format nick!user@host,\n"
378  "everything else will be considered a nick. Wildcards are permitted.\n"
379  " \n"
380  "Ignores will not be enforced on IRC Operators."));
381 
382  const Anope::string &regexengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine");
383  if (!regexengine.empty())
384  {
385  source.Reply(" ");
386  source.Reply(_("Regex matches are also supported using the %s engine.\n"
387  "Enclose your pattern in // if this is desired."), regexengine.c_str());
388  }
389 
390  return true;
391  }
392 };
393 
394 class OSIgnore : public Module
395 {
399 
400  public:
401  OSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
402  ignoredata_type("IgnoreData", IgnoreDataImpl::Unserialize), osignoreservice(this), commandosignore(this)
403  {
404 
405  }
406 
408  {
409  if (!u->HasMode("OPER") && this->osignoreservice.Find(u->nick))
410  return EVENT_STOP;
411 
412  return EVENT_CONTINUE;
413  }
414 };
415 
Definition: bots.h:24
CoreExport bool ReadOnly
Definition: main.cpp:28
Anope::string mask
Definition: os_ignore.h:15
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: os_ignore.cpp:348
void AddIgnore(IgnoreData *ign) anope_override
Definition: os_ignore.cpp:67
bool Matches(User *u, bool full=false) const
Definition: modes.cpp:830
std::vector< IgnoreData * > & GetIgnores() anope_override
Definition: os_ignore.cpp:151
#define BAD_USERHOST_MASK
Definition: language.h:68
CommandOSIgnore(Module *creator)
Definition: os_ignore.cpp:339
void DelIgnore(IgnoreData *ign) anope_override
Definition: os_ignore.cpp:72
Anope::string reason
Definition: os_ignore.h:17
void ClearIgnores() anope_override
Definition: os_ignore.cpp:79
Definition: users.h:34
void DoList(CommandSource &source)
Definition: os_ignore.cpp:244
#define READ_ONLY_MODE
Definition: language.h:71
void SetDesc(const Anope::string &d)
Definition: command.cpp:130
bool equals_ci(const char *_str) const
Definition: anope.h:78
Serialize::Checker< std::vector< IgnoreData * > > ignores
Definition: os_ignore.cpp:62
CoreExport time_t CurTime
Definition: main.cpp:41
const Anope::string & GetNick() const
Definition: command.cpp:26
std::map< Anope::string, Anope::string > ListEntry
Definition: lists.h:68
void DoClear(CommandSource &source)
Definition: os_ignore.cpp:323
Serialize::Type ignoredata_type
Definition: os_ignore.cpp:396
Definition: Config.cs:26
OSIgnoreService osignoreservice
Definition: os_ignore.cpp:397
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
CoreExport time_t DoTime(const Anope::string &s)
Definition: misc.cpp:275
void Reply(const char *message,...)
Definition: command.cpp:96
EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) anope_override
Definition: os_ignore.cpp:407
#define anope_override
Definition: services.h:56
bool empty() const
Definition: anope.h:126
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
Definition: os_ignore.cpp:366
Anope::string host
Definition: users.h:65
void Serialize(Serialize::Data &data) const anope_override
Definition: os_ignore.cpp:29
IgnoreData * Find(const Anope::string &mask) anope_override
Definition: os_ignore.cpp:93
EventReturn
Definition: modules.h:129
#define MODULE_INIT(x)
Definition: modules.h:45
Anope::string RealMask(const Anope::string &mask)
Definition: os_ignore.cpp:160
void SetSyntax(const Anope::string &s)
Definition: command.cpp:140
Anope::string creator
Definition: os_ignore.h:16
time_t time
Definition: os_ignore.h:18
CoreExport bool NoExpire
Definition: main.cpp:28
static User * Find(const Anope::string &name, bool nick_only=false)
Definition: users.cpp:815
void DoDel(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_ignore.cpp:290
T anope_dynamic_static_cast(O ptr)
Definition: anope.h:774
void SendSyntax(CommandSource &)
Definition: command.cpp:145
NickCore * GetAccount()
Definition: command.cpp:36
CommandOSIgnore commandosignore
Definition: os_ignore.cpp:398
const char * c_str() const
Definition: anope.h:117
IgnoreData * Create() anope_override
Definition: os_ignore.cpp:88
Definition: logger.h:53
OSIgnore(const Anope::string &modname, const Anope::string &creator)
Definition: os_ignore.cpp:401
CoreExport Anope::string Duration(time_t seconds, const NickCore *nc=NULL)
Definition: misc.cpp:315
void DoAdd(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_ignore.cpp:190
#define BAD_EXPIRY_TIME
Definition: language.h:69
Definition: modes.h:388
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
Type(const Anope::string &n, unserialize_func f, Module *owner=NULL)
OSIgnoreService(Module *o)
Definition: os_ignore.cpp:65
static Serializable * Unserialize(Serializable *obj, Serialize::Data &data)
Definition: os_ignore.cpp:37
static ServiceReference< IgnoreService > ignore_service("IgnoreService","ignore")