]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/mode.cpp
Replace std::deque with std::vector in spanningtree and related modules
[user/henk/code/inspircd.git] / src / mode.cpp
index 3b2a7c45a1c784959da25596d687f4236b5063dc..947f3c4fb53a5f69af8ee459044bc6a49d522e98 100644 (file)
@@ -2,8 +2,8 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
- * See: http://www.inspircd.org/wiki/index.php/Credits
+ *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
  *
  * This program is free but copyrighted software; see
  *            the file COPYING for details.
  * ---------------------------------------------------
  */
 
-/* $Core: libIRCDmode */
-/* $ExtraDeps: $(RELCPPFILES) */
-/* $ExtraObjects: modes/modeclasses.a */
-/* $ExtraBuild: @${MAKE} -C "modes" DIRNAME="src/modes" CC="$(CC)" $(MAKEARGS) CPPFILES="$(CPPFILES)" */
+/* $Core */
 
 #include "inspircd.h"
 #include "inspstring.h"
 #include "modes/cmode_h.h"
 /* +v (channel voice) */
 #include "modes/cmode_v.h"
-/* +s (server notices) */
-#include "modes/umode_s.h"
 /* +w (see wallops) */
 #include "modes/umode_w.h"
 /* +i (invisible) */
 #include "modes/umode_i.h"
 /* +o (operator) */
 #include "modes/umode_o.h"
-/* +n (notice mask - our implementation of snomasks) */
-#include "modes/umode_n.h"
+/* +s (server notice masks) */
+#include "modes/umode_s.h"
 
-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)
+ModeHandler::ModeHandler(InspIRCd* Instance, char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly, char mprefix, char prefixrequired, TranslateType translate)
+       : ServerInstance(Instance), mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), m_paramtype(translate), oper(operonly), prefix(mprefix), count(0), prefixneeded(prefixrequired)
 {
 }
 
@@ -70,6 +65,8 @@ bool ModeHandler::IsListMode()
 
 char ModeHandler::GetNeededPrefix()
 {
+       if (prefixneeded == '%' && !ServerInstance->Config->AllowHalfop)
+               return '@';
        return prefixneeded;
 }
 
@@ -99,6 +96,11 @@ ModeType ModeHandler::GetModeType()
        return m_type;
 }
 
+TranslateType ModeHandler::GetTranslateType()
+{
+       return m_paramtype;
+}
+
 bool ModeHandler::NeedsOper()
 {
        return oper;
@@ -119,6 +121,11 @@ char ModeHandler::GetModeChar()
        return mode;
 }
 
+std::string ModeHandler::GetUserParameter(User* user)
+{
+       return "";
+}
+
 ModeAction ModeHandler::OnModeChange(User*, User*, Channel*, std::string&, bool, bool)
 {
        return MODEACTION_DENY;
@@ -144,6 +151,10 @@ void ModeHandler::DisplayEmptyList(User*, Channel*)
 {
 }
 
+void ModeHandler::OnParameterMissing(User* user, User* dest, Channel* channel)
+{
+}
+
 bool ModeHandler::CheckTimeStamp(time_t theirs, time_t ours, const std::string&, const std::string&, Channel*)
 {
        return (ours < theirs);
@@ -167,10 +178,6 @@ SimpleChannelModeHandler::SimpleChannelModeHandler(InspIRCd* Instance, char mode
 
 ModeAction SimpleUserModeHandler::OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding, bool servermode)
 {
-       /* Only opers can change other users modes */
-       if (source != dest)
-               return MODEACTION_DENY;
-
        if (adding)
        {
                if (!dest->IsModeSet(this->GetModeChar()))
@@ -251,7 +258,7 @@ User* ModeParser::SanityChecks(User *user, const char *dest, Channel *chan, int)
        d = ServerInstance->FindNick(dest);
        if (!d)
        {
-               user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), dest);
+               user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), dest);
                return NULL;
        }
        return d;
@@ -322,35 +329,35 @@ void ModeParser::DisplayCurrentModes(User *user, User* targetuser, Channel* targ
        if (targetchannel)
        {
                /* Display channel's current mode string */
-               user->WriteNumeric(324, "%s %s +%s",user->nick.c_str(), targetchannel->name.c_str(), targetchannel->ChanModes(targetchannel->HasUser(user)));
-               user->WriteNumeric(329, "%s %s %lu", user->nick.c_str(), targetchannel->name.c_str(), (unsigned long)targetchannel->age);
+               user->WriteNumeric(RPL_CHANNELMODEIS, "%s %s +%s",user->nick.c_str(), targetchannel->name.c_str(), targetchannel->ChanModes(targetchannel->HasUser(user)));
+               user->WriteNumeric(RPL_CHANNELCREATED, "%s %s %lu", user->nick.c_str(), targetchannel->name.c_str(), (unsigned long)targetchannel->age);
                return;
        }
        else if (targetuser)
        {
                if (targetuser->Visibility && !targetuser->Visibility->VisibleTo(user))
                {
-                       user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), text);
+                       user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), text);
                        return;
                }
 
