]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Add ERR_INVALIDMODEPARAM for responding to invalid mode params.
authorPeter Powell <petpow@saberuk.com>
Sat, 27 Jan 2018 13:05:14 +0000 (13:05 +0000)
committerPeter Powell <petpow@saberuk.com>
Mon, 29 Jan 2018 11:52:13 +0000 (11:52 +0000)
Currently on invalid modes we do a combination of different things:

1. Send a custom mode-specific numeric (which often collides with
   other modes).

2. Send a server notice.

3. Do absolutely nothing.

This new numeric is a generic way of handling invalid parameters
when setting a mode that avoids all of the mistakes of the previous
behaviour.

12 files changed:
include/numeric.h
include/numericbuilder.h
include/numerics.h
src/mode.cpp
src/modules/m_chanfilter.cpp
src/modules/m_chanhistory.cpp
src/modules/m_exemptchanops.cpp
src/modules/m_joinflood.cpp
src/modules/m_kicknorejoin.cpp
src/modules/m_messageflood.cpp
src/modules/m_nickflood.cpp
src/modules/m_repeat.cpp

index 8ea2447bf4663be94b40d478bf849ac898bb30d1..85f2f13f082340c6038e36970a711b2a9360fb1c 100644 (file)
@@ -85,30 +85,3 @@ class Numeric::Numeric
         */
        std::vector<std::string>& GetParams() { return params; }
 };
-
-namespace Numerics
-{
-       /** Builder for the ERR_NOSUCHNICK numeric. */
-       class NoSuchNick : public Numeric::Numeric
-       {
-        public:
-               NoSuchNick(const std::string& nick)
-                       : Numeric(ERR_NOSUCHNICK)
-               {
-                       push(nick);
-                       push("No such nick");
-               }
-       };
-
-       /** Builder for the ERR_NOSUCHCHANNEL numeric. */
-       class NoSuchChannel : public Numeric::Numeric
-       {
-        public:
-               NoSuchChannel(const std::string& chan)
-                       : Numeric(ERR_NOSUCHCHANNEL)
-               {
-                       push(chan);
-                       push("No such channel");
-               }
-       };
-}
index 17aa9e0c866bb1ceafe1bae03a30e24fd482157c..0d55093ca59c3db15d9f75b787f2872fa7dc918d 100644 (file)
@@ -196,3 +196,57 @@ class Numeric::ParamBuilder : public GenericParamBuilder<NumStaticParams, SendEm
        {
        }
 };
+
+namespace Numerics
+{
+       class InvalidModeParameter;
+       class NoSuchChannel;
+       class NoSuchNick;
+}
+
+/* Builder for the ERR_INVALIDMODEPARAM numeric. */
+class Numerics::InvalidModeParameter : public Numeric::Numeric
+{
+ public:
+       InvalidModeParameter(Channel* chan, ModeHandler* mode, const std::string& parameter, const std::string& message = "")
+               : Numeric(ERR_INVALIDMODEPARAM)
+       {
+               push(chan->name);
+               push(mode->GetModeChar());
+               push(parameter);
+               push(message.empty() ? InspIRCd::Format("Invalid %s mode parameter", mode->name.c_str()) : message);
+       }
+
+       InvalidModeParameter(User* user, ModeHandler* mode, const std::string& parameter, const std::string& message = "")
+               : Numeric(ERR_INVALIDMODEPARAM)
+       {
+               push(user->registered & REG_NICK ? user->nick : "*");
+               push(mode->GetModeChar());
+               push(parameter);
+               push(message.empty() ? InspIRCd::Format("Invalid %s mode parameter", mode->name.c_str()) : message);
+       }
+};
+
+/** Builder for the ERR_NOSUCHCHANNEL numeric. */
+class Numerics::NoSuchChannel : public Numeric::Numeric
+{
+ public:
+       NoSuchChannel(const std::string& chan)
+               : Numeric(ERR_NOSUCHCHANNEL)
+       {
+               push(chan);
+               push("No such channel");
+       }
+};
+
+/** Builder for the ERR_NOSUCHNICK numeric. */
+class Numerics::NoSuchNick : public Numeric::Numeric
+{
+ public:
+       NoSuchNick(const std::string& nick)
+               : Numeric(ERR_NOSUCHNICK)
+       {
+               push(nick);
+               push("No such nick");
+       }
+};
index 57ecee4dfb7ef69c8513fee766f73dec64e17a38..740ee17973bf6e1f67d47bc526de7a6434003314 100644 (file)
@@ -184,6 +184,7 @@ enum
        ERR_CANTSENDTOUSER              = 531, // ???
 
        RPL_SYNTAX                      = 650, // insp-specific
+       ERR_INVALIDMODEPARAM            = 696, // insp-specific
 
        ERR_CHANOPEN                    = 713,
        ERR_KNOCKONCHAN                 = 714,
