cs_enforce.cpp

Go to the documentation of this file.
00001 /* ChanServ core functions
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Original Coder: GeniusDex <geniusdex@anope.org>
00007  *
00008  * Please read COPYING and README for further details.
00009  *
00010  * Send any bug reports to the Anope Coder, as he will be able
00011  * to deal with it best.
00012  */
00013 
00014 #include "module.h"
00015 
00016 class CommandCSEnforce : public Command
00017 {
00018  private:
00019         void DoSecureOps(CommandSource &source, ChannelInfo *ci)
00020         {
00021                 bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
00022                 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce secureops";
00023 
00024                 /* Dirty hack to allow Channel::SetCorrectModes to work ok.
00025                  * We pretend like SECUREOPS is on so it doesn't ignore that
00026                  * part of the code. This way we can enforce SECUREOPS even
00027                  * if it's off.
00028                  */
00029                 bool hadsecureops = ci->HasExt("SECUREOPS");
00030                 ci->ExtendMetadata("SECUREOPS");
00031 
00032                 for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
00033                 {
00034                         ChanUserContainer *uc = *it;
00035 
00036                         ci->c->SetCorrectModes(uc->user, false, false);
00037                 }
00038 
00039                 if (!hadsecureops)
00040                         ci->Shrink("SECUREOPS");
00041 
00042                 source.Reply(_("Secureops enforced on %s."), ci->name.c_str());
00043         }
00044 
00045         void DoRestricted(CommandSource &source, ChannelInfo *ci)
00046         {
00047                 bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
00048                 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce restricted";
00049 
00050                 std::vector<User *> users;
00051                 for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
00052                 {
00053                         ChanUserContainer *uc = *it;
00054                         User *user = uc->user;
00055 
00056                         if (user->IsProtected())
00057                                 continue;
00058 
00059                         if (ci->AccessFor(user).empty())
00060                                 users.push_back(user);
00061                 }
00062 
00063                 for (unsigned i = 0; i < users.size(); ++i)
00064                 {       
00065                         User *user = users[i];
00066 
00067                         Anope::string mask = ci->GetIdealBan(user);
00068                         Anope::string reason = Language::Translate(user, _("RESTRICTED enforced by ")) + source.GetNick();
00069                         ci->c->SetMode(NULL, "BAN", mask);
00070                         ci->c->Kick(NULL, user, "%s", reason.c_str());
00071                 }
00072 
00073                 source.Reply(_("Restricted enforced on %s."), ci->name.c_str());
00074         }
00075 
00076         void DoRegOnly(CommandSource &source, ChannelInfo *ci)
00077         {
00078                 bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
00079                 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce registered only";
00080 
00081                 std::vector<User *> users;
00082                 for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
00083                 {
00084                         ChanUserContainer *uc = *it;
00085                         User *user = uc->user;
00086 
00087                         if (user->IsProtected())
00088                                 continue;
00089 
00090                         if (!user->IsIdentified())
00091                                 users.push_back(user);
00092                 }
00093 
00094                 for (unsigned i = 0; i < users.size(); ++i)
00095                 {
00096                         User *user = users[i];
00097 
00098                         Anope::string mask = ci->GetIdealBan(user);
00099                         Anope::string reason = Language::Translate(user, _("REGONLY enforced by ")) + source.GetNick();
00100                         if (!ci->c->HasMode("REGISTEREDONLY"))
00101                                 ci->c->SetMode(NULL, "BAN", mask);
00102                         ci->c->Kick(NULL, user, "%s", reason.c_str());
00103                 }
00104 
00105                 source.Reply(_("Registered only enforced on %s."), ci->name.c_str());
00106         }
00107 
00108         void DoSSLOnly(CommandSource &source, ChannelInfo *ci)
00109         {
00110                 bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
00111                 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce SSL only";
00112 
00113                 std::vector<User *> users;
00114                 for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
00115                 {
00116                         ChanUserContainer *uc = *it;
00117                         User *user = uc->user;
00118 
00119                         if (user->IsProtected())
00120                                 continue;
00121 
00122                         if (!user->HasMode("SSL"))
00123                                 users.push_back(user);
00124                 }
00125 
00126                 for (unsigned i = 0; i < users.size(); ++i)
00127                 {
00128                         User *user = users[i];
00129 
00130                         Anope::string mask = ci->GetIdealBan(user);
00131                         Anope::string reason = Language::Translate(user, _("SSLONLY enforced by ")) + source.GetNick();
00132                         if (!ci->c->HasMode("SSL"))
00133                                 ci->c->SetMode(NULL, "BAN", mask);
00134                         ci->c->Kick(NULL, user, "%s", reason.c_str());
00135                 }
00136 
00137                 source.Reply(_("SSL only enforced on %s."), ci->name.c_str());
00138         }
00139 
00140         void DoBans(CommandSource &source, ChannelInfo *ci)
00141         {
00142                 bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
00143                 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce bans";
00144 
00145                 std::vector<User *> users;
00146                 for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
00147                 {
00148                         ChanUserContainer *uc = *it;
00149                         User *user = uc->user;
00150 
00151                         if (user->IsProtected())
00152                                 continue;
00153 
00154                         if (ci->c->MatchesList(user, "BAN") && !ci->c->MatchesList(user, "EXCEPT"))
00155                                 users.push_back(user);
00156                 }
00157 
00158                 for (unsigned i = 0; i < users.size(); ++i)
00159                 {
00160                         User *user = users[i];
00161         
00162                         Anope::string reason = Language::Translate(user, _("BANS enforced by ")) + source.GetNick();
00163                         ci->c->Kick(NULL, user, "%s", reason.c_str());
00164                 }
00165 
00166                 source.Reply(_("Bans enforced on %s."), ci->name.c_str());
00167         }
00168 
00169         void DoLimit(CommandSource &source, ChannelInfo *ci)
00170         {
00171                 bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
00172                 Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce limit";
00173 
00174                 Anope::string l_str;
00175                 if (!ci->c->GetParam("LIMIT", l_str))
00176                 {
00177                         source.Reply(_("No limit is set on %s."), ci->name.c_str());
00178                         return;
00179                 }
00180 
00181                 int l;
00182                 try
00183                 {
00184                         l = convertTo<int>(l_str);
00185                         if (l < 0)
00186                                 throw ConvertException();
00187                 }
00188                 catch (const ConvertException &)
00189                 {
00190                         source.Reply(_("The limit on %s is not valid."), ci->name.c_str());
00191                         return;
00192                 }
00193 
00194                 std::vector<User *> users;
00195                 /* The newer users are at the end of the list, so kick users starting from the end */
00196                 for (Channel::ChanUserList::reverse_iterator it = ci->c->users.rbegin(), it_end = ci->c->users.rend(); it != it_end; ++it)
00197                 {
00198                         ChanUserContainer *uc = *it;
00199                         User *user = uc->user;
00200 
00201                         if (user->IsProtected())
00202                                 continue;
00203 
00204                         if (!ci->AccessFor(user).empty())
00205                                 continue;
00206 
00207                         if (ci->c->users.size() - users.size() <= static_cast<unsigned>(l))
00208                                 continue;
00209 
00210                         users.push_back(user);
00211                 }
00212 
00213                 for (unsigned i = 0; i < users.size(); ++i)
00214                 {
00215                         User *user = users[i];
00216         
00217                         Anope::string reason = Language::Translate(user, _("LIMIT enforced by ")) + source.GetNick();
00218                         ci->c->Kick(NULL, user, "%s", reason.c_str());
00219                 }
00220 
00221                 source.Reply(_("LIMIT enforced on %s, %d users removed."), ci->name.c_str(), users.size());
00222         }
00223 
00224  public:
00225         CommandCSEnforce(Module *creator) : Command(creator, "chanserv/enforce", 2, 2)
00226         {
00227                 this->SetDesc(_("Enforce various channel modes and set options"));
00228                 this->SetSyntax(_("\037channel\037 \037what\037"));
00229         }
00230 
00231         void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
00232         {
00233                 const Anope::string &what = params.size() > 1 ? params[1] : "";
00234 
00235                 ChannelInfo *ci = ChannelInfo::Find(params[0]);
00236 
00237                 if (!ci)
00238                         source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
00239                 else if (!ci->c)
00240                         source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str());
00241                 else if (!source.AccessFor(ci).HasPriv("AKICK") && !source.HasPriv("chanserv/access/modify"))
00242                         source.Reply(ACCESS_DENIED);
00243                 else if (what.equals_ci("SECUREOPS"))
00244                         this->DoSecureOps(source, ci);
00245                 else if (what.equals_ci("RESTRICTED"))
00246                         this->DoRestricted(source, ci);
00247                 else if (what.equals_ci("REGONLY"))
00248                         this->DoRegOnly(source, ci);
00249                 else if (what.equals_ci("SSLONLY"))
00250                         this->DoSSLOnly(source, ci);
00251                 else if (what.equals_ci("BANS"))
00252                         this->DoBans(source, ci);
00253                 else if (what.equals_ci("LIMIT"))
00254                         this->DoLimit(source, ci);
00255                 else
00256                         this->OnSyntaxError(source, "");
00257         }
00258 
00259         bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00260         {
00261                 this->SendSyntax(source);
00262                 source.Reply(" ");
00263                 source.Reply(_("Enforce various channel modes and set options. The \037channel\037\n"
00264                         "option indicates what channel to enforce the modes and options\n"
00265                         "on. The \037what\037 option indicates what modes and options to\n"
00266                         "enforce, and can be any of \002SECUREOPS\002, \002RESTRICTED\002, \002REGONLY\002, \002SSLONLY\002,\n"
00267                         "\002BANS\002, or \002LIMIT\002.\n"
00268                         " \n"
00269                         "Use \002SECUREOPS\002 to enforce the SECUREOPS option, even if it is not\n"
00270                         "enabled. Use \002RESTRICTED\002 to enfore the RESTRICTED option, also\n"
00271                         "if it's not enabled. Use \002REGONLY\002 to kick all unregistered users\n"
00272                         "from the channel. Use \002SSLONLY\002 to kick all users not using a secure\n"
00273                         "connection from the channel. \002BANS\002 will enforce bans on the channel by\n"
00274                         "kicking users affected by them, and \002LIMIT\002 will kick users until the\n"
00275                         "user count drops below the channel limit, if one is set."));
00276                 return true;
00277         }
00278 };
00279 
00280 class CSEnforce : public Module
00281 {
00282         CommandCSEnforce commandcsenforce;
00283 
00284  public:
00285         CSEnforce(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
00286                 commandcsenforce(this)
00287         {
00288                 this->SetAuthor("Anope");
00289 
00290         }
00291 };
00292 
00293 MODULE_INIT(CSEnforce)