+ ExemptChanOps(Module* Creator)
+ : ListModeBase(Creator, "exemptchanops", 'X', "End of channel exemptchanops list", RPL_EXEMPTIONLIST, RPL_ENDOFEXEMPTIONLIST, false)
+ {
+ syntax = "<restriction>:<prefix>";
+ }
+
+ static PrefixMode* FindMode(const std::string& mode)
+ {
+ if (mode.length() == 1)
+ return ServerInstance->Modes->FindPrefixMode(mode[0]);
+
+ ModeHandler* mh = ServerInstance->Modes->FindMode(mode, MODETYPE_CHANNEL);
+ return mh ? mh->IsPrefixMode() : NULL;
+ }
+
+ static bool ParseEntry(const std::string& entry, std::string& restriction, std::string& prefix)
+ {
+ // The entry must be in the format <restriction>:<prefix>.
+ std::string::size_type colon = entry.find(':');
+ if (colon == std::string::npos || colon == entry.length()-1)
+ return false;
+
+ restriction.assign(entry, 0, colon);
+ prefix.assign(entry, colon + 1, std::string::npos);
+ return true;
+ }
+
+ ModResult AccessCheck(User* source, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE
+ {
+ std::string restriction;
+ std::string prefix;
+ if (!ParseEntry(parameter, restriction, prefix))
+ return MOD_RES_PASSTHRU;
+
+ PrefixMode* pm = FindMode(prefix);
+ if (!pm)
+ return MOD_RES_PASSTHRU;
+
+ if (channel->GetPrefixValue(source) >= pm->GetLevelRequired(adding))
+ return MOD_RES_PASSTHRU;
+
+ source->WriteNumeric(ERR_CHANOPRIVSNEEDED, channel->name, InspIRCd::Format("You must be able to %s mode %c (%s) to %s a restriction containing it",
+ adding ? "set" : "unset", pm->GetModeChar(), pm->name.c_str(), adding ? "add" : "remove"));
+ return MOD_RES_DENY;
+ }