index c07c342a362d71211a0d7f0e351c27654e8c0244..9d17f5be8b8eda5cae8a329fd550ef2d3d6d6b08 100644 (file)
@@ -89,6 +89,11 @@ void ModeHandler::DisplayEmptyList(User*, Channel*)
 
 void ModeHandler::OnParameterMissing(User* user, User* dest, Channel* channel)
 {
+       const std::string message = InspIRCd::Format("You must specify a parameter for the %s mode", name.c_str());
+       if (channel)
+               user->WriteNumeric(Numerics::InvalidModeParameter(channel, this, "*", message));
+       else
+               user->WriteNumeric(Numerics::InvalidModeParameter(dest, this, "*", message));
 }
 
 bool ModeHandler::ResolveModeConflict(std::string& theirs, const std::string& ours, Channel*)
index e7dc6372b664ca166b74b861a02da73573e3c87e..d201f5418b60bed6dcff04963f41b317a9136590 100644 (file)
@@ -37,7 +37,7 @@ class ChanFilter : public ListModeBase
        bool ValidateParam(User* user, Channel* chan, std::string& word) CXX11_OVERRIDE {
                if (word.length() > 35)
                {
-                       user->WriteNumeric(935, chan->name, word, "%word is too long for censor list");
+                       user->WriteNumeric(Numerics::InvalidModeParameter(chan, this, word, "Word is too long for the spamfilter list"));
                        return false;
                }
 
index 4d74b65e00a4bfbefb54523adfa099115d915ab7..5f081d9decbb17a2b26debf16ad4e4f36702453d 100644 (file)
@@ -63,18 +63,25 @@ class HistoryMode : public ParamMode<HistoryMode, SimpleExtItem<HistoryList> >
        {
                std::string::size_type colon = parameter.find(':');
                if (colon == std::string::npos)
+               {
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
                        return MODEACTION_DENY;
+               }
 
                std::string duration(parameter, colon+1);
                if ((IS_LOCAL(source)) && ((duration.length() > 10) || (!IsValidDuration(duration))))
+               {
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
                        return MODEACTION_DENY;
+               }
 
                unsigned int len = ConvToInt(parameter.substr(0, colon));
                unsigned int time = InspIRCd::Duration(duration);
-               if (len == 0)
-                       return MODEACTION_DENY;
-               if (len > maxlines && IS_LOCAL(source))
+               if (len == 0 || (len > maxlines && IS_LOCAL(source)))
+               {
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
                        return MODEACTION_DENY;
+               }
                if (len > maxlines)
                        len = maxlines;
 
index 52e7c4dad463c2488ad352babf269dd86959ad33..b1d7b35dfc31aa2066649c81a961723af2b3e829 100644 (file)
@@ -32,7 +32,7 @@ class ExemptChanOps : public ListModeBase
                std::string::size_type p = word.find(':');
                if (p == std::string::npos)
                {
-                       user->WriteNumeric(955, chan->name, word, "Invalid exemptchanops entry, format is <restriction>:<prefix>");
+                       user->WriteNumeric(Numerics::InvalidModeParameter(chan, this, word, "Invalid exemptchanops entry, format is <restriction>:<prefix>"));
                        return false;
                }
 
@@ -45,7 +45,7 @@ class ExemptChanOps : public ListModeBase
 
                if (!ServerInstance->Modes->FindMode(restriction, MODETYPE_CHANNEL))
                {
-                       user->WriteNumeric(955, chan->name, restriction, "Unknown restriction");
+                       user->WriteNumeric(Numerics::InvalidModeParameter(chan, this, word, "Unknown restriction"));
                        return false;
                }
 
index b4a8f6181aa03540c9f4dd343dfe273906cc61a6..bd9e0ad9e23dda77748bb641d3413aa42a27c790 100644 (file)
@@ -98,7 +98,7 @@ class JoinFlood : public ParamMode<JoinFlood, SimpleExtItem<joinfloodsettings> >
                std::string::size_type colon = parameter.find(':');
                if ((colon == std::string::npos) || (parameter.find('-') != std::string::npos))
                {
-                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
                        return MODEACTION_DENY;
                }
 
@@ -107,7 +107,7 @@ class JoinFlood : public ParamMode<JoinFlood, SimpleExtItem<joinfloodsettings> >
                unsigned int nsecs = ConvToInt(parameter.substr(colon+1));
                if ((njoins<1) || (nsecs<1))
                {
-                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
                        return MODEACTION_DENY;
                }
 
index 1bc11948c0c65a964eaef9b1d0777ab066c0716d..67711f7665b8e60e381d6ff1c2f911839c0e4ed1 100644 (file)
@@ -95,7 +95,10 @@ class KickRejoin : public ParamMode<KickRejoin, SimpleExtItem<KickRejoinData> >
        {
                int v = ConvToInt(parameter);
                if (v <= 0)
+               {
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
                        return MODEACTION_DENY;
+               }
 
                if ((IS_LOCAL(source) && ((unsigned int)v > max)))
                        v = max;
index 36f2c923b6779991bfecb152f8dff02568ddf43b..0707e6ae4e6fa10b28389b9d7a0aa6df68ae49f2 100644 (file)
@@ -77,7 +77,7 @@ class MsgFlood : public ParamMode<MsgFlood, SimpleExtItem<floodsettings> >
                std::string::size_type colon = parameter.find(':');
                if ((colon == std::string::npos) || (parameter.find('-') != std::string::npos))
                {
-                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
                        return MODEACTION_DENY;
                }
 
@@ -88,7 +88,7 @@ class MsgFlood : public ParamMode<MsgFlood, SimpleExtItem<floodsettings> >
 
                if ((nlines<2) || (nsecs<1))
                {
-                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
                        return MODEACTION_DENY;
                }
 
index e3b448871431e903c992435d0c62d4318dc8983f..50e2b3d9366a3ed0c456c275acafbaa14d602fab 100644 (file)
@@ -95,7 +95,7 @@ class NickFlood : public ParamMode<NickFlood, SimpleExtItem<nickfloodsettings> >
                std::string::size_type colon = parameter.find(':');
                if ((colon == std::string::npos) || (parameter.find('-') != std::string::npos))
                {
-                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
                        return MODEACTION_DENY;
                }
 
@@ -105,7 +105,7 @@ class NickFlood : public ParamMode<NickFlood, SimpleExtItem<nickfloodsettings> >
 
                if ((nnicks<1) || (nsecs<1))
                {
-                       source->WriteNumeric(608, channel->name, "Invalid flood parameter");
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter));
                        return MODEACTION_DENY;
                }
 
index a57e9674021eb03f877b4391ddb32a23abedcf97..3e974c22194caf33db75b646fc293264306549c9 100644 (file)
@@ -140,18 +140,20 @@ class RepeatMode : public ParamMode<RepeatMode, SimpleExtItem<ChannelSettings> >
                ChannelSettings settings;
                if (!ParseSettings(source, parameter, settings))
                {
-                       source->WriteNotice("*** Invalid syntax. Syntax is {[~*]}[lines]:[time]{:[difference]}{:[backlog]}");
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter,
+                               "Invalid repeat syntax. Syntax is {[~*]}[lines]:[time]{:[difference]}{:[backlog]}."));
                        return MODEACTION_DENY;
                }
 
                if ((settings.Backlog > 0) && (settings.Lines > settings.Backlog))
                {
-                       source->WriteNotice("*** You can't set needed lines higher than backlog");
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter,
+                               "Invalid repeat syntax. You can't set needed lines higher than backlog."));
                        return MODEACTION_DENY;
                }
 
                LocalUser* localsource = IS_LOCAL(source);
