Anope IRC Services  Version 2.0
cs_ban.cpp
Go to the documentation of this file.
1 /* ChanServ 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 
13 #include "module.h"
14 
15 static Module *me;
16 
17 class TempBan : public Timer
18 {
19  private:
23 
24  public:
25  TempBan(time_t seconds, Channel *c, const Anope::string &banmask, const Anope::string &mod) : Timer(me, seconds), channel(c->name), mask(banmask), mode(mod) { }
26 
27  void Tick(time_t ctime) anope_override
28  {
29  Channel *c = Channel::Find(this->channel);
30  if (c)
31  c->RemoveMode(NULL, mode, this->mask);
32  }
33 };
34 
35 class CommandCSBan : public Command
36 {
37  public:
38  CommandCSBan(Module *creator) : Command(creator, "chanserv/ban", 2, 4)
39  {
40  this->SetDesc(_("Bans a given nick or mask on a channel"));
41  this->SetSyntax(_("\037channel\037 [+\037expiry\037] {\037nick\037 | \037mask\037} [\037reason\037]"));
42  }
43 
44  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
45  {
46  const Anope::string &chan = params[0];
47  Configuration::Block *block = Config->GetCommand(source);
48  const Anope::string &mode = block->Get<Anope::string>("mode", "BAN");
49 
51  if (ci == NULL)
52  {
53  source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str());
54  return;
55  }
56 
57  Channel *c = ci->c;
58  if (c == NULL)
59  {
60  source.Reply(CHAN_X_NOT_IN_USE, chan.c_str());
61  return;
62  }
63  else if (IRCD->GetMaxListFor(c) && c->HasMode(mode) >= IRCD->GetMaxListFor(c))
64  {
65  source.Reply(_("The %s list for %s is full."), mode.lower().c_str(), c->name.c_str());
66  return;
67  }
68 
69  Anope::string expiry, target, reason;
70  time_t ban_time;
71  if (params[1][0] == '+')
72  {
73  ban_time = Anope::DoTime(params[1]);
74  if (ban_time == -1)
75  {
76  source.Reply(BAD_EXPIRY_TIME);
77  return;
78  }
79  if (params.size() < 3)
80  {
81  this->SendSyntax(source);
82  return;
83  }
84  target = params[2];
85  reason = "Requested";
86  if (params.size() > 3)
87  reason = params[3];
88  }
89  else
90  {
91  ban_time = 0;
92  target = params[1];
93  reason = "Requested";
94  if (params.size() > 2)
95  reason = params[2];
96  if (params.size() > 3)
97  reason += " " + params[3];
98  }
99 
100  unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200");
101  if (reason.length() > reasonmax)
102  reason = reason.substr(0, reasonmax);
103 
104  User *u = source.GetUser();
105  User *u2 = User::Find(target, true);
106 
107  AccessGroup u_access = source.AccessFor(ci);
108 
109  if (!u_access.HasPriv("BAN") && !source.HasPriv("chanserv/kick"))
110  source.Reply(ACCESS_DENIED);
111  else if (u2)
112  {
113  AccessGroup u2_access = ci->AccessFor(u2);
114 
115  if (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access && !source.HasPriv("chanserv/kick"))
116  source.Reply(ACCESS_DENIED);
117  /*
118  * Dont ban/kick the user on channels where he is excepted
119  * to prevent services <-> server wars.
120  */
121  else if (c->MatchesList(u2, "EXCEPT"))
122  source.Reply(CHAN_EXCEPTED, u2->nick.c_str(), ci->name.c_str());
123  else if (u2->IsProtected())
124  source.Reply(ACCESS_DENIED);
125  else
126  {
127  Anope::string mask = ci->GetIdealBan(u2);
128 
129  bool override = !u_access.HasPriv("BAN") || (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access);
130  Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << mask;
131 
132  if (!c->HasMode(mode, mask))
133  {
134  c->SetMode(NULL, mode, mask);
135  if (ban_time)
136  {
137  new TempBan(ban_time, c, mask, mode);
138  source.Reply(_("Ban on \002%s\002 expires in %s."), mask.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
139  }
140  }
141 
142  /* We still allow host banning while not allowing to kick */
143  if (!c->FindUser(u2))
144  return;
145 
146  if (block->Get<bool>("kick", "yes"))
147  {
148  if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !source.AccessFor(ci).HasPriv("SIGNKICK")))
149  c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), source.GetNick().c_str());
150  else
151  c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
152  }
153  }
154  }
155  else
156  {
157  bool founder = u_access.HasPriv("FOUNDER");
158  bool override = !founder && !u_access.HasPriv("BAN");
159  Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << target;
160 
161  if (!c->HasMode(mode, target))
162  {
163  c->SetMode(NULL, mode, target);
164  if (ban_time)
165  {
166  new TempBan(ban_time, c, target, mode);
167  source.Reply(_("Ban on \002%s\002 expires in %s."), target.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
168  }
169  }
170 
171  int matched = 0, kicked = 0;
172  for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end;)
173  {
174  ChanUserContainer *uc = it->second;
175  ++it;
176 
177  if (Anope::Match(uc->user->nick, target) || Anope::Match(uc->user->GetDisplayedMask(), target))
178  {
179  ++matched;
180 
181  AccessGroup u2_access = ci->AccessFor(uc->user);
182 
183  if (matched > 1 && !founder)
184  continue;
185  if (u != uc->user && ci->HasExt("PEACE") && u2_access >= u_access)
186  continue;
187  else if (ci->c->MatchesList(uc->user, "EXCEPT"))
188  continue;
189  else if (uc->user->IsProtected())
190  continue;
191 
192  if (block->Get<bool>("kick", "yes"))
193  {
194  ++kicked;
195  if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
196  c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), target.c_str(), source.GetNick().c_str());
197  else
198  c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), target.c_str());
199  }
200  }
201  }
202 
203  if (matched)
204  source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, target.c_str(), c->name.c_str());
205  else
206  source.Reply(_("No users on %s match %s."), c->name.c_str(), target.c_str());
207  }
208  }
209 
210  bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
211  {
212  this->SendSyntax(source);
213  source.Reply(" ");
214  source.Reply(_("Bans a given nick or mask on a channel. An optional expiry may\n"
215  "be given to cause services to remove the ban after a set amount\n"
216  "of time.\n"
217  " \n"
218  "By default, limited to AOPs or those with level 5 access\n"
219  "and above on the channel. Channel founders may ban masks."));
220  return true;
221  }
222 };
223 
224 class CSBan : public Module
225 {
227 
228  public:
229  CSBan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsban(this)
230  {
231  me = this;
232  }
233 };
234 
CSBan(const Anope::string &modname, const Anope::string &creator)
Definition: cs_ban.cpp:229
Definition: timers.h:18
Definition: hashcomp.h:84
#define CHAN_X_NOT_IN_USE
Definition: language.h:85
CommandCSBan commandcsban
Definition: cs_ban.cpp:226
#define ACCESS_DENIED
Definition: language.h:73
Definition: users.h:34
Anope::string mode
Definition: cs_ban.cpp:22
void SetDesc(const Anope::string &d)
Definition: command.cpp:130
string lower() const
Definition: anope.h:255
Anope::string name
Definition: channels.h:44
bool HasPriv(const Anope::string &priv) const
Definition: access.cpp:384
static ChannelInfo * Find(const Anope::string &name)
Definition: regchannel.cpp:630
string substr(size_type pos=0, size_type n=npos) const
Definition: anope.h:277
bool IsProtected()
Definition: users.cpp:724
size_type length() const
Definition: anope.h:131
Anope::string mask
Definition: cs_ban.cpp:21
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
CoreExport time_t DoTime(const Anope::string &s)
Definition: misc.cpp:275
Anope::string GetDisplayedMask() const
Definition: users.cpp:274
#define anope_override
Definition: services.h:56
CoreExport IRCDProto * IRCD
Definition: protocol.cpp:23
#define MODULE_INIT(x)
Definition: modules.h:45
#define CHAN_EXCEPTED
Definition: language.h:110
ChanUserList users
Definition: channels.h:56
ChanUserContainer * FindUser(User *u) const
Definition: channels.cpp:173
void SetSyntax(const Anope::string &s)
Definition: command.cpp:140
CommandCSBan(Module *creator)
Definition: cs_ban.cpp:38
size_t HasMode(const Anope::string &name, const Anope::string &param="")
Definition: channels.cpp:201
virtual unsigned GetMaxListFor(Channel *c)
Definition: protocol.cpp:432
bool MatchesList(User *u, const Anope::string &list)
Definition: channels.cpp:713
#define CHAN_X_NOT_REGISTERED
Definition: language.h:84
Anope::string nick
Definition: users.h:62
bool Kick(BotInfo *bi, User *u, const char *reason=NULL,...)
Definition: channels.cpp:762
static User * Find(const Anope::string &name, bool nick_only=false)
Definition: users.cpp:815
Anope::string channel
Definition: cs_ban.cpp:20
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: cs_ban.cpp:44
TempBan(time_t seconds, Channel *c, const Anope::string &banmask, const Anope::string &mod)
Definition: cs_ban.cpp:25
static Channel * Find(const Anope::string &name)
Definition: channels.cpp:920
Anope::string name
Definition: access.cpp:22
void SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param="", bool enforce_mlock=true)
Definition: channels.cpp:401
void SendSyntax(CommandSource &)
Definition: command.cpp:145
const char * c_str() const
Definition: anope.h:117
Definition: logger.h:53
T Get(const Anope::string &tag)
Definition: config.h:44
CoreExport Anope::string Duration(time_t seconds, const NickCore *nc=NULL)
Definition: misc.cpp:315
static Module * me
Definition: cs_ban.cpp:15
#define BAD_EXPIRY_TIME
Definition: language.h:69
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
Definition: cs_ban.cpp:210
#define _(x)
Definition: services.h:50
bool HasExt(const Anope::string &name) const
Definition: extensible.cpp:31
void Tick(time_t ctime) anope_override
Definition: cs_ban.cpp:27
void RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param="", bool enforce_mlock=true)
Definition: channels.cpp:459