summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/builtinmodes.h10
-rw-r--r--include/channels.h11
-rw-r--r--include/membership.h10
-rw-r--r--include/mode.h56
-rw-r--r--src/channels.cpp25
-rw-r--r--src/mode.cpp56
-rw-r--r--src/modes/cmode_o.cpp9
-rw-r--r--src/modes/cmode_v.cpp9
-rw-r--r--src/modules/m_customprefix.cpp12
-rw-r--r--src/modules/m_ojoin.cpp12
-rw-r--r--src/modules/m_operprefix.cpp22
11 files changed, 107 insertions, 125 deletions
diff --git a/include/builtinmodes.h b/include/builtinmodes.h
index b1e5c3ccd..ce73a7817 100644
--- a/include/builtinmodes.h
+++ b/include/builtinmodes.h
@@ -86,13 +86,10 @@ class ModeChannelNoExternal : public SimpleChannelModeHandler
/** Channel mode +o
*/
-class ModeChannelOp : public ModeHandler
+class ModeChannelOp : public PrefixMode
{
- private:
public:
ModeChannelOp();
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
- unsigned int GetPrefixRank();
};
/** Channel mode +p
@@ -127,13 +124,10 @@ class ModeChannelTopicOps : public SimpleChannelModeHandler
/** Channel mode +v
*/
-class ModeChannelVoice : public ModeHandler
+class ModeChannelVoice : public PrefixMode
{
- private:
public:
ModeChannelVoice();
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
- unsigned int GetPrefixRank();
};
/** User mode +i
diff --git a/include/channels.h b/include/channels.h
index 0c7a3a20c..4f61e15e4 100644
--- a/include/channels.h
+++ b/include/channels.h
@@ -338,17 +338,6 @@ class CoreExport Channel : public Extensible, public InviteBase
*/
unsigned int GetPrefixValue(User* user);
- /** Add a prefix character to a user.
- * Only the core should call this method, usually from
- * within the mode parser or when the first user joins
- * the channel (to grant ops to them)
- * @param user The user to associate the privilage with
- * @param prefix The prefix character to associate
- * @param adding True if adding the prefix, false when removing
- * @return True if a change was made
- */
- bool SetPrefix(User* user, char prefix, bool adding);
-
/** Check if a user is banned on this channel
* @param user A user to check against the banlist
* @returns True if the user given is banned
diff --git a/include/membership.h b/include/membership.h
index 5850e0ae0..7074566ae 100644
--- a/include/membership.h
+++ b/include/membership.h
@@ -32,6 +32,16 @@ class CoreExport Membership : public Extensible
return modes.find(m) != std::string::npos;
}
unsigned int getRank();
+
+ /** Add a prefix character to a user.
+ * Only the core should call this method, usually from
+ * within the mode parser or when the first user joins
+ * the channel (to grant the default privs to them)
+ * @param mh The mode handler of the prefix mode to associate
+ * @param adding True if adding the prefix, false when removing
+ * @return True if a change was made
+ */
+ bool SetPrefix(ModeHandler* mh, bool adding);
};
class CoreExport InviteBase
diff --git a/include/mode.h b/include/mode.h
index 18fed8b0a..8c3e875f3 100644
--- a/include/mode.h
+++ b/include/mode.h
@@ -103,16 +103,10 @@ class CoreExport ModeHandler : public ServiceProvider
public:
enum Class
{
+ MC_PREFIX,
MC_OTHER
};
- /**
- * Removes this prefix mode from all users on the given channel
- * @param channel The channel which the server wants to remove your mode from
- * @param stack The mode stack to add the mode change to
- */
- void RemovePrefixMode(Channel* chan, irc::modestacker& stack);
-
protected:
/**
* The mode parameter translation type
@@ -312,6 +306,54 @@ class CoreExport ModeHandler : public ServiceProvider
inline unsigned int GetLevelRequired() const { return levelrequired; }
};
+/**
+ * Prefix modes are channel modes that grant a specific rank to members having prefix mode set.
+ * They require a parameter when setting and unsetting; the parameter is always a member of the channel.
+ * A prefix mode may be set on any number of members on a channel, but for a given member a given prefix
+ * mode is either set or not set, in other words members cannot have the same prefix mode set more than once.
+ *
+ * A rank of a member is defined as the rank given by the 'strongest' prefix mode that member has.
+ * Other parts of the IRCd use this rank to determine whether a channel action is allowable for a user or not.
+ * The rank of a prefix mode is constant, i.e. the same rank value is given to all users having that prefix mode set.
+ *
+ * Note that it is possible that the same action requires a different rank on a different channel;
+ * for example changing the topic on a channel having +t set requires a rank that is >= than the rank of a halfop,
+ * but there is no such restriction when +t isn't set.
+ */
+class PrefixMode : public ModeHandler
+{
+ public:
+ /**
+ * Constructor
+ * @param Creator The module creating this mode
+ * @param Name The user-friendly one word name of the prefix mode, e.g.: "op", "voice"
+ * @param ModeLetter The mode letter of this mode
+ */
+ PrefixMode(Module* Creator, const std::string& Name, char ModeLetter);
+
+ /**
+ * Handles setting and unsetting the prefix mode.
+ * Finds the given member of the given channel, if it's not found an error message is sent to 'source'
+ * and MODEACTION_DENY is returned. Otherwise the mode change is attempted.
+ * @param source Source of the mode change, an error message is sent to this user if the target is not found
+ * @param dest Unused
+ * @param channel The channel the mode change is happening on
+ * @param param The nickname or uuid of the target user
+ * @param adding True when the mode is being set, false when it is being unset
+ * @return MODEACTION_ALLOW if the change happened, MODEACTION_DENY if no change happened
+ * The latter occurs either when the member cannot be found or when the member already has this prefix set
+ * (when setting) or doesn't have this prefix set (when unsetting).
+ */
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& param, bool adding);
+
+ /**
+ * Removes this prefix mode from all users on the given channel
+ * @param chan The channel which the server wants to remove your mode from
+ * @param stack The mode stack to add the mode change to
+ */
+ void RemoveMode(Channel* chan, irc::modestacker& stack);
+};
+
/** A prebuilt mode handler which handles a simple user mode, e.g. no parameters, usable by any user, with no extra
* behaviour to the mode beyond the basic setting and unsetting of the mode, not allowing the mode to be set if it
* is already set and not allowing it to be unset if it is already unset.
diff --git a/src/channels.cpp b/src/channels.cpp
index afc569909..91aec6fa5 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -343,9 +343,8 @@ void Channel::ForceJoin(User* user, const std::string* privs, bool bursting, boo
if (mh && mh->GetPrefixRank())
{
std::string nick = user->nick;
- /* Set, and make sure that the mode handler knows this mode was now set */
- this->SetPrefix(user, mh->GetModeChar(), true);
- mh->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, this, nick, true);
+ // Set the mode on the user
+ mh->OnModeChange(ServerInstance->FakeClient, NULL, this, nick, true);
}
}
}
@@ -792,29 +791,23 @@ unsigned int Channel::GetPrefixValue(User* user)
return m->second->getRank();
}
-bool Channel::SetPrefix(User* user, char prefix, bool adding)
+bool Membership::SetPrefix(ModeHandler* delta_mh, bool adding)
{
- ModeHandler* delta_mh = ServerInstance->Modes->FindMode(prefix, MODETYPE_CHANNEL);
- if (!delta_mh)
- return false;
- UserMembIter m = userlist.find(user);
- if (m == userlist.end())
- return false;
- for(unsigned int i=0; i < m->second->modes.length(); i++)
+ char prefix = delta_mh->GetModeChar();
+ for (unsigned int i = 0; i < modes.length(); i++)
{
- char mchar = m->second->modes[i];
+ char mchar = modes[i];
ModeHandler* mh = ServerInstance->Modes->FindMode(mchar, MODETYPE_CHANNEL);
if (mh && mh->GetPrefixRank() <= delta_mh->GetPrefixRank())
{
- m->second->modes =
- m->second->modes.substr(0,i) +
+ modes = modes.substr(0,i) +
(adding ? std::string(1, prefix) : "") +
- m->second->modes.substr(mchar == prefix ? i+1 : i);
+ modes.substr(mchar == prefix ? i+1 : i);
return adding != (mchar == prefix);
}
}
if (adding)
- m->second->modes += std::string(1, prefix);
+ modes.push_back(prefix);
return adding;
}
diff --git a/src/mode.cpp b/src/mode.cpp
index b76e1558f..aedc8bb85 100644
--- a/src/mode.cpp
+++ b/src/mode.cpp
@@ -195,6 +195,30 @@ void ModeParser::DisplayCurrentModes(User *user, User* targetuser, Channel* targ
}
}
+PrefixMode::PrefixMode(Module* Creator, const std::string& Name, char ModeLetter)
+ : ModeHandler(Creator, Name, ModeLetter, PARAM_ALWAYS, MODETYPE_CHANNEL, MC_PREFIX)
+{
+ list = true;
+ m_paramtype = TR_NICK;
+}
+
+ModeAction PrefixMode::OnModeChange(User* source, User*, Channel* chan, std::string& parameter, bool adding)
+{
+ User* target = ServerInstance->FindNick(parameter);
+ if (!target)
+ {
+ source->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel", source->nick.c_str(), parameter.c_str());
+ return MODEACTION_DENY;
+ }
+
+ Membership* memb = chan->GetUser(target);
+ if (!memb)
+ return MODEACTION_DENY;
+
+ parameter = target->nick;
+ return (memb->SetPrefix(this, adding) ? MODEACTION_ALLOW : MODEACTION_DENY);
+}
+
ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool adding, const unsigned char modechar,
std::string &parameter, bool SkipACL)
{
@@ -295,21 +319,6 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool
return MODEACTION_DENY;
}
- if (mh->GetTranslateType() == TR_NICK && !ServerInstance->FindNick(parameter))
- {
- user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel", user->nick.c_str(), parameter.c_str());
- return MODEACTION_DENY;
- }
-
- if (mh->GetPrefixRank() && chan)
- {
- User* user_to_prefix = ServerInstance->FindNick(parameter);
- if (!user_to_prefix)
- return MODEACTION_DENY;
- if (!chan->SetPrefix(user_to_prefix, modechar, adding))
- return MODEACTION_DENY;
- }
-
/* Call the handler for the mode */
ModeAction ma = mh->OnModeChange(user, targetuser, chan, parameter, adding);
@@ -437,16 +446,9 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User* user,
if (pcnt)
{
- TranslateType tt = mh->GetTranslateType();
- if (tt == TR_NICK)
- {
- User* u = ServerInstance->FindNick(parameter);
- if (u)
- parameter = u->nick;
- }
output_parameters << " " << parameter;
LastParseParams.push_back(parameter);
- LastParseTranslate.push_back(tt);
+ LastParseTranslate.push_back(mh->GetTranslateType());
}
if ( (output_mode.length() + output_parameters.str().length() > 450)
@@ -827,11 +829,7 @@ void ModeHandler::RemoveMode(User* user)
void ModeHandler::RemoveMode(Channel* channel, irc::modestacker& stack)
{
- if (this->GetPrefixRank())
- {
- RemovePrefixMode(channel, stack);
- }
- else if (channel->IsModeSet(this))
+ if (channel->IsModeSet(this))
{
if (this->GetNumParams(false))
// Removing this mode requires a parameter
@@ -841,7 +839,7 @@ void ModeHandler::RemoveMode(Channel* channel, irc::modestacker& stack)
}
}
-void ModeHandler::RemovePrefixMode(Channel* chan, irc::modestacker& stack)
+void PrefixMode::RemoveMode(Channel* chan, irc::modestacker& stack)
{
const UserMembList* userlist = chan->GetUsers();
for (UserMembCIter i = userlist->begin(); i != userlist->end(); ++i)
diff --git a/src/modes/cmode_o.cpp b/src/modes/cmode_o.cpp
index d500f23b1..6e96afa67 100644
--- a/src/modes/cmode_o.cpp
+++ b/src/modes/cmode_o.cpp
@@ -28,16 +28,9 @@
#include "modules.h"
#include "builtinmodes.h"
-ModeChannelOp::ModeChannelOp() : ModeHandler(NULL, "op", 'o', PARAM_ALWAYS, MODETYPE_CHANNEL)
+ModeChannelOp::ModeChannelOp() : PrefixMode(NULL, "op", 'o')
{
- list = true;
prefix = '@';
levelrequired = OP_VALUE;
- m_paramtype = TR_NICK;
prefixrank = OP_VALUE;
}
-
-ModeAction ModeChannelOp::OnModeChange(User* source, User*, Channel* channel, std::string &parameter, bool adding)
-{
- return MODEACTION_ALLOW;
-}
diff --git a/src/modes/cmode_v.cpp b/src/modes/cmode_v.cpp
index fe62c407f..c8ce30ab1 100644
--- a/src/modes/cmode_v.cpp
+++ b/src/modes/cmode_v.cpp
@@ -28,16 +28,9 @@
#include "modules.h"
#include "builtinmodes.h"
-ModeChannelVoice::ModeChannelVoice() : ModeHandler(NULL, "voice", 'v', PARAM_ALWAYS, MODETYPE_CHANNEL)
+ModeChannelVoice::ModeChannelVoice() : PrefixMode(NULL, "voice", 'v')
{
- list = true;
prefix = '+';
levelrequired = HALFOP_VALUE;
- m_paramtype = TR_NICK;
prefixrank = VOICE_VALUE;
}
-
-ModeAction ModeChannelVoice::OnModeChange(User* source, User*, Channel* channel, std::string &parameter, bool adding)
-{
- return MODEACTION_ALLOW;
-}
diff --git a/src/modules/m_customprefix.cpp b/src/modules/m_customprefix.cpp
index bda11e8b3..f0b6d88e3 100644
--- a/src/modules/m_customprefix.cpp
+++ b/src/modules/m_customprefix.cpp
@@ -19,17 +19,16 @@
#include "inspircd.h"
-class CustomPrefixMode : public ModeHandler
+class CustomPrefixMode : public PrefixMode
{
public:
reference<ConfigTag> tag;
bool depriv;
CustomPrefixMode(Module* parent, ConfigTag* Tag)
- : ModeHandler(parent, Tag->getString("name"), 0, PARAM_ALWAYS, MODETYPE_CHANNEL), tag(Tag)
+ : PrefixMode(parent, Tag->getString("name"), 0)
+ , tag(Tag)
{
- list = true;
- m_paramtype = TR_NICK;
std::string v = tag->getString("prefix");
prefix = v.c_str()[0];
v = tag->getString("letter");
@@ -45,11 +44,6 @@ class CustomPrefixMode : public ModeHandler
return MOD_RES_ALLOW;
return MOD_RES_PASSTHRU;
}
-
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
- {
- return MODEACTION_ALLOW;
- }
};
class ModuleCustomPrefix : public Module
diff --git a/src/modules/m_ojoin.cpp b/src/modules/m_ojoin.cpp
index 54c7bfa73..0a5a57f40 100644
--- a/src/modules/m_ojoin.cpp
+++ b/src/modules/m_ojoin.cpp
@@ -84,16 +84,14 @@ class CommandOjoin : public SplitCommand
/** channel mode +Y
*/
-class NetworkPrefix : public ModeHandler
+class NetworkPrefix : public PrefixMode
{
public:
NetworkPrefix(Module* parent, char NPrefix)
- : ModeHandler(parent, "official-join", 'Y', PARAM_ALWAYS, MODETYPE_CHANNEL)
+ : PrefixMode(parent, "official-join", 'Y')
{
- list = true;
prefix = NPrefix;
levelrequired = INT_MAX;
- m_paramtype = TR_NICK;
prefixrank = NETWORK_VALUE;
}
@@ -106,12 +104,6 @@ class NetworkPrefix : public ModeHandler
return MOD_RES_PASSTHRU;
}
-
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
- {
- return MODEACTION_ALLOW;
- }
-
};
class ModuleOjoin : public Module
diff --git a/src/modules/m_operprefix.cpp b/src/modules/m_operprefix.cpp
index 23390baea..3d2a34bdb 100644
--- a/src/modules/m_operprefix.cpp
+++ b/src/modules/m_operprefix.cpp
@@ -26,32 +26,16 @@
#define OPERPREFIX_VALUE 1000000
-class OperPrefixMode : public ModeHandler
+class OperPrefixMode : public PrefixMode
{
public:
- OperPrefixMode(Module* Creator) : ModeHandler(Creator, "operprefix", 'y', PARAM_ALWAYS, MODETYPE_CHANNEL)
+ OperPrefixMode(Module* Creator) : PrefixMode(Creator, "operprefix", 'y')
{
std::string pfx = ServerInstance->Config->ConfValue("operprefix")->getString("prefix", "!");
- list = true;
prefix = pfx.empty() ? '!' : pfx[0];
- levelrequired = OPERPREFIX_VALUE;
- m_paramtype = TR_NICK;
+ levelrequired = INT_MAX;
prefixrank = OPERPREFIX_VALUE;
}
-
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
- {
- if (IS_SERVER(source) || ServerInstance->ULine(source->server))
- return MODEACTION_ALLOW;
- else
- {
- if (channel)
- source->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :Only servers are permitted to change channel mode '%c'", source->nick.c_str(), channel->name.c_str(), 'y');
- return MODEACTION_DENY;
- }
- }
-
- bool NeedsOper() { return true; }
};
class ModuleOperPrefixMode;