summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2008-02-14 18:24:28 +0000
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2008-02-14 18:24:28 +0000
commit91a8894d5d4637ad6aea33ad77af67445d548732 (patch)
tree1900d40f30f8e871502710bdd7950aaa35bd9531
parent1f9b2453f25eaf74d2c71c427c45d529694e4e34 (diff)
New mode stuff. Note, the framework is now here so that every mode handler can state what prefix is required to execute it. For example: You can say that mode +j needs '%' to execute it, so that
then only a halfop or above can use mode +j. If you put '@' in this member value, only ops and above can use it. The OnRawMode can return ACR_ALLOW on a case by case basis to totally override this check against the prefix char. If you return ACR_DEFAULT the check goes ahead. git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@8935 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--include/mode.h11
-rw-r--r--src/mode.cpp69
2 files changed, 61 insertions, 19 deletions
diff --git a/include/mode.h b/include/mode.h
index 716071176..8faea3491 100644
--- a/include/mode.h
+++ b/include/mode.h
@@ -134,6 +134,11 @@ class CoreExport ModeHandler : public Extensible
*/
unsigned int count;
+ /** The prefix char needed on channel to use this mode,
+ * only checked for channel modes
+ */
+ char prefixneeded;
+
public:
/**
* The constructor for ModeHandler initalizes the mode handler.
@@ -151,7 +156,7 @@ class CoreExport ModeHandler : public Extensible
* and the rank values OP_VALUE, HALFOP_VALUE and VOICE_VALUE respectively. Any prefixes you define should have unique values proportional
* to these three defaults or proportional to another mode in a module you depend on. See src/cmode_o.cpp as an example.
*/
- ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix = 0);
+ ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix = 0, char prefixrequired = '%');
/**
* The default destructor does nothing
*/
@@ -277,6 +282,10 @@ class CoreExport ModeHandler : public Extensible
* @param channel The channel which the server wants to remove your mode from
*/
virtual void RemoveMode(Channel* channel);
+
+ char GetNeededPrefix();
+
+ void SetNeededPrefix(char needsprefix);
};
/**
diff --git a/src/mode.cpp b/src/mode.cpp
index 4d0a812e8..3fad8627d 100644
--- a/src/mode.cpp
+++ b/src/mode.cpp
@@ -54,8 +54,8 @@
/* +n (notice mask - our implementation of snomasks) */
#include "modes/umode_n.h"
-ModeHandler::ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix)
- : ServerInstance(Instance), mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), oper(operonly), prefix(mprefix), count(0)
+ModeHandler::ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix, char prefixrequired)
+ : ServerInstance(Instance), mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), oper(operonly), prefix(mprefix), count(0), prefixneeded(prefixrequired)
{
}
@@ -68,6 +68,16 @@ bool ModeHandler::IsListMode()
return list;
}
+char ModeHandler::GetNeededPrefix()
+{
+ return prefixneeded;
+}
+
+void ModeHandler::SetNeededPrefix(char needsprefix)
+{
+ prefixneeded = needsprefix;
+}
+
unsigned int ModeHandler::GetPrefixRank()
{
return 0;
@@ -386,28 +396,13 @@ void ModeParser::Process(const char** parameters, int pcnt, User *user, bool ser
* (e.g. are they a (half)op?
*/
- if ((IS_LOCAL(user)) && (targetchannel->GetStatus(user) < STATUS_HOP))
+ if ((IS_LOCAL(user)) && (!ServerInstance->ULine(user->server)) && (!servermode))
{
/* We don't have halfop */
int MOD_RESULT = 0;
FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE));
if (MOD_RESULT == ACR_DENY)
return;
-
- if (MOD_RESULT == ACR_DEFAULT)
- {
- /* Are we a uline or is it a servermode? */
- if ((!ServerInstance->ULine(user->server)) && (!servermode))
- {
- /* Not enough permission:
- * NOT a uline and NOT a servermode,
- * OR, NOT halfop or above.
- */
- user->WriteServ("482 %s %s :You're not a channel %soperator",user->nick, targetchannel->name,
- ServerInstance->Config->AllowHalfop ? "(half)" : "");
- return;
- }
- }
}
}
else if (targetuser)
@@ -509,11 +504,49 @@ void ModeParser::Process(const char** parameters, int pcnt, User *user, bool ser
continue;
}
+
int MOD_RESULT = 0;
FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, modechar, parameter, adding, 1));
if (MOD_RESULT == ACR_DENY)
continue;
+ if (MOD_RESULT != ACR_ALLOW)
+ {
+ /* Check access to this mode character */
+ if ((type == MODETYPE_CHANNEL) && (modehandlers[handler_id]->GetNeededPrefix()))
+ {
+ bool allowed = false;
+ char needed = modehandlers[handler_id]->GetNeededPrefix();
+ ModeHandler* prefixmode = FindPrefix(needed);
+ if (prefixmode)
+ {
+ unsigned int neededrank = prefixmode->GetPrefixRank();
+
+ /* Compare our rank on the channel against the rank of the required prefix,
+ * allow if >= ours
+ */
+
+ std::string modestring = ModeString(user, targetchannel);
+ for (std::string::iterator v = modestring.begin(); v != modestring.end(); ++v)
+ {
+ ModeHandler* ourmode = FindPrefix(*v);
+ if (ourmode && (ourmode->GetPrefixRank() >= neededrank))
+ {
+ /* Yay, allowed */
+ allowed = true;
+ break;
+ }
+ }
+ }
+
+ if (!allowed)
+ {
+ user->WriteServ("482 %s %s :You require channel privilege '%c' or above to execute channel mode '%c'",user->nick,
+ targetchannel->name, needed, modechar);
+ }
+ }
+ }
+
bool had_parameter = !parameter.empty();
for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)