From 257bf752fc6b87fa35bfa8cf95fc37730c3d55c6 Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Wed, 18 Oct 2017 03:40:31 +0100 Subject: Add support for setting the unset rank in ModeHandler. --- docs/conf/modules.conf.example | 3 ++- include/builtinmodes.h | 4 ++-- include/mode.h | 19 +++++++++++++------ src/coremods/core_channel/cmd_kick.cpp | 4 ++-- src/mode.cpp | 15 +++++++++++---- src/modules/m_auditorium.cpp | 2 +- src/modules/m_autoop.cpp | 4 ++-- src/modules/m_customprefix.cpp | 3 ++- src/modules/m_delayjoin.cpp | 2 +- src/modules/m_delaymsg.cpp | 2 +- src/modules/m_ojoin.cpp | 2 +- src/modules/m_operprefix.cpp | 2 +- src/modules/m_override.cpp | 2 +- src/modules/m_rmode.cpp | 2 +- 14 files changed, 41 insertions(+), 25 deletions(-) diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 3c3978c28..28450c7e9 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -633,7 +633,8 @@ # rank A numeric rank for this prefix, defining what permissions it gives. # The rank of voice, halfop and op is 10000, 20000, and 30000, # respectively. -# ranktoset The numeric rank required to set/unset this mode. Defaults to rank. +# ranktoset The numeric rank required to set this mode. Defaults to rank. +# ranktounset The numeric rank required to unset this mode. Defaults to ranktoset. # depriv Can you remove the mode from yourself? Defaults to yes. # # diff --git a/include/builtinmodes.h b/include/builtinmodes.h index bfb46823f..922a86f0e 100644 --- a/include/builtinmodes.h +++ b/include/builtinmodes.h @@ -66,7 +66,7 @@ class ModeChannelOp : public PrefixMode ModeChannelOp() : PrefixMode(NULL, "op", 'o', OP_VALUE, '@') { - levelrequired = OP_VALUE; + ranktoset = ranktounset = OP_VALUE; } }; @@ -78,7 +78,7 @@ class ModeChannelVoice : public PrefixMode ModeChannelVoice() : PrefixMode(NULL, "voice", 'v', VOICE_VALUE, '+') { - levelrequired = HALFOP_VALUE; + ranktoset = ranktounset = HALFOP_VALUE; } }; diff --git a/include/mode.h b/include/mode.h index ec293e497..5cfbe4015 100644 --- a/include/mode.h +++ b/include/mode.h @@ -148,10 +148,11 @@ class CoreExport ModeHandler : public ServiceProvider */ const Class type_id; - /** The prefix char needed on channel to use this mode, - * only checked for channel modes - */ - int levelrequired; + /** The prefix rank required to set this mode on channels. */ + unsigned int ranktoset; + + /** The prefix rank required to unset this mode on channels. */ + unsigned int ranktounset; public: /** @@ -320,7 +321,13 @@ class CoreExport ModeHandler : public ServiceProvider */ virtual void RemoveMode(Channel* channel, Modes::ChangeList& changelist); - inline unsigned int GetLevelRequired() const { return levelrequired; } + /** Retrieves the level required to modify this mode. + * @param adding Whether the mode is being added or removed. + */ + inline unsigned int GetLevelRequired(bool adding) const + { + return adding ? ranktoset : ranktounset; + } friend class ModeParser; }; @@ -616,7 +623,7 @@ class CoreExport ModeParser : public fakederef /** If this flag is set then the mode change will be subject to access checks. * For more information see the documentation of the PrefixMode class, - * ModeHandler::levelrequired and ModeHandler::AccessCheck(). + * ModeHandler::ranktoset and ModeHandler::AccessCheck(). * Modules may explicitly allow a mode change regardless of this flag by returning * MOD_RES_ALLOW from the OnPreMode hook. Only affects channel mode changes. */ diff --git a/src/coremods/core_channel/cmd_kick.cpp b/src/coremods/core_channel/cmd_kick.cpp index 7f8a8a329..420ed2b83 100644 --- a/src/coremods/core_channel/cmd_kick.cpp +++ b/src/coremods/core_channel/cmd_kick.cpp @@ -104,8 +104,8 @@ CmdResult CommandKick::Handle (const std::vector& parameters, User for (std::string::size_type i = 0; i < memb->modes.length(); i++) { ModeHandler* mh = ServerInstance->Modes->FindMode(memb->modes[i], MODETYPE_CHANNEL); - if (mh && mh->GetLevelRequired() > req) - req = mh->GetLevelRequired(); + if (mh && mh->GetLevelRequired(true) > req) + req = mh->GetLevelRequired(true); } if (them < req) diff --git a/src/mode.cpp b/src/mode.cpp index fd5e30707..cff625c46 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -27,9 +27,16 @@ #include "builtinmodes.h" ModeHandler::ModeHandler(Module* Creator, const std::string& Name, char modeletter, ParamSpec Params, ModeType type, Class mclass) - : ServiceProvider(Creator, Name, SERVICE_MODE), modeid(ModeParser::MODEID_MAX), - parameters_taken(Params), mode(modeletter), oper(false), - list(false), m_type(type), type_id(mclass), levelrequired(HALFOP_VALUE) + : ServiceProvider(Creator, Name, SERVICE_MODE) + , modeid(ModeParser::MODEID_MAX) + , parameters_taken(Params) + , mode(modeletter) + , oper(false) + , list(false) + , m_type(type) + , type_id(mclass) + , ranktoset(HALFOP_VALUE) + , ranktounset(HALFOP_VALUE) { } @@ -237,7 +244,7 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode return MODEACTION_DENY; if (MOD_RESULT == MOD_RES_PASSTHRU) { - unsigned int neededrank = mh->GetLevelRequired(); + unsigned int neededrank = mh->GetLevelRequired(adding); /* Compare our rank on the channel against the rank of the required prefix, * allow if >= ours. Because mIRC and xchat throw a tizz if the modes shown * in NAMES(X) are not in rank order, we know the most powerful mode is listed diff --git a/src/modules/m_auditorium.cpp b/src/modules/m_auditorium.cpp index 692b3eba4..7acbd2fff 100644 --- a/src/modules/m_auditorium.cpp +++ b/src/modules/m_auditorium.cpp @@ -28,7 +28,7 @@ class AuditoriumMode : public SimpleChannelModeHandler public: AuditoriumMode(Module* Creator) : SimpleChannelModeHandler(Creator, "auditorium", 'u') { - levelrequired = OP_VALUE; + ranktoset = ranktounset = OP_VALUE; } }; diff --git a/src/modules/m_autoop.cpp b/src/modules/m_autoop.cpp index 8c7f300da..257c3647c 100644 --- a/src/modules/m_autoop.cpp +++ b/src/modules/m_autoop.cpp @@ -28,7 +28,7 @@ class AutoOpList : public ListModeBase public: AutoOpList(Module* Creator) : ListModeBase(Creator, "autoop", 'w', "End of Channel Access List", 910, 911, true) { - levelrequired = OP_VALUE; + ranktoset = ranktounset = OP_VALUE; tidy = false; } @@ -61,7 +61,7 @@ class AutoOpList : public ListModeBase std::string dummy; if (mh->AccessCheck(source, channel, dummy, true) == MOD_RES_DENY) return MOD_RES_DENY; - if (mh->GetLevelRequired() > mylevel) + if (mh->GetLevelRequired(true) > mylevel) { source->WriteNumeric(ERR_CHANOPRIVSNEEDED, channel->name, InspIRCd::Format("You must be able to set mode '%s' to include it in an autoop", mid.c_str())); return MOD_RES_DENY; diff --git a/src/modules/m_customprefix.cpp b/src/modules/m_customprefix.cpp index f6f9a84f6..1be9676b5 100644 --- a/src/modules/m_customprefix.cpp +++ b/src/modules/m_customprefix.cpp @@ -33,7 +33,8 @@ class CustomPrefixMode : public PrefixMode prefix = v.c_str()[0]; v = tag->getString("letter"); mode = v.c_str()[0]; - levelrequired = tag->getInt("ranktoset", prefixrank); + ranktoset = tag->getInt("ranktoset", prefixrank, prefixrank, UINT_MAX); + ranktounset = tag->getInt("ranktounset", ranktoset, ranktoset, UINT_MAX); depriv = tag->getBool("depriv", true); } diff --git a/src/modules/m_delayjoin.cpp b/src/modules/m_delayjoin.cpp index e864a8289..6d1251345 100644 --- a/src/modules/m_delayjoin.cpp +++ b/src/modules/m_delayjoin.cpp @@ -28,7 +28,7 @@ class DelayJoinMode : public ModeHandler public: DelayJoinMode(Module* Parent) : ModeHandler(Parent, "delayjoin", 'D', PARAM_NONE, MODETYPE_CHANNEL) { - levelrequired = OP_VALUE; + ranktoset = ranktounset = OP_VALUE; } ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding); diff --git a/src/modules/m_delaymsg.cpp b/src/modules/m_delaymsg.cpp index 1ad41cc57..3471c7fd2 100644 --- a/src/modules/m_delaymsg.cpp +++ b/src/modules/m_delaymsg.cpp @@ -27,7 +27,7 @@ class DelayMsgMode : public ParamMode : ParamMode(Parent, "delaymsg", 'd') , jointime("delaymsg", ExtensionItem::EXT_MEMBERSHIP, Parent) { - levelrequired = OP_VALUE; + ranktoset = ranktounset = OP_VALUE; } bool ResolveModeConflict(std::string &their_param, const std::string &our_param, Channel*) diff --git a/src/modules/m_ojoin.cpp b/src/modules/m_ojoin.cpp index 76e66bdc2..a96e47bc6 100644 --- a/src/modules/m_ojoin.cpp +++ b/src/modules/m_ojoin.cpp @@ -89,7 +89,7 @@ class NetworkPrefix : public PrefixMode NetworkPrefix(Module* parent, char NPrefix) : PrefixMode(parent, "official-join", 'Y', NETWORK_VALUE, NPrefix) { - levelrequired = INT_MAX; + ranktoset = ranktounset = UINT_MAX; } ModResult AccessCheck(User* source, Channel* channel, std::string ¶meter, bool adding) diff --git a/src/modules/m_operprefix.cpp b/src/modules/m_operprefix.cpp index 73155b394..8b68dbe60 100644 --- a/src/modules/m_operprefix.cpp +++ b/src/modules/m_operprefix.cpp @@ -33,7 +33,7 @@ class OperPrefixMode : public PrefixMode : PrefixMode(Creator, "operprefix", 'y', OPERPREFIX_VALUE) { prefix = ServerInstance->Config->ConfValue("operprefix")->getString("prefix", "!", 1, 1)[0]; - levelrequired = INT_MAX; + ranktoset = ranktounset = UINT_MAX; } }; diff --git a/src/modules/m_override.cpp b/src/modules/m_override.cpp index fd09dd6ec..2094d3c96 100644 --- a/src/modules/m_override.cpp +++ b/src/modules/m_override.cpp @@ -42,7 +42,7 @@ class ModuleOverride : public Module for (Modes::ChangeList::List::const_iterator i = list.begin(); i != list.end(); ++i) { ModeHandler* mh = i->mh; - if (mh->GetLevelRequired() > userlevel) + if (mh->GetLevelRequired(i->adding) > userlevel) return true; } return false; diff --git a/src/modules/m_rmode.cpp b/src/modules/m_rmode.cpp index 37c6e62ff..7c15247be 100644 --- a/src/modules/m_rmode.cpp +++ b/src/modules/m_rmode.cpp @@ -50,7 +50,7 @@ class CommandRMode : public Command return CMD_FAILURE; } - if (chan->GetPrefixValue(user) < mh->GetLevelRequired()) + if (chan->GetPrefixValue(user) < mh->GetLevelRequired(false)) { user->WriteNotice("You do not have access to unset " + ConvToStr(modeletter) + " on " + chan->name + "."); return CMD_FAILURE; -- cgit v1.2.3