]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/mode.cpp
Move depriv from m_customprefix into PrefixMode.
[user/henk/code/inspircd.git] / src / mode.cpp
index 3762dc52e14d9a25b537114532d1c58c43402dfe..fd25a9a9ff58b65355c8ac00d7a7f31c82961eaf 100644 (file)
 #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)
 {
 }
 
@@ -44,21 +51,21 @@ ModeHandler::~ModeHandler()
 {
 }
 
-int ModeHandler::GetNumParams(bool adding)
+bool ModeHandler::NeedsParam(bool adding) const
 {
        switch (parameters_taken)
        {
                case PARAM_ALWAYS:
-                       return 1;
+                       return true;
                case PARAM_SETONLY:
-                       return adding ? 1 : 0;
+                       return adding;
                case PARAM_NONE:
                        break;
        }
-       return 0;
+       return false;
 }
 
-std::string ModeHandler::GetUserParameter(User* user)
+std::string ModeHandler::GetUserParameter(const User* user) const
 {
        return "";
 }
@@ -144,11 +151,6 @@ ModeWatcher::~ModeWatcher()
        ServerInstance->Modes->DelModeWatcher(this);
 }
 
-ModeType ModeWatcher::GetModeType()
-{
-       return m_type;
-}
-
 bool ModeWatcher::BeforeMode(User*, User*, Channel*, std::string&, bool)
 {
        return true;
@@ -160,11 +162,20 @@ void ModeWatcher::AfterMode(User*, User*, Channel*, const std::string&, bool)
 
 PrefixMode::PrefixMode(Module* Creator, const std::string& Name, char ModeLetter, unsigned int Rank, char PrefixChar)
        : ModeHandler(Creator, Name, ModeLetter, PARAM_ALWAYS, MODETYPE_CHANNEL, MC_PREFIX)
-       , prefix(PrefixChar), prefixrank(Rank)
+       , prefix(PrefixChar)
+       , prefixrank(Rank)
+       , selfremove(true)
 {
        list = true;
 }
 
+ModResult PrefixMode::AccessCheck(User* src, Channel*, std::string& value, bool adding)
+{
+       if (!adding && src->nick == value && selfremove)
+               return MOD_RES_ALLOW;
+       return MOD_RES_PASSTHRU;
+}
+
 ModeAction PrefixMode::OnModeChange(User* source, User*, Channel* chan, std::string& parameter, bool adding)
 {
        User* target;
@@ -219,7 +230,7 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode
 
        ModeHandler* mh = mcitem.mh;
        bool adding = mcitem.adding;
-       int pcnt = mh->GetNumParams(adding);
+       const bool needs_param = mh->NeedsParam(adding);
 
        std::string& parameter = mcitem.param;
        // crop mode parameter size to 250 characters
@@ -242,7 +253,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
@@ -251,11 +262,12 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode
                        unsigned int ourrank = chan->GetPrefixValue(user);
                        if (ourrank < neededrank)
                        {
-                               PrefixMode* neededmh = NULL;
-                               for(char c='A'; c <= 'z'; c++)
+                               const PrefixMode* neededmh = NULL;
+                               const PrefixModeList& prefixmodes = GetPrefixModes();
+                               for (PrefixModeList::const_iterator i = prefixmodes.begin(); i != prefixmodes.end(); ++i)
                                {
-                                       PrefixMode* privmh = FindPrefixMode(c);
-                                       if (privmh && privmh->GetPrefixRank() >= neededrank)
+                                       const PrefixMode* const privmh = *i;
+                                       if (privmh->GetPrefixRank() >= neededrank)
                                        {
                                                // this mode is sufficient to allow this action
                                                if (!neededmh || privmh->GetPrefixRank() < neededmh->GetPrefixRank())
@@ -283,15 +295,15 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode
                                return MODEACTION_DENY;
 
                        // A module whacked the parameter completely, and there was one. Abort.
-                       if (pcnt && parameter.empty())
+                       if ((needs_param) && (parameter.empty()))
                                return MODEACTION_DENY;
                }
        }
 
        if (IS_LOCAL(user) && !user->IsOper())
        {
-               char* disabled = (type == MODETYPE_CHANNEL) ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes;
-               if (disabled[modechar - 'A'])
+               const std::bitset<64>& disabled = (type == MODETYPE_CHANNEL) ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes;
+               if (disabled.test(modechar - 'A'))
                {
                        user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - %s mode %c has been locked by the administrator",
                                type == MODETYPE_CHANNEL ? "channel" : "user", modechar));
@@ -299,7 +311,7 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode
                }
        }
 
-       if (adding && IS_LOCAL(user) && mh->NeedsOper() && !user->HasModePermission(modechar, type))
+       if ((adding) && (IS_LOCAL(user)) && (mh->NeedsOper()) && (!user->HasModePermission(mh)))
        {
                /* It's an oper only mode, and they don't have access to it. */
                if (user->IsOper())
@@ -318,7 +330,7 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode
        /* Call the handler for the mode */
        ModeAction ma = mh->OnModeChange(user, targetuser, chan, parameter, adding);
 
-       if (pcnt && parameter.empty())
+       if ((needs_param) && (parameter.empty()))
                return MODEACTION_DENY;
 
        if (ma != MODEACTION_ALLOW)
@@ -363,7 +375,7 @@ void ModeParser::ModeParamsToChangeList(User* user, ModeType type, const std::ve
                }
 
                std::string parameter;
-               if (mh->GetNumParams(adding) && param_at < endindex)
+               if ((mh->NeedsParam(adding)) && (param_at < endindex))
                        parameter = parameters[param_at++];
 
                changelist.push(mh, adding, parameter);
@@ -432,7 +444,7 @@ unsigned int ModeParser::ProcessSingle(User* user, Channel* targetchannel, User*
 
                // If the mode is supposed to have a parameter then we first take a look at item.param
                // and, if we were asked to, also handle mode merges now
-               if (mh->GetNumParams(item.adding))
+               if (mh->NeedsParam(item.adding))
                {
                        // Skip the mode if the parameter does not pass basic validation
                        if (!IsModeParamValid(user, targetchannel, targetuser, item))
@@ -574,11 +586,7 @@ ModeHandler::Id ModeParser::AllocateModeId(ModeType mt)
 
 void ModeParser::AddMode(ModeHandler* mh)
 {
-       /* Yes, i know, this might let people declare modes like '_' or '^'.
-        * If they do that, thats their problem, and if i ever EVER see an
-        * official InspIRCd developer do that, i'll beat them with a paddle!
-        */
-       if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
+       if (!ModeParser::IsModeChar(mh->GetModeChar()))
                throw ModuleException("Invalid letter for mode " + mh->name);
 
        /* A mode prefix of ',' is not acceptable, it would fuck up server to server.
@@ -628,7 +636,7 @@ void ModeParser::AddMode(ModeHandler* mh)
 
 bool ModeParser::DelMode(ModeHandler* mh)
 {
-       if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
+       if (!ModeParser::IsModeChar(mh->GetModeChar()))
                return false;
 
        ModeHandlerMap& mhmap = modehandlersbyname[mh->GetModeType()];
@@ -698,7 +706,7 @@ ModeHandler* ModeParser::FindMode(const std::string& modename, ModeType mt)
 
 ModeHandler* ModeParser::FindMode(unsigned const char modeletter, ModeType mt)
 {
-       if ((modeletter < 'A') || (modeletter > 'z'))
+       if (!ModeParser::IsModeChar(modeletter))
                return NULL;
 
        return modehandlers[mt][modeletter-65];
@@ -719,7 +727,7 @@ std::string ModeParser::CreateModeList(ModeType mt, bool needparam)
        for (unsigned char mode = 'A'; mode <= 'z'; mode++)
        {
                ModeHandler* mh = modehandlers[mt][mode-65];
-               if ((mh) && ((!needparam) || (mh->GetNumParams(true))))
+               if ((mh) && ((!needparam) || (mh->NeedsParam(true))))
                        modestr.push_back(mode);
        }
 
@@ -728,7 +736,9 @@ std::string ModeParser::CreateModeList(ModeType mt, bool needparam)
 
 void ModeParser::RecreateModeListFor004Numeric()
 {
-       Cached004ModeList = CreateModeList(MODETYPE_USER) + " " + CreateModeList(MODETYPE_CHANNEL) + " " + CreateModeList(MODETYPE_CHANNEL, true);
+       Cached004ModeList[0] = CreateModeList(MODETYPE_USER);
+       Cached004ModeList[1] = CreateModeList(MODETYPE_CHANNEL);
+       Cached004ModeList[2] = CreateModeList(MODETYPE_CHANNEL, true);
 }
 
 PrefixMode* ModeParser::FindPrefix(unsigned const char pfxletter)
@@ -756,7 +766,7 @@ std::string ModeParser::GiveModeList(ModeType mt)
                 /* One parameter when adding */
                if (mh)
                {
-                       if (mh->GetNumParams(true))
+                       if (mh->NeedsParam(true))
                        {
                                PrefixMode* pm = mh->IsPrefixMode();
                                if ((mh->IsListMode()) && ((!pm) || (pm->GetPrefix() == 0)))
@@ -766,7 +776,7 @@ std::string ModeParser::GiveModeList(ModeType mt)
                                else
                                {
                                        /* ... and one parameter when removing */
-                                       if (mh->GetNumParams(false))
+                                       if (mh->NeedsParam(false))
                                        {
                                                /* But not a list mode */
                                                if (!pm)
@@ -858,7 +868,7 @@ void ModeHandler::RemoveMode(Channel* channel, Modes::ChangeList& changelist)
 {
        if (channel->IsModeSet(this))
        {
-               if (this->GetNumParams(false))
+               if (this->NeedsParam(false))
                        // Removing this mode requires a parameter
                        changelist.push_remove(this, channel->GetModeParameter(this));
                else
@@ -871,7 +881,7 @@ void PrefixMode::RemoveMode(Channel* chan, Modes::ChangeList& changelist)
        const Channel::MemberMap& userlist = chan->GetUsers();
        for (Channel::MemberMap::const_iterator i = userlist.begin(); i != userlist.end(); ++i)
        {
-               if (i->second->hasMode(this->GetModeChar()))
+               if (i->second->HasMode(this))
                        changelist.push_remove(this, i->first->nick);
        }
 }
@@ -923,6 +933,11 @@ void ModeParser::InitBuiltinModes()
        static_modes.b.DoRehash();
 }
 
+bool ModeParser::IsModeChar(char chr)
+{
+       return ((chr >= 'A' && chr <= 'Z') || (chr >= 'a' && chr <= 'z'));
+}
+
 ModeParser::ModeParser()
 {
        /* Clear mode handler list */