-               if ((localsource) && (!ValidateSettings(localsource, settings)))
+               if ((localsource) && (!ValidateSettings(localsource, channel, parameter, settings)))
                        return MODEACTION_DENY;
 
                ext.set(channel, settings);
@@ -302,11 +304,12 @@ class RepeatMode : public ParamMode<RepeatMode, SimpleExtItem<ChannelSettings> >
                return true;
        }
 
-       bool ValidateSettings(LocalUser* source, const ChannelSettings& settings)
+       bool ValidateSettings(LocalUser* source, Channel* channel, const std::string& parameter, const ChannelSettings& settings)
        {
                if (settings.Backlog && !ms.MaxBacklog)
                {
-                       source->WriteNotice("*** The server administrator has disabled backlog matching");
+                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter,
+                               "Invalid repeat parameter. The server administrator has disabled backlog matching."));
                        return false;
                }
 
@@ -315,21 +318,25 @@ class RepeatMode : public ParamMode<RepeatMode, SimpleExtItem<ChannelSettings> >
                        if (settings.Diff > ms.MaxDiff)
                        {
                                if (ms.MaxDiff == 0)
-                                       source->WriteNotice("*** The server administrator has disabled matching on edit distance");
+                                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter,
+                                               "Invalid repeat parameter. The server administrator has disabled matching on edit distance."));
                                else
-                                       source->WriteNotice("*** The distance you specified is too great. Maximum allowed is " + ConvToStr(ms.MaxDiff));
+                                       source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter, InspIRCd::Format(
+                                               "Invalid repeat parameter. The distance you specified is too great. Maximum allowed is %u.", ms.MaxDiff)));
                                return false;
                        }
 
                        if (ms.MaxLines && settings.Lines > ms.MaxLines)
                        {
-                               source->WriteNotice("*** The line number you specified is too great. Maximum allowed is " + ConvToStr(ms.MaxLines));
+                               source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter, InspIRCd::Format(
+                                       "Invalid repeat parameter. The line number you specified is too great. Maximum allowed is %u.", ms.MaxLines)));
                                return false;
                        }
 
                        if (ms.MaxSecs && settings.Seconds > ms.MaxSecs)
                        {
-                               source->WriteNotice("*** The seconds you specified is too great. Maximum allowed is " + ConvToStr(ms.MaxSecs));
+                               source->WriteNumeric(Numerics::InvalidModeParameter(channel, this, parameter, InspIRCd::Format(
+                                       "Invalid repeat parameter. The seconds you specified is too great. Maximum allowed is %u.", ms.MaxSecs)));
                                return false;
                        }
                }