summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Powell <petpow@saberuk.com>2018-01-27 13:05:14 +0000
committerPeter Powell <petpow@saberuk.com>2018-01-29 11:52:13 +0000
commitd5a6054948502625d7f0c235f6faaeea58734de5 (patch)
treea43e95ded07dca92c9d3659e331a88cb8e0b7b21
parent3398ce7e50f1c269e8221df04e1eefb52d54c820 (diff)
Add ERR_INVALIDMODEPARAM for responding to invalid mode params.
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.
-rw-r--r--include/numeric.h27
-rw-r--r--include/numericbuilder.h54
-rw-r--r--include/numerics.h1
-rw-r--r--src/mode.cpp5
-rw-r--r--src/modules/m_chanfilter.cpp2
-rw-r--r--src/modules/m_chanhistory.cpp13
-rw-r--r--src/modules/m_exemptchanops.cpp4
-rw-r--r--src/modules/m_joinflood.cpp4
-rw-r--r--src/modules/m_kicknorejoin.cpp3
-rw-r--r--src/modules/m_messageflood.cpp4
-rw-r--r--src/modules/m_nickflood.cpp4
-rw-r--r--src/modules/m_repeat.cpp25
12 files changed, 98 insertions, 48 deletions
diff --git a/include/numeric.h b/include/numeric.h
index 8ea2447bf..85f2f13f0 100644
--- a/include/numeric.h
+++ b/include/numeric.h
@@ -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");
- }
- };
-}
diff --git a/include/numericbuilder.h b/include/numericbuilder.h
index 17aa9e0c8..0d55093ca 100644
--- a/include/numericbuilder.h
+++ b/include/numericbuilder.h
@@ -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");
+ }
+};
diff --git a/include/numerics.h b/include/numerics.h
index 57ecee4df..740ee1797 100644
--- a/include/numerics.h
+++ b/include/numerics.h
@@ -184,6 +184,7 @@ enum
ERR_CANTSENDTOUSER = 531, // ???
RPL_SYNTAX = 650, // insp-specific
+ ERR_INVALIDMODEPARAM = 696, // insp-specific
ERR_CHANOPEN = 713,
ERR_KNOCKONCHAN = 714,
diff --git a/src/mode.cpp b/src/mode.cpp
index c07c342a3..9d17f5be8 100644
--- a/src/mode.cpp
+++ b/src/mode.cpp
@@ -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*)
diff --git a/src/modules/m_chanfilter.cpp b/src/modules/m_chanfilter.cpp
index e7dc6372b..d201f5418 100644
--- a/src/modules/m_chanfilter.cpp
+++ b/src/modules/m_chanfilter.cpp
@@ -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;
}
diff --git a/src/modules/m_chanhistory.cpp b/src/modules/m_chanhistory.cpp
index 4d74b65e0..5f081d9de 100644
--- a/src/modules/m_chanhistory.cpp
+++ b/src/modules/m_chanhistory.cpp
@@ -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;
diff --git a/src/modules/m_exemptchanops.cpp b/src/modules/m_exemptchanops.cpp
index 52e7c4dad..b1d7b35df 100644
--- a/src/modules/m_exemptchanops.cpp
+++ b/src/modules/m_exemptchanops.cpp
@@ -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;
}
diff --git a/src/modules/m_joinflood.cpp b/src/modules/m_joinflood.cpp
index b4a8f6181..bd9e0ad9e 100644
--- a/src/modules/m_joinflood.cpp
+++ b/src/modules/m_joinflood.cpp
@@ -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;
}
diff --git a/src/modules/m_kicknorejoin.cpp b/src/modules/m_kicknorejoin.cpp
index 1bc11948c..67711f766 100644
--- a/src/modules/m_kicknorejoin.cpp
+++ b/src/modules/m_kicknorejoin.cpp
@@ -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;
diff --git a/src/modules/m_messageflood.cpp b/src/modules/m_messageflood.cpp
index 36f2c923b..0707e6ae4 100644
--- a/src/modules/m_messageflood.cpp
+++ b/src/modules/m_messageflood.cpp
@@ -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;
}
diff --git a/src/modules/m_nickflood.cpp b/src/modules/m_nickflood.cpp
index e3b448871..50e2b3d93 100644
--- a/src/modules/m_nickflood.cpp
+++ b/src/modules/m_nickflood.cpp
@@ -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;
}
diff --git a/src/modules/m_repeat.cpp b/src/modules/m_repeat.cpp
index a57e96740..3e974c221 100644
--- a/src/modules/m_repeat.cpp
+++ b/src/modules/m_repeat.cpp
@@ -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;
}
}