anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

cs_enforce.cpp (9129B)

      1 /* ChanServ core functions
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Original Coder: GeniusDex <geniusdex@anope.org>
      7  *
      8  * Please read COPYING and README for further details.
      9  *
     10  * Send any bug reports to the Anope Coder, as he will be able
     11  * to deal with it best.
     12  */
     13 
     14 #include "module.h"
     15 
     16 class CommandCSEnforce : public Command
     17 {
     18  private:
     19 	void DoSecureOps(CommandSource &source, ChannelInfo *ci)
     20 	{
     21 		bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
     22 		Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce secureops";
     23 
     24 		/* Dirty hack to allow Channel::SetCorrectModes to work ok.
     25 		 * We pretend like SECUREOPS is on so it doesn't ignore that
     26 		 * part of the code. This way we can enforce SECUREOPS even
     27 		 * if it's off.
     28 		 */
     29 		bool hadsecureops = ci->HasExt("SECUREOPS");
     30 		ci->Extend<bool>("SECUREOPS");
     31 
     32 		for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
     33 		{
     34 			ChanUserContainer *uc = it->second;
     35 
     36 			ci->c->SetCorrectModes(uc->user, false);
     37 		}
     38 
     39 		if (!hadsecureops)
     40 			ci->Shrink<bool>("SECUREOPS");
     41 
     42 		source.Reply(_("Secureops enforced on %s."), ci->name.c_str());
     43 	}
     44 
     45 	void DoRestricted(CommandSource &source, ChannelInfo *ci)
     46 	{
     47 		bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
     48 		Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce restricted";
     49 
     50 		std::vector<User *> users;
     51 		for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
     52 		{
     53 			ChanUserContainer *uc = it->second;
     54 			User *user = uc->user;
     55 
     56 			if (user->IsProtected())
     57 				continue;
     58 
     59 			if (ci->AccessFor(user).empty())
     60 				users.push_back(user);
     61 		}
     62 
     63 		for (unsigned i = 0; i < users.size(); ++i)
     64 		{
     65 			User *user = users[i];
     66 
     67 			Anope::string mask = ci->GetIdealBan(user);
     68 			Anope::string reason = Language::Translate(user, _("RESTRICTED enforced by ")) + source.GetNick();
     69 			ci->c->SetMode(NULL, "BAN", mask);
     70 			ci->c->Kick(NULL, user, "%s", reason.c_str());
     71 		}
     72 
     73 		source.Reply(_("Restricted enforced on %s."), ci->name.c_str());
     74 	}
     75 
     76 	void DoRegOnly(CommandSource &source, ChannelInfo *ci)
     77 	{
     78 		bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
     79 		Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce registered only";
     80 
     81 		std::vector<User *> users;
     82 		for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
     83 		{
     84 			ChanUserContainer *uc = it->second;
     85 			User *user = uc->user;
     86 
     87 			if (user->IsProtected())
     88 				continue;
     89 
     90 			if (!user->IsIdentified())
     91 				users.push_back(user);
     92 		}
     93 
     94 		for (unsigned i = 0; i < users.size(); ++i)
     95 		{
     96 			User *user = users[i];
     97 
     98 			Anope::string mask = ci->GetIdealBan(user);
     99 			Anope::string reason = Language::Translate(user, _("REGONLY enforced by ")) + source.GetNick();
    100 			if (!ci->c->HasMode("REGISTEREDONLY"))
    101 				ci->c->SetMode(NULL, "BAN", mask);
    102 			ci->c->Kick(NULL, user, "%s", reason.c_str());
    103 		}
    104 
    105 		source.Reply(_("Registered only enforced on %s."), ci->name.c_str());
    106 	}
    107 
    108 	void DoSSLOnly(CommandSource &source, ChannelInfo *ci)
    109 	{
    110 		bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
    111 		Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce SSL only";
    112 
    113 		std::vector<User *> users;
    114 		for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
    115 		{
    116 			ChanUserContainer *uc = it->second;
    117 			User *user = uc->user;
    118 
    119 			if (user->IsProtected())
    120 				continue;
    121 
    122 			if (!user->HasMode("SSL") && !user->HasExt("ssl"))
    123 				users.push_back(user);
    124 		}
    125 
    126 		for (unsigned i = 0; i < users.size(); ++i)
    127 		{
    128 			User *user = users[i];
    129 
    130 			Anope::string mask = ci->GetIdealBan(user);
    131 			Anope::string reason = Language::Translate(user, _("SSLONLY enforced by ")) + source.GetNick();
    132 			if (!ci->c->HasMode("SSL"))
    133 				ci->c->SetMode(NULL, "BAN", mask);
    134 			ci->c->Kick(NULL, user, "%s", reason.c_str());
    135 		}
    136 
    137 		source.Reply(_("SSL only enforced on %s."), ci->name.c_str());
    138 	}
    139 
    140 	void DoBans(CommandSource &source, ChannelInfo *ci)
    141 	{
    142 		bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
    143 		Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce bans";
    144 
    145 		std::vector<User *> users;
    146 		for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
    147 		{
    148 			ChanUserContainer *uc = it->second;
    149 			User *user = uc->user;
    150 
    151 			if (user->IsProtected())
    152 				continue;
    153 
    154 			if (ci->c->MatchesList(user, "BAN") && !ci->c->MatchesList(user, "EXCEPT"))
    155 				users.push_back(user);
    156 		}
    157 
    158 		for (unsigned i = 0; i < users.size(); ++i)
    159 		{
    160 			User *user = users[i];
    161 
    162 			Anope::string reason = Language::Translate(user, _("BANS enforced by ")) + source.GetNick();
    163 			ci->c->Kick(NULL, user, "%s", reason.c_str());
    164 		}
    165 
    166 		source.Reply(_("Bans enforced on %s."), ci->name.c_str());
    167 	}
    168 
    169 	void DoLimit(CommandSource &source, ChannelInfo *ci)
    170 	{
    171 		bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
    172 		Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce limit";
    173 
    174 		Anope::string l_str;
    175 		if (!ci->c->GetParam("LIMIT", l_str))
    176 		{
    177 			source.Reply(_("No limit is set on %s."), ci->name.c_str());
    178 			return;
    179 		}
    180 
    181 		int l;
    182 		try
    183 		{
    184 			l = convertTo<int>(l_str);
    185 			if (l < 0)
    186 				throw ConvertException();
    187 		}
    188 		catch (const ConvertException &)
    189 		{
    190 			source.Reply(_("The limit on %s is not valid."), ci->name.c_str());
    191 			return;
    192 		}
    193 
    194 		std::vector<User *> users;
    195 		/* The newer users are at the end of the list, so kick users starting from the end */
    196 		for (Channel::ChanUserList::reverse_iterator it = ci->c->users.rbegin(), it_end = ci->c->users.rend(); it != it_end; ++it)
    197 		{
    198 			ChanUserContainer *uc = it->second;
    199 			User *user = uc->user;
    200 
    201 			if (user->IsProtected())
    202 				continue;
    203 
    204 			if (!ci->AccessFor(user).empty())
    205 				continue;
    206 
    207 			if (ci->c->users.size() - users.size() <= static_cast<unsigned>(l))
    208 				continue;
    209 
    210 			users.push_back(user);
    211 		}
    212 
    213 		for (unsigned i = 0; i < users.size(); ++i)
    214 		{
    215 			User *user = users[i];
    216 
    217 			Anope::string reason = Language::Translate(user, _("LIMIT enforced by ")) + source.GetNick();
    218 			ci->c->Kick(NULL, user, "%s", reason.c_str());
    219 		}
    220 
    221 		source.Reply(_("LIMIT enforced on %s, %d users removed."), ci->name.c_str(), users.size());
    222 	}
    223 
    224  public:
    225 	CommandCSEnforce(Module *creator) : Command(creator, "chanserv/enforce", 2, 2)
    226 	{
    227 		this->SetDesc(_("Enforce various channel modes and set options"));
    228 		this->SetSyntax(_("\037channel\037 \037what\037"));
    229 	}
    230 
    231 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
    232 	{
    233 		const Anope::string &what = params.size() > 1 ? params[1] : "";
    234 
    235 		ChannelInfo *ci = ChannelInfo::Find(params[0]);
    236 
    237 		if (!ci)
    238 			source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
    239 		else if (!ci->c)
    240 			source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str());
    241 		else if (!source.AccessFor(ci).HasPriv("AKICK") && !source.HasPriv("chanserv/access/modify"))
    242 			source.Reply(ACCESS_DENIED);
    243 		else if (what.equals_ci("SECUREOPS"))
    244 			this->DoSecureOps(source, ci);
    245 		else if (what.equals_ci("RESTRICTED"))
    246 			this->DoRestricted(source, ci);
    247 		else if (what.equals_ci("REGONLY"))
    248 			this->DoRegOnly(source, ci);
    249 		else if (what.equals_ci("SSLONLY"))
    250 			this->DoSSLOnly(source, ci);
    251 		else if (what.equals_ci("BANS"))
    252 			this->DoBans(source, ci);
    253 		else if (what.equals_ci("LIMIT"))
    254 			this->DoLimit(source, ci);
    255 		else
    256 			this->OnSyntaxError(source, "");
    257 	}
    258 
    259 	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
    260 	{
    261 		this->SendSyntax(source);
    262 		source.Reply(" ");
    263 		source.Reply(_("Enforce various channel modes and set options. The \037channel\037\n"
    264 			"option indicates what channel to enforce the modes and options\n"
    265 			"on. The \037what\037 option indicates what modes and options to\n"
    266 			"enforce, and can be any of \002SECUREOPS\002, \002RESTRICTED\002, \002REGONLY\002, \002SSLONLY\002,\n"
    267 			"\002BANS\002, or \002LIMIT\002.\n"
    268 			" \n"
    269 			"Use \002SECUREOPS\002 to enforce the SECUREOPS option, even if it is not\n"
    270 			"enabled. Use \002RESTRICTED\002 to enforce the RESTRICTED option, also\n"
    271 			"if it's not enabled. Use \002REGONLY\002 to kick all unregistered users\n"
    272 			"from the channel. Use \002SSLONLY\002 to kick all users not using a secure\n"
    273 			"connection from the channel. \002BANS\002 will enforce bans on the channel by\n"
    274 			"kicking users affected by them, and \002LIMIT\002 will kick users until the\n"
    275 			"user count drops below the channel limit, if one is set."));
    276 		return true;
    277 	}
    278 };
    279 
    280 class CSEnforce : public Module
    281 {
    282 	CommandCSEnforce commandcsenforce;
    283 
    284  public:
    285 	CSEnforce(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
    286 		commandcsenforce(this)
    287 	{
    288 
    289 	}
    290 };
    291 
    292 MODULE_INIT(CSEnforce)