-               if ((targetuser == user) || (IS_OPER(user)))
+               if (targetuser == user || user->HasPrivPermission("users/auspex"))
                {
                        /* Display user's current mode string */
-                       user->WriteNumeric(221, "%s :+%s",targetuser->nick.c_str(),targetuser->FormatModes());
+                       user->WriteNumeric(RPL_UMODEIS, "%s :+%s",targetuser->nick.c_str(),targetuser->FormatModes());
                        if (IS_OPER(targetuser))
-                               user->WriteNumeric(8, "%s +%s :Server notice mask", targetuser->nick.c_str(), targetuser->FormatNoticeMasks());
+                               user->WriteNumeric(RPL_SNOMASKIS, "%s +%s :Server notice mask", targetuser->nick.c_str(), targetuser->FormatNoticeMasks());
                        return;
                }
                else
                {
-                       user->WriteNumeric(502, "%s :Can't change mode for other users", user->nick.c_str());
+                       user->WriteNumeric(ERR_USERSDONTMATCH, "%s :Can't change mode for other users", user->nick.c_str());
                        return;
                }
        }
 
        /* No such nick/channel */
-       user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), text);
+       user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), text);
        return;
 }
 
@@ -363,6 +370,8 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
        User* targetuser  = ServerInstance->FindNick(parameters[0]);
 
        LastParse.clear();
+       LastParseParams.clear();
+       LastParseTranslate.clear();
 
        /* Special case for displaying the list for listmodes,
         * e.g. MODE #chan b, or MODE #chan +b without a parameter
@@ -375,7 +384,7 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                seq++;
 
                mask = MASK_CHANNEL;
-               
+
                while (mode && *mode)
                {
                        unsigned char mletter = *mode;
@@ -385,7 +394,7 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                mode++;
                                continue;
                        }
-                       
+
                        /* Ensure the user doesnt request the same mode twice,
                         * so they cant flood themselves off out of idiocy.
                         */
@@ -412,11 +421,11 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                        continue;
                                }
 
-                               if (!IS_OPER(user))
+                               if (!user->HasPrivPermission("channels/auspex"))
                                {
                                        if (ServerInstance->Config->HideModeLists[mletter] && (targetchannel->GetStatus(user) < STATUS_HOP))
                                        {
-                                               user->WriteNumeric(482, "%s %s :Only half-operators and above may view the +%c list",user->nick.c_str(), targetchannel->name.c_str(), *mode++);
+                                               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :Only half-operators and above may view the +%c list",user->nick.c_str(), targetchannel->name.c_str(), *mode++);
                                                mh->DisplayEmptyList(user, targetchannel);
                                                continue;
                                        }
@@ -429,7 +438,7 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                for(ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
                                {
                                        std::string dummyparam;
-                                       
+
                                        if (!((*watchers)->BeforeMode(user, NULL, targetchannel, dummyparam, true, MODETYPE_CHANNEL)))
                                                display = false;
                                }
@@ -467,9 +476,12 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
 
                        if ((IS_LOCAL(user)) && (!ServerInstance->ULine(user->server)) && (!servermode))
                        {
+                               /* Make modes that are being changed visible to OnAccessCheck */
+                               LastParse = parameters[1];
                                /* We don't have halfop */
                                int MOD_RESULT = 0;
                                FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE));
+                               LastParse.clear();
                                if (MOD_RESULT == ACR_DENY)
                                        return;
                                SkipAccessChecks = (MOD_RESULT == ACR_ALLOW);
@@ -479,16 +491,16 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                {
                        type = MODETYPE_USER;
                        mask = MASK_USER;
-                       if ((user != targetuser) && (!ServerInstance->ULine(user->server)))
+                       if (user != targetuser && IS_LOCAL(user) && !ServerInstance->ULine(user->server))
                        {
-                               user->WriteNumeric(502, "%s :Can't change mode for other users", user->nick.c_str());
+                               user->WriteNumeric(ERR_USERSDONTMATCH, "%s :Can't change mode for other users", user->nick.c_str());
                                return;
                        }
                }
                else
                {
                        /* No such nick/channel */
-                       user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
+                       user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
                        return;
                }
 
@@ -501,6 +513,8 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                unsigned int parameter_counter = 2; /* Index of first parameter */
                unsigned int parameter_count = 0;
                bool last_successful_state_change = false;
+               LastParseParams.push_back(output_sequence);
+               LastParseTranslate.push_back(TR_TEXT);
 
                /* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */
                if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-'))
@@ -573,6 +587,7 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                                                else
                                                                {
                                                                        /* No parameter, continue to the next mode */
+                                                                       modehandlers[handler_id]->OnParameterMissing(user, targetuser, targetchannel);
                                                                        continue;
                                                                }
 
@@ -597,11 +612,11 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                                                        /* If the mode defined by the handler is not '\0', but the handler for it
                                                                         * cannot be found, they probably dont have the right module loaded to implement
                                                                         * the prefix they want to compare the mode against, e.g. '&' for m_chanprotect.
-                                                                        * Revert to checking against the minimum core prefix, '%'.
+                                                                        * Revert to checking against the minimum core prefix, '%' or '@'.
                                                                         */
                                                                        if (needed && !prefixmode)
-                                                                               prefixmode = FindPrefix('%');
-                                               
+                                                                               prefixmode = ServerInstance->Config->AllowHalfop ? FindPrefix('%') : FindPrefix('@');
+
                                                                        unsigned int neededrank = prefixmode->GetPrefixRank();
                                                                        /* 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
@@ -614,7 +629,7 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                                                        if (!ourmode || ourmode->GetPrefixRank() < neededrank)
                                                                        {
                                                                                /* Bog off */
-                                                                               user->WriteNumeric(482, "%s %s :You must have channel privilege %c or above to %sset channel mode %c",
+                                                                               user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must have channel privilege %c or above to %sset channel mode %c",
                                                                                                user->nick.c_str(), targetchannel->name.c_str(), needed, adding ? "" : "un", modechar);
                                                                                continue;
                                                                        }
