00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "module.h"
00015
00016 static Module *me;
00017
00018 class TempBan : public CallBack
00019 {
00020 private:
00021 Anope::string channel;
00022 Anope::string mask;
00023
00024 public:
00025 TempBan(time_t seconds, Channel *c, const Anope::string &banmask) : CallBack(me, seconds), channel(c->name), mask(banmask) { }
00026
00027 void Tick(time_t ctime) anope_override
00028 {
00029 Channel *c = Channel::Find(this->channel);
00030 if (c)
00031 c->RemoveMode(NULL, "BAN", this->mask);
00032 }
00033 };
00034
00035 class CommandCSBan : public Command
00036 {
00037 public:
00038 CommandCSBan(Module *creator) : Command(creator, "chanserv/ban", 2, 4)
00039 {
00040 this->SetDesc(_("Bans a given nick or mask on a channel"));
00041 this->SetSyntax(_("\037channel\037 [+\037expiry\037] \037nick\037 [\037reason\037]"));
00042 this->SetSyntax(_("\037channel\037 [+\037expiry\037] \037mask\037 [\037reason\037]"));
00043 }
00044
00045 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00046 {
00047 const Anope::string &chan = params[0];
00048
00049 ChannelInfo *ci = ChannelInfo::Find(chan);
00050 if (ci == NULL)
00051 {
00052 source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str());
00053 return;
00054 }
00055
00056 Anope::string expiry, target, reason;
00057 time_t ban_time;
00058 if (params[1][0] == '+')
00059 {
00060 ban_time = Anope::DoTime(params[1]);
00061 if (params.size() < 3)
00062 {
00063 this->SendSyntax(source);
00064 return;
00065 }
00066 target = params[2];
00067 reason = "Requested";
00068 if (params.size() > 3)
00069 reason = params[3];
00070 }
00071 else
00072 {
00073 ban_time = 0;
00074 target = params[1];
00075 reason = "Requested";
00076 if (params.size() > 2)
00077 reason = params[2];
00078 if (params.size() > 3)
00079 reason += " " + params[3];
00080 }
00081
00082 if (reason.length() > Config->CSReasonMax)
00083 reason = reason.substr(0, Config->CSReasonMax);
00084
00085 Channel *c = ci->c;
00086 User *u = source.GetUser();
00087 User *u2 = User::Find(target, true);
00088
00089 AccessGroup u_access = source.AccessFor(ci);
00090
00091 if (!c)
00092 source.Reply(CHAN_X_NOT_IN_USE, chan.c_str());
00093 else if (!u_access.HasPriv("BAN") && !source.HasPriv("chanserv/kick"))
00094 source.Reply(ACCESS_DENIED);
00095 else if (u2)
00096 {
00097 AccessGroup u2_access = ci->AccessFor(u2);
00098
00099 if (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access && !source.HasPriv("chanserv/kick"))
00100 source.Reply(ACCESS_DENIED);
00101
00102
00103
00104
00105 else if (ci->c->MatchesList(u2, "EXCEPT"))
00106 source.Reply(CHAN_EXCEPTED, u2->nick.c_str(), ci->name.c_str());
00107 else if (u2->IsProtected())
00108 source.Reply(ACCESS_DENIED);
00109 else
00110 {
00111 Anope::string mask = ci->GetIdealBan(u2);
00112
00113 bool override = !u_access.HasPriv("BAN") || (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access);
00114 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << mask;
00115
00116 if (!c->HasMode("BAN", mask))
00117 {
00118 c->SetMode(NULL, "BAN", mask);
00119 if (ban_time)
00120 {
00121 new TempBan(ban_time, c, mask);
00122 source.Reply(_("Ban on \002%s\002 expires in %s."), mask.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
00123 }
00124 }
00125
00126
00127 if (!c->FindUser(u2))
00128 return;
00129
00130 if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !source.AccessFor(ci).HasPriv("SIGNKICK")))
00131 c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), source.GetNick().c_str());
00132 else
00133 c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
00134 }
00135 }
00136 else if (u_access.HasPriv("FOUNDER"))
00137 {
00138 Log(LOG_COMMAND, source, this, ci) << "for " << target;
00139
00140 if (!c->HasMode("BAN", target))
00141 {
00142 c->SetMode(NULL, "BAN", target);
00143 if (ban_time)
00144 {
00145 new TempBan(ban_time, c, target);
00146 source.Reply(_("Ban on \002%s\002 expires in %s."), target.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
00147 }
00148 }
00149
00150 int matched = 0, kicked = 0;
00151 for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end;)
00152 {
00153 ChanUserContainer *uc = *it++;
00154
00155 if (Anope::Match(uc->user->nick, target) || Anope::Match(uc->user->GetDisplayedMask(), target))
00156 {
00157 ++matched;
00158
00159 AccessGroup u2_access = ci->AccessFor(uc->user);
00160
00161 if (u != uc->user && ci->HasExt("PEACE") && u2_access >= u_access)
00162 continue;
00163 else if (ci->c->MatchesList(uc->user, "EXCEPT"))
00164 continue;
00165 else if (uc->user->IsProtected())
00166 continue;
00167
00168 ++kicked;
00169 if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
00170 c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), target.c_str(), source.GetNick().c_str());
00171 else
00172 c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), target.c_str());
00173 }
00174 }
00175
00176 if (matched)
00177 source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, target.c_str(), c->name.c_str());
00178 else
00179 source.Reply(_("No users on %s match %s."), c->name.c_str(), target.c_str());
00180 }
00181 else
00182 source.Reply(NICK_X_NOT_IN_USE, target.c_str());
00183 }
00184
00185 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00186 {
00187 this->SendSyntax(source);
00188 source.Reply(" ");
00189 source.Reply(_("Bans a given nick or mask on a channel. An optional expiry may\n"
00190 "be given to cause services to remove the ban after a set amount\n"
00191 "of time.\n"
00192 " \n"
00193 "By default, limited to AOPs or those with level 5 access\n"
00194 "and above on the channel. Channel founders may ban masks."));
00195 return true;
00196 }
00197 };
00198
00199 class CSBan : public Module
00200 {
00201 CommandCSBan commandcsban;
00202
00203 public:
00204 CSBan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandcsban(this)
00205 {
00206 this->SetAuthor("Anope");
00207 me = this;
00208 }
00209 };
00210
00211 MODULE_INIT(CSBan)