]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/mode.cpp
Update all wiki links to point to the new wiki. This was done automatically with...
[user/henk/code/inspircd.git] / src / mode.cpp
index 2fb001037565df2c207ba5de8d0b6fdfbf425491..35cbed451920a3f82bfc9d104b68788a10edc065 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.
@@ -11,7 +11,7 @@
  * ---------------------------------------------------
  */
 
-/* $Core: libIRCDmode */
+/* $Core */
 /* $ExtraDeps: $(RELCPPFILES) */
 /* $ExtraObjects: modes/modeclasses.a */
 /* $ExtraBuild: @${MAKE} -C "modes" DIRNAME="src/modes" CC="$(CC)" $(MAKEARGS) CPPFILES="$(CPPFILES)" */
 #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 +68,8 @@ bool ModeHandler::IsListMode()
 
 char ModeHandler::GetNeededPrefix()
 {
+       if (prefixneeded == '%' && !ServerInstance->Config->AllowHalfop)
+               return '@';
        return prefixneeded;
 }
 
@@ -99,6 +99,11 @@ ModeType ModeHandler::GetModeType()
        return m_type;
 }
 
+TranslateType ModeHandler::GetTranslateType()
+{
+       return m_paramtype;
+}
+
 bool ModeHandler::NeedsOper()
 {
        return oper;
@@ -119,6 +124,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 +154,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 +181,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 +261,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 +332,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, targetchannel->ChanModes(targetchannel->HasUser(user)));
-               user->WriteNumeric(329, "%s %s %lu", user->nick.c_str(), targetchannel->name, (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 +373,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 +387,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 +397,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 +424,14 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                        continue;
                                }
 
-                               if (ServerInstance->Config->HideModeLists[mletter] && (targetchannel->GetStatus(user) < STATUS_HOP))
+                               if (!user->HasPrivPermission("channels/auspex"))
                                {
-                                       user->WriteNumeric(482, "%s %s :Only half-operators and above may view the +%c list",user->nick.c_str(), targetchannel->name, *mode++);
-                                       mh->DisplayEmptyList(user, targetchannel);
-                                       continue;
+                                       if (ServerInstance->Config->HideModeLists[mletter] && (targetchannel->GetStatus(user) < STATUS_HOP))
+                                       {
+                                               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;
+                                       }
                                }
 
                                /** See below for a description of what craq this is :D
@@ -426,7 +441,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;
                                }
@@ -464,9 +479,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);
@@ -476,16 +494,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;
                }
 
@@ -498,6 +516,7 @@ 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;
+               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() != '-'))
@@ -570,6 +589,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;
                                                                }
 
@@ -594,11 +614,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
@@ -611,15 +631,15 @@ 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->nick.c_str(), targetchannel->name, needed, adding ? "" : "un", modechar);
+                                                                               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;
                                                                        }
                                                                }
                                                        }
 
                                                        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)
@@ -638,6 +658,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
                                                         */
@@ -645,7 +676,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",
@@ -653,7 +684,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());
@@ -682,7 +713,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);
 
@@ -692,6 +723,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)
@@ -711,7 +744,7 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                                                                state_change = false;
 
                                                                if ((output_sequence.length() + parameter_list.str().length() > 450) || (output_sequence.length() > 100)
-                                                                               || (parameter_count > MAXMODES))
+                                                                               || (parameter_count > ServerInstance->Config->Limits.MaxModes))
                                                                {
                                                                        /* We cant have a mode sequence this long */
                                                                        letter = mode_sequence.end() - 1;
@@ -732,11 +765,12 @@ 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())
                {
+                       LastParseParams.push_front(output_sequence);
                        if (servermode)
                        {
                                if (type == MODETYPE_CHANNEL)
                                {
-                                       targetchannel->WriteChannelWithServ(ServerInstance->Config->ServerName, "MODE %s %s%s", targetchannel->name, output_sequence.c_str(), parameter_list.str().c_str());
+                                       targetchannel->WriteChannelWithServ(ServerInstance->Config->ServerName, "MODE %s %s%s", targetchannel->name.c_str(), output_sequence.c_str(), parameter_list.str().c_str());
                                        this->LastParse = targetchannel->name;
                                }
                                else
@@ -749,14 +783,14 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                        {
                                if (type == MODETYPE_CHANNEL)
                                {
-                                       targetchannel->WriteChannel(user,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str());
-                                       FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str()));
+                                       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, 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()));
+                                       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, LastParseParams, LastParseTranslate));
                                        this->LastParse = targetuser->nick;
                                }
                        }
@@ -780,6 +814,9 @@ void ModeParser::CleanMask(std::string &mask)
        std::string::size_type pos_of_dot = mask.find_first_of('.');
        std::string::size_type pos_of_colons = mask.find("::"); /* Because ipv6 addresses are colon delimited -- double so it treats extban as nick */
 
+       if (mask.length() >= 2 && mask[1] == ':')
+               return; // if it's an extban, don't even try guess how it needs to be formed.
+
        if ((pos_of_pling == std::string::npos) && (pos_of_at == std::string::npos))
        {
                /* Just a nick, or just a host - or clearly ipv6 (starting with :) */
@@ -910,9 +947,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])
@@ -929,9 +963,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)))
@@ -989,7 +1020,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 */
@@ -998,13 +1029,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()))
@@ -1034,14 +1062,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;
 }
 
@@ -1054,9 +1081,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()))
@@ -1140,7 +1164,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, false);
                }
        }
 }
@@ -1185,7 +1209,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),
@@ -1204,5 +1227,5 @@ ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
                this->AddMode(modes[index]);
 
        seq = 0;
-       memset(&sent, 0, 256);
+       memset(&sent, 0, sizeof(sent));
 }