@@ -622,7 +637,7 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                                        }
 
                                                        bool had_parameter = !parameter.empty();
-                                                               
+
                                                        for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
                                                        {
                                                                if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type, servermode) == false)
@@ -641,6 +656,17 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                                        if (abort)
                                                                continue;
 
+                                                       /* If it's disabled, they have to be an oper.
+                                                        */
+                                                       if (IS_LOCAL(user) && !IS_OPER(user) && ((type == MODETYPE_CHANNEL ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes)[modehandlers[handler_id]->GetModeChar() - 'A']))
+                                                       {
+                                                               user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - %s mode %c has been locked by the administrator",
+                                                                               user->nick.c_str(),
+                                                                               type == MODETYPE_CHANNEL ? "channel" : "user",
+                                                                               modehandlers[handler_id]->GetModeChar());
+                                                               continue;
+                                                       }
+
                                                        /* It's an oper only mode, check if theyre an oper. If they arent,
                                                         * eat any parameter that  came with the mode, and continue to next
                                                         */
@@ -648,7 +674,7 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                                        {
                                                                if (IS_OPER(user))
                                                                {
-                                                                       user->WriteNumeric(481, "%s :Permission Denied - Oper type %s does not have access to set %s mode %c",
+                                                                       user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to set %s mode %c",
                                                                                        user->nick.c_str(),
                                                                                        user->oper.c_str(),
                                                                                        type == MODETYPE_CHANNEL ? "channel" : "user",
@@ -656,7 +682,7 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                                                }
                                                                else
                                                                {
-                                                                       user->WriteNumeric(481, "%s :Permission Denied - Only operators may set %s mode %c",
+                                                                       user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Only operators may set %s mode %c",
                                                                                        user->nick.c_str(),
                                                                                        type == MODETYPE_CHANNEL ? "channel" : "user",
                                                                                        modehandlers[handler_id]->GetModeChar());
@@ -685,7 +711,7 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                                                                output_sequence.append(adding ? "+" : "-");
                                                                        last_successful_state_change = adding;
                                                                }
-                                                               
+
                                                                /* Add the mode letter */
                                                                output_sequence.push_back(modechar);
 
@@ -695,6 +721,8 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                                                if ((modehandlers[handler_id]->GetNumParams(adding)) && (!parameter.empty()))
                                                                {
                                                                        parameter_list << " " << parameter;
+                                                                       LastParseParams.push_back(parameter);
+                                                                       LastParseTranslate.push_back(modehandlers[handler_id]->GetTranslateType());
                                                                        parameter_count++;
                                                                        /* Does this mode have a prefix? */
                                                                        if (modehandlers[handler_id]->GetPrefix() && targetchannel)
@@ -735,7 +763,8 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                /* Was there at least one valid mode in the sequence? */
                if (!output_sequence.empty())
                {
-                       if (servermode)
+                       LastParseParams[0] = output_sequence;
+                       if (!user)
                        {
                                if (type == MODETYPE_CHANNEL)
                                {
@@ -753,13 +782,13 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                if (type == MODETYPE_CHANNEL)
                                {
                                        targetchannel->WriteChannel(user, "MODE %s %s%s", targetchannel->name.c_str(), output_sequence.c_str(), parameter_list.str().c_str());
-                                       FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str()));
+                                       FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, LastParseParams, LastParseTranslate));
                                        this->LastParse = targetchannel->name;
                                }
                                else
                                {
                                        user->WriteTo(targetuser, "MODE %s %s%s", targetuser->nick.c_str(), output_sequence.c_str(), parameter_list.str().c_str());
-                                       FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, output_sequence + parameter_list.str()));
+                                       FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, LastParseParams, LastParseTranslate));
                                        this->LastParse = targetuser->nick;
                                }
                        }
