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> ¶ms) 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)