@@ -916,9 +945,6 @@ std::string ModeParser::ChannelModeList()
 
        for (unsigned char mode = 'A'; mode <= 'z'; mode++)
        {
-               if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
-                       continue;
-
                unsigned char pos = (mode-65) | MASK_CHANNEL;
 
                if (modehandlers[pos])
@@ -935,9 +961,6 @@ std::string ModeParser::ParaModeList()
 
        for (unsigned char mode = 'A'; mode <= 'z'; mode++)
        {
-               if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
-                       continue;
-
                unsigned char pos = (mode-65) | MASK_CHANNEL;
 
                if ((modehandlers[pos]) && (modehandlers[pos]->GetNumParams(true)))
@@ -995,7 +1018,7 @@ std::string ModeParser::ModeString(User* user, Channel* channel, bool nick_suffi
                return types;
 }
 
-std::string ModeParser::ChanModes()
+std::string ModeParser::GiveModeList(ModeMasks m)
 {
        std::string type1;      /* Listmodes EXCEPT those with a prefix */
        std::string type2;      /* Modes that take a param when adding or removing */
@@ -1004,13 +1027,10 @@ std::string ModeParser::ChanModes()
 
        for (unsigned char mode = 'A'; mode <= 'z'; mode++)
        {
-               if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
-                       continue;
-
-               unsigned char pos = (mode-65) | MASK_CHANNEL;
+               unsigned char pos = (mode-65) | m;
                 /* One parameter when adding */
                if (modehandlers[pos])
-               {       
+               {
                        if (modehandlers[pos]->GetNumParams(true))
                        {
                                if ((modehandlers[pos]->IsListMode()) && (!modehandlers[pos]->GetPrefix()))
@@ -1040,14 +1060,13 @@ std::string ModeParser::ChanModes()
                                type4 += modehandlers[pos]->GetModeChar();
                        }
                }
-                        
        }
 
        return type1 + "," + type2 + "," + type3 + "," + type4;
 }
 
 bool ModeParser::PrefixComparison(prefixtype one, prefixtype two)
-{       
+{
        return one.second > two.second;
 }
 
@@ -1060,9 +1079,6 @@ std::string ModeParser::BuildPrefixes()
 
        for (unsigned char mode = 'A'; mode <= 'z'; mode++)
        {
-               if ((!ServerInstance->Config->AllowHalfop) && (mode == 'h'))
-                       continue;
-
                unsigned char pos = (mode-65) | MASK_CHANNEL;
 
                if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix()))
@@ -1146,7 +1162,7 @@ void ModeHandler::RemoveMode(User* user, irc::modestacker* stack)
                        sprintf(moderemove,"-%c",this->GetModeChar());
                        parameters.push_back(user->nick);
                        parameters.push_back(moderemove);
-                       ServerInstance->Parser->CallHandler("MODE", parameters, user);
+                       ServerInstance->Modes->Process(parameters, ServerInstance->FakeClient, true);
                }
        }
 }
@@ -1191,7 +1207,6 @@ ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
                new ModeChannelOp(Instance),
                new ModeChannelHalfOp(Instance),
                new ModeChannelVoice(Instance),
-               new ModeUserServerNotice(Instance),
                new ModeUserWallops(Instance),
                new ModeUserInvisible(Instance),
                new ModeUserOperator(Instance),
@@ -1210,5 +1225,5 @@ ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
                this->AddMode(modes[index]);
 
        seq = 0;
-       memset(&sent, 0, 256);
+       memset(&sent, 0, sizeof(sent));
 }