aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Sadie Powell2019-01-24 15:58:57 +0000
committerGravatar Sadie Powell2019-01-24 15:58:57 +0000
commit1799bcff97e8018156df809fd3cae3ed3d663591 (patch)
treee8ed9f51b8d52f188c9b3d18abab4ebde915c3d4 /src
parentAdd translation for casemapping between 2.0/3.0 (#1544) (diff)
parentAdd translation for casemapping between 2.0/3.0 (#1544) (diff)
downloadinspircd++-1799bcff97e8018156df809fd3cae3ed3d663591.tar.gz
inspircd++-1799bcff97e8018156df809fd3cae3ed3d663591.tar.bz2
inspircd++-1799bcff97e8018156df809fd3cae3ed3d663591.zip
Merge branch 'insp3' into master
Diffstat (limited to 'src')
-rw-r--r--src/clientprotocol.cpp2
-rw-r--r--src/command_parse.cpp19
-rw-r--r--src/configreader.cpp46
-rw-r--r--src/coremods/core_hostname_lookup.cpp8
-rw-r--r--src/coremods/core_info/cmd_version.cpp8
-rw-r--r--src/coremods/core_privmsg.cpp39
-rw-r--r--src/coremods/core_serialize_rfc.cpp75
-rw-r--r--src/coremods/core_xline/cmd_eline.cpp8
-rw-r--r--src/coremods/core_xline/cmd_gline.cpp10
-rw-r--r--src/coremods/core_xline/cmd_kline.cpp10
-rw-r--r--src/coremods/core_xline/cmd_qline.cpp8
-rw-r--r--src/coremods/core_xline/cmd_zline.cpp8
-rw-r--r--src/coremods/core_xline/core_xline.cpp15
-rw-r--r--src/coremods/core_xline/core_xline.h10
-rw-r--r--src/hashcomp.cpp4
-rw-r--r--src/inspircd.cpp1
-rw-r--r--src/inspsocket.cpp5
-rw-r--r--src/mode.cpp35
-rw-r--r--src/modules/m_alias.cpp1
-rw-r--r--src/modules/m_cban.cpp4
-rw-r--r--src/modules/m_cgiirc.cpp27
-rw-r--r--src/modules/m_check.cpp2
-rw-r--r--src/modules/m_clearchan.cpp2
-rw-r--r--src/modules/m_conn_umodes.cpp6
-rw-r--r--src/modules/m_connectban.cpp4
-rw-r--r--src/modules/m_disable.cpp189
-rw-r--r--src/modules/m_dnsbl.cpp14
-rw-r--r--src/modules/m_filter.cpp10
-rw-r--r--src/modules/m_haproxy.cpp7
-rw-r--r--src/modules/m_hostchange.cpp2
-rw-r--r--src/modules/m_ident.cpp16
-rw-r--r--src/modules/m_ircv3_echomessage.cpp7
-rw-r--r--src/modules/m_passforward.cpp8
-rw-r--r--src/modules/m_rline.cpp18
-rw-r--r--src/modules/m_samode.cpp3
-rw-r--r--src/modules/m_shun.cpp4
-rw-r--r--src/modules/m_spanningtree/away.cpp2
-rw-r--r--src/modules/m_spanningtree/main.cpp8
-rw-r--r--src/modules/m_spanningtree/treesocket.h2
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp2
-rw-r--r--src/modules/m_sslinfo.cpp3
-rw-r--r--src/modules/m_svshold.cpp6
-rw-r--r--src/snomasks.cpp4
-rw-r--r--src/usermanager.cpp5
-rw-r--r--src/users.cpp82
-rw-r--r--src/xline.cpp12
46 files changed, 470 insertions, 291 deletions
diff --git a/src/clientprotocol.cpp b/src/clientprotocol.cpp
index a732855a5..212d65d6b 100644
--- a/src/clientprotocol.cpp
+++ b/src/clientprotocol.cpp
@@ -35,7 +35,7 @@ bool ClientProtocol::Serializer::HandleTag(LocalUser* user, const std::string& t
for (::Events::ModuleEventProvider::SubscriberList::const_iterator i = list.begin(); i != list.end(); ++i)
{
MessageTagProvider* const tagprov = static_cast<MessageTagProvider*>(*i);
- const ModResult res = tagprov->OnClientProtocolProcessTag(user, tagname, tagvalue);
+ const ModResult res = tagprov->OnProcessTag(user, tagname, tagvalue);
if (res == MOD_RES_ALLOW)
return tags.insert(std::make_pair(tagname, MessageTagData(tagprov, tagvalue))).second;
else if (res == MOD_RES_DENY)
diff --git a/src/command_parse.cpp b/src/command_parse.cpp
index c2ae39d49..7a732f8b5 100644
--- a/src/command_parse.cpp
+++ b/src/command_parse.cpp
@@ -266,24 +266,6 @@ void CommandParser::ProcessCommand(LocalUser* user, std::string& command, Comman
}
}
- if ((user->registered == REG_ALL) && (!user->IsOper()) && (handler->IsDisabled()))
- {
- /* command is disabled! */
- user->CommandFloodPenalty += failpenalty;
- if (ServerInstance->Config->DisabledDontExist)
- {
- user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "Unknown command");
- }
- else
- {
- user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "This command has been disabled.");
- }
-
- ServerInstance->SNO->WriteToSnoMask('a', "%s denied for %s (%s@%s)",
- command.c_str(), user->nick.c_str(), user->ident.c_str(), user->GetRealHost().c_str());
- return;
- }
-
if ((!command_p.empty()) && (command_p.back().empty()) && (!handler->allow_empty_last_param))
command_p.pop_back();
@@ -333,7 +315,6 @@ CommandBase::CommandBase(Module* mod, const std::string& cmd, unsigned int minpa
, min_params(minpara)
, max_params(maxpara)
, use_count(0)
- , disabled(false)
, works_before_reg(false)
, allow_empty_last_param(true)
, Penalty(1)
diff --git a/src/configreader.cpp b/src/configreader.cpp
index ce03f1d9e..5a0ceff06 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -72,31 +72,6 @@ ServerConfig::~ServerConfig()
delete EmptyTag;
}
-bool ServerConfig::ApplyDisabledCommands()
-{
- // Enable everything first.
- const CommandParser::CommandMap& commands = ServerInstance->Parser.GetCommands();
- for (CommandParser::CommandMap::const_iterator x = commands.begin(); x != commands.end(); ++x)
- x->second->Disable(false);
-
- // Now disable the commands specified in the config.
- std::string command;
- irc::spacesepstream commandlist(ConfValue("disabled")->getString("commands"));
- while (commandlist.GetToken(command))
- {
- Command* handler = ServerInstance->Parser.GetHandler(command);
- if (!handler)
- {
- ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "Unable to disable the %s command as it does not exist!", command.c_str());
- continue;
- }
-
- ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "The %s command has been disabled", command.c_str());
- handler->Disable(true);
- }
- return true;
-}
-
static void ReadXLine(ServerConfig* conf, const std::string& tag, const std::string& key, XLineFactory* make)
{
ConfigTagList tags = conf->ConfTags(tag);
@@ -378,7 +353,6 @@ void ServerConfig::Fill()
ServerDesc = server->getString("description", "Configure Me");
Network = server->getString("network", "Network");
NetBufferSize = ConfValue("performance")->getInt("netbuffersize", 10240, 1024, 65534);
- DisabledDontExist = ConfValue("disabled")->getBool("fakenonexistant");
CustomVersion = security->getString("customversion");
HideBans = security->getBool("hidebans");
HideServer = security->getString("hideserver", security->getString("hidewhois"));
@@ -429,25 +403,6 @@ void ServerConfig::Fill()
RestrictBannedUsers = ServerConfig::BUT_RESTRICT_NOTIFY;
else
throw CoreException(restrictbannedusers + " is an invalid <options:restrictbannedusers> value, at " + options->getTagLocation());
-
- DisabledUModes.reset();
- std::string modes = ConfValue("disabled")->getString("usermodes");
- for (std::string::const_iterator p = modes.begin(); p != modes.end(); ++p)
- {
- // Complain when the character is not a valid mode character.
- if (!ModeParser::IsModeChar(*p))
- throw CoreException("Invalid usermode " + std::string(1, *p) + " was found.");
- DisabledUModes.set(*p - 'A');
- }
-
- DisabledCModes.reset();
- modes = ConfValue("disabled")->getString("chanmodes");
- for (std::string::const_iterator p = modes.begin(); p != modes.end(); ++p)
- {
- if (!ModeParser::IsModeChar(*p))
- throw CoreException("Invalid chanmode " + std::string(1, *p) + " was found.");
- DisabledCModes.set(*p - 'A');
- }
}
// WARNING: it is not safe to use most of the codebase in this function, as it
@@ -723,7 +678,6 @@ void ConfigReaderThread::Finish()
ServerInstance->Users.RehashCloneCounts();
ServerInstance->XLines->CheckELines();
ServerInstance->XLines->ApplyLines();
- Config->ApplyDisabledCommands();
User* user = ServerInstance->FindNick(TheUserUID);
ConfigStatus status(user);
diff --git a/src/coremods/core_hostname_lookup.cpp b/src/coremods/core_hostname_lookup.cpp
index ec93732b1..85d0f530c 100644
--- a/src/coremods/core_hostname_lookup.cpp
+++ b/src/coremods/core_hostname_lookup.cpp
@@ -193,18 +193,14 @@ class ModuleHostnameLookup : public Module
void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE
{
+ // If core_dns is not loaded or hostname resolution is disabled for the user's
+ // connect class then the logic in this function does not apply.
if (!DNS || !user->MyClass->resolvehostnames)
- {
- user->WriteNotice("*** Skipping host resolution (disabled by server administrator)");
return;
- }
// Clients can't have a DNS hostname if they aren't connected via IPv4 or IPv6.
if (user->client_sa.family() != AF_INET && user->client_sa.family() != AF_INET6)
- {
- user->WriteNotice("*** Skipping host resolution (connected via a non-IP socket)");
return;
- }
user->WriteNotice("*** Looking up your hostname...");
diff --git a/src/coremods/core_info/cmd_version.cpp b/src/coremods/core_info/cmd_version.cpp
index 29d96169e..57f9b05cf 100644
--- a/src/coremods/core_info/cmd_version.cpp
+++ b/src/coremods/core_info/cmd_version.cpp
@@ -29,8 +29,12 @@ CommandVersion::CommandVersion(Module* parent)
CmdResult CommandVersion::Handle(User* user, const Params& parameters)
{
- std::string version = ServerInstance->GetVersionString((user->IsOper()));
- user->WriteNumeric(RPL_VERSION, version);
+ Numeric::Numeric numeric(RPL_VERSION);
+ irc::tokenstream tokens(ServerInstance->GetVersionString(user->IsOper()));
+ for (std::string token; tokens.GetTrailing(token); )
+ numeric.push(token);
+ user->WriteNumeric(numeric);
+
LocalUser *lu = IS_LOCAL(user);
if (lu != NULL)
{
diff --git a/src/coremods/core_privmsg.cpp b/src/coremods/core_privmsg.cpp
index dae770abe..692a661b3 100644
--- a/src/coremods/core_privmsg.cpp
+++ b/src/coremods/core_privmsg.cpp
@@ -95,12 +95,24 @@ class MessageCommandBase : public Command
ChanModeReference noextmsgmode;
/** Send a PRIVMSG or NOTICE message to all local users from the given user
- * @param user User sending the message
- * @param msg The message to send
- * @param mt Type of the message (MSG_PRIVMSG or MSG_NOTICE)
- * @param tags Message tags to include in the outgoing protocol message
+ * @param source The user sending the message.
+ * @param msg The details of the message to send.
*/
- static void SendAll(User* user, const std::string& msg, MessageType mt, const ClientProtocol::TagMap& tags);
+ static void SendAll(User* source, const MessageDetails& details)
+ {
+ ClientProtocol::Messages::Privmsg message(ClientProtocol::Messages::Privmsg::nocopy, source, "$*", details.text, details.type);
+ message.AddTags(details.tags_out);
+ message.SetSideEffect(true);
+ ClientProtocol::Event messageevent(ServerInstance->GetRFCEvents().privmsg, message);
+
+ const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
+ for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i)
+ {
+ LocalUser* user = *i;
+ if ((user->registered == REG_ALL) && (!details.exemptions.count(user)))
+ user->Send(messageevent);
+ }
+ }
public:
MessageCommandBase(Module* parent, MessageType mt)
@@ -128,21 +140,6 @@ class MessageCommandBase : public Command
}
};
-void MessageCommandBase::SendAll(User* user, const std::string& msg, MessageType mt, const ClientProtocol::TagMap& tags)
-{
- ClientProtocol::Messages::Privmsg message(ClientProtocol::Messages::Privmsg::nocopy, user, "$*", msg, mt);
- message.AddTags(tags);
- message.SetSideEffect(true);
- ClientProtocol::Event messageevent(ServerInstance->GetRFCEvents().privmsg, message);
-
- const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
- for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i)
- {
- if ((*i)->registered == REG_ALL)
- (*i)->Send(messageevent);
- }
-}
-
CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters, MessageType mt)
{
User *dest;
@@ -171,7 +168,7 @@ CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters
FOREACH_MOD(OnUserMessage, (user, msgtarget, msgdetails));
if (InspIRCd::Match(ServerInstance->Config->ServerName, servername, NULL))
{
- SendAll(user, msgdetails.text, mt, msgdetails.tags_out);
+ SendAll(user, msgdetails);
}
FOREACH_MOD(OnUserPostMessage, (user, msgtarget, msgdetails));
return CMD_SUCCESS;
diff --git a/src/coremods/core_serialize_rfc.cpp b/src/coremods/core_serialize_rfc.cpp
index 1ba330146..23a4c2052 100644
--- a/src/coremods/core_serialize_rfc.cpp
+++ b/src/coremods/core_serialize_rfc.cpp
@@ -19,11 +19,20 @@
#include "inspircd.h"
+enum
+{
+ // From ircu.
+ ERR_INPUTTOOLONG = 417
+};
+
class RFCSerializer : public ClientProtocol::Serializer
{
- /** Maximum size of the message tags portion of the message, including the `@` and the trailing space characters.
- */
- static const std::string::size_type MAX_MESSAGE_TAG_LENGTH = 512;
+
+ /** The maximum size of client-originated message tags in an incoming message including the `@`. */
+ static const std::string::size_type MAX_CLIENT_MESSAGE_TAG_LENGTH = 4095;
+
+ /** The maximum size of server-originated message tags in an outgoing message including the `@`. */
+ static const std::string::size_type MAX_SERVER_MESSAGE_TAG_LENGTH = 511;
static void SerializeTags(const ClientProtocol::TagMap& tags, const ClientProtocol::TagSelection& tagwl, std::string& line);
@@ -47,15 +56,32 @@ bool RFCSerializer::Parse(LocalUser* user, const std::string& line, ClientProtoc
return false;
}
- ServerInstance->Logs->Log("USERINPUT", LOG_RAWIO, "C[%s] I %s", user->uuid.c_str(), line.c_str());
+ // Work out how long the message can actually be.
+ size_t maxline = ServerInstance->Config->Limits.MaxLine - start - 2;
+ if (line[start] == '@')
+ maxline += MAX_CLIENT_MESSAGE_TAG_LENGTH + 1;
- irc::tokenstream tokens(line, start);
- std::string token;
+ irc::tokenstream tokens(line, start, maxline);
+ ServerInstance->Logs->Log("USERINPUT", LOG_RAWIO, "C[%s] I %s", user->uuid.c_str(), tokens.GetMessage().c_str());
// This will always exist because of the check at the start of the function.
+ std::string token;
tokens.GetMiddle(token);
if (token[0] == '@')
{
+ // Check that the client tags fit within the client tag space.
+ if (token.length() > MAX_CLIENT_MESSAGE_TAG_LENGTH)
+ {
+ user->WriteNumeric(ERR_INPUTTOOLONG, "Input line was too long");
+ user->CommandFloodPenalty += 2000;
+ return false;
+ }
+
+ // Truncate the RFC part of the message if it is too long.
+ size_t maxrfcline = token.length() + ServerInstance->Config->Limits.MaxLine - 1;
+ if (tokens.GetMessage().length() > maxrfcline)
+ tokens.GetMessage().erase(maxrfcline);
+
// Line begins with message tags, parse them.
std::string tagval;
irc::sepstream ss(token.substr(1), ';');
@@ -78,7 +104,6 @@ bool RFCSerializer::Parse(LocalUser* user, const std::string& line, ClientProtoc
HandleTag(user, token, tagval, parseoutput.tags);
}
-
// Try to read the prefix or command name.
if (!tokens.GetMiddle(token))
{
@@ -114,17 +139,29 @@ bool RFCSerializer::Parse(LocalUser* user, const std::string& line, ClientProtoc
return true;
}
+namespace
+{
+ void CheckTagLength(std::string& line, size_t prevsize, size_t& length, size_t maxlength)
+ {
+ const std::string::size_type diffsize = line.size() - prevsize;
+ if (length + diffsize > maxlength)
+ line.erase(prevsize);
+ else
+ length += diffsize;
+ }
+}
+
void RFCSerializer::SerializeTags(const ClientProtocol::TagMap& tags, const ClientProtocol::TagSelection& tagwl, std::string& line)
{
- char prefix = '@'; // First tag name is prefixed with a '@'
+ size_t client_tag_length = 0;
+ size_t server_tag_length = 0;
for (ClientProtocol::TagMap::const_iterator i = tags.begin(); i != tags.end(); ++i)
{
if (!tagwl.IsSelected(tags, i))
continue;
const std::string::size_type prevsize = line.size();
- line.push_back(prefix);
- prefix = ';'; // Remaining tags are prefixed with ';'
+ line.push_back(prevsize ? ';' : '@');
line.append(i->first);
const std::string& val = i->second.value;
if (!val.empty())
@@ -133,16 +170,14 @@ void RFCSerializer::SerializeTags(const ClientProtocol::TagMap& tags, const Clie
line.append(val);
}
- // The tags part of the message mustn't grow longer than what is allowed by the spec. If it does,
- // remove last tag and stop adding more tags.
- //
- // One is subtracted from the limit before comparing because there must be a ' ' char after the last tag
- // which also counts towards the limit.
- if (line.size() > MAX_MESSAGE_TAG_LENGTH-1)
- {
- line.erase(prevsize);
- break;
- }
+ // The tags part of the message must not contain more client and server tags than allowed by the
+ // message tags specification. This is complicated by the tag space having separate limits for
+ // both server-originated and client-originated tags. If either of the tag limits is exceeded then
+ // the most recently added tag is removed.
+ if (i->first[0] == '+')
+ CheckTagLength(line, prevsize, client_tag_length, MAX_CLIENT_MESSAGE_TAG_LENGTH);
+ else
+ CheckTagLength(line, prevsize, server_tag_length, MAX_SERVER_MESSAGE_TAG_LENGTH);
}
if (!line.empty())
diff --git a/src/coremods/core_xline/cmd_eline.cpp b/src/coremods/core_xline/cmd_eline.cpp
index a3a4d9466..3010e0f61 100644
--- a/src/coremods/core_xline/cmd_eline.cpp
+++ b/src/coremods/core_xline/cmd_eline.cpp
@@ -50,7 +50,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters)
if (ih.first.empty())
{
- user->WriteNotice("*** Target not found");
+ user->WriteNotice("*** Target not found.");
return CMD_FAILURE;
}
@@ -61,7 +61,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters)
unsigned long duration;
if (!InspIRCd::Duration(parameters[1], duration))
{
- user->WriteNotice("*** Invalid duration for E-line");
+ user->WriteNotice("*** Invalid duration for E-line.");
return CMD_FAILURE;
}
ELine* el = new ELine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str());
@@ -82,7 +82,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters)
else
{
delete el;
- user->WriteNotice("*** E-Line for " + target + " already exists");
+ user->WriteNotice("*** E-line for " + target + " already exists.");
}
}
else
@@ -93,7 +93,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters)
}
else
{
- user->WriteNotice("*** E-Line " + target + " not found in list, try /stats e");
+ user->WriteNotice("*** E-line " + target + " not found in list, try /stats e.");
}
}
diff --git a/src/coremods/core_xline/cmd_gline.cpp b/src/coremods/core_xline/cmd_gline.cpp
index a9de707c4..60dcd714a 100644
--- a/src/coremods/core_xline/cmd_gline.cpp
+++ b/src/coremods/core_xline/cmd_gline.cpp
@@ -50,7 +50,7 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters)
if (ih.first.empty())
{
- user->WriteNotice("*** Target not found");
+ user->WriteNotice("*** Target not found.");
return CMD_FAILURE;
}
@@ -60,14 +60,14 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters)
else if (target.find('!') != std::string::npos)
{
- user->WriteNotice("*** G-Line cannot operate on nick!user@host masks");
+ user->WriteNotice("*** G-line cannot operate on nick!user@host masks.");
return CMD_FAILURE;
}
unsigned long duration;
if (!InspIRCd::Duration(parameters[1], duration))
{
- user->WriteNotice("*** Invalid duration for G-line");
+ user->WriteNotice("*** Invalid duration for G-line.");
return CMD_FAILURE;
}
GLine* gl = new GLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str());
@@ -90,7 +90,7 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters)
else
{
delete gl;
- user->WriteNotice("** G-Line for " + target + " already exists");
+ user->WriteNotice("** G-line for " + target + " already exists.");
}
}
@@ -102,7 +102,7 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters)
}
else
{
- user->WriteNotice("*** G-Line " + target + " not found in list, try /stats g.");
+ user->WriteNotice("*** G-line " + target + " not found in list, try /stats g.");
}
}
diff --git a/src/coremods/core_xline/cmd_kline.cpp b/src/coremods/core_xline/cmd_kline.cpp
index 9b474d16c..813b9afa6 100644
--- a/src/coremods/core_xline/cmd_kline.cpp
+++ b/src/coremods/core_xline/cmd_kline.cpp
@@ -50,7 +50,7 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters)
if (ih.first.empty())
{
- user->WriteNotice("*** Target not found");
+ user->WriteNotice("*** Target not found.");
return CMD_FAILURE;
}
@@ -60,14 +60,14 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters)
if (target.find('!') != std::string::npos)
{
- user->WriteNotice("*** K-Line cannot operate on nick!user@host masks");
+ user->WriteNotice("*** K-line cannot operate on nick!user@host masks.");
return CMD_FAILURE;
}
unsigned long duration;
if (!InspIRCd::Duration(parameters[1], duration))
{
- user->WriteNotice("*** Invalid duration for K-line");
+ user->WriteNotice("*** Invalid duration for K-line.");
return CMD_FAILURE;
}
KLine* kl = new KLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str());
@@ -90,7 +90,7 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters)
else
{
delete kl;
- user->WriteNotice("*** K-Line for " + target + " already exists");
+ user->WriteNotice("*** K-line for " + target + " already exists.");
}
}
else
@@ -101,7 +101,7 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters)
}
else
{
- user->WriteNotice("*** K-Line " + target + " not found in list, try /stats k.");
+ user->WriteNotice("*** K-line " + target + " not found in list, try /stats k.");
}
}
diff --git a/src/coremods/core_xline/cmd_qline.cpp b/src/coremods/core_xline/cmd_qline.cpp
index 893c8d213..086d860fc 100644
--- a/src/coremods/core_xline/cmd_qline.cpp
+++ b/src/coremods/core_xline/cmd_qline.cpp
@@ -40,14 +40,14 @@ CmdResult CommandQline::Handle(User* user, const Params& parameters)
if (parameters[0].find('@') != std::string::npos || parameters[0].find('!') != std::string::npos || parameters[0].find('.') != std::string::npos)
{
- user->WriteNotice("*** A Q-Line only bans a nick pattern, not a nick!user@host pattern.");
+ user->WriteNotice("*** A Q-line only bans a nick pattern, not a nick!user@host pattern.");
return CMD_FAILURE;
}
unsigned long duration;
if (!InspIRCd::Duration(parameters[1], duration))
{
- user->WriteNotice("*** Invalid duration for Q-line");
+ user->WriteNotice("*** Invalid duration for Q-line.");
return CMD_FAILURE;
}
QLine* ql = new QLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str());
@@ -69,7 +69,7 @@ CmdResult CommandQline::Handle(User* user, const Params& parameters)
else
{
delete ql;
- user->WriteNotice("*** Q-Line for " + parameters[0] + " already exists");
+ user->WriteNotice("*** Q-line for " + parameters[0] + " already exists.");
}
}
else
@@ -80,7 +80,7 @@ CmdResult CommandQline::Handle(User* user, const Params& parameters)
}
else
{
- user->WriteNotice("*** Q-Line " + parameters[0] + " not found in list, try /stats q.");
+ user->WriteNotice("*** Q-line " + parameters[0] + " not found in list, try /stats q.");
return CMD_FAILURE;
}
}
diff --git a/src/coremods/core_xline/cmd_zline.cpp b/src/coremods/core_xline/cmd_zline.cpp
index e81fc727f..31030adce 100644
--- a/src/coremods/core_xline/cmd_zline.cpp
+++ b/src/coremods/core_xline/cmd_zline.cpp
@@ -38,7 +38,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters)
{
if (target.find('!') != std::string::npos)
{
- user->WriteNotice("*** You cannot include a nickname in a zline, a zline must ban only an IP mask");
+ user->WriteNotice("*** You cannot include a nickname in a Z-line, a Z-line must ban only an IP mask.");
return CMD_FAILURE;
}
@@ -65,7 +65,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters)
unsigned long duration;
if (!InspIRCd::Duration(parameters[1], duration))
{
- user->WriteNotice("*** Invalid duration for Z-line");
+ user->WriteNotice("*** Invalid duration for Z-line.");
return CMD_FAILURE;
}
ZLine* zl = new ZLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ipaddr);
@@ -87,7 +87,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters)
else
{
delete zl;
- user->WriteNotice("*** Z-Line for " + std::string(ipaddr) + " already exists");
+ user->WriteNotice("*** Z-line for " + std::string(ipaddr) + " already exists.");
}
}
else
@@ -98,7 +98,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters)
}
else
{
- user->WriteNotice("*** Z-Line " + target + " not found in list, try /stats Z.");
+ user->WriteNotice("*** Z-line " + target + " not found in list, try /stats Z.");
return CMD_FAILURE;
}
}
diff --git a/src/coremods/core_xline/core_xline.cpp b/src/coremods/core_xline/core_xline.cpp
index ab80ab4ed..c53834fc0 100644
--- a/src/coremods/core_xline/core_xline.cpp
+++ b/src/coremods/core_xline/core_xline.cpp
@@ -64,18 +64,27 @@ class CoreModXLine : public Module
{
}
+ void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE
+ {
+ if (user->quitting)
+ return;
+
+ user->exempt = (ServerInstance->XLines->MatchesLine("E", user) != NULL);
+ user->CheckLines(true);
+ }
+
ModResult OnUserPreNick(LocalUser* user, const std::string& newnick) CXX11_OVERRIDE
{
- // Check Q-Lines (for local nick changes only, remote servers have our Q-Lines to enforce themselves)
+ // Check Q-lines (for local nick changes only, remote servers have our Q-lines to enforce themselves)
XLine* xline = ServerInstance->XLines->MatchesLine("Q", newnick);
if (!xline)
return MOD_RES_PASSTHRU; // No match
- // A Q-Line matched the new nick, tell opers if the user is registered
+ // A Q-line matched the new nick, tell opers if the user is registered
if (user->registered == REG_ALL)
{
- ServerInstance->SNO->WriteGlobalSno('a', "Q-Lined nickname %s from %s: %s",
+ ServerInstance->SNO->WriteGlobalSno('a', "Q-lined nickname %s from %s: %s",
newnick.c_str(), user->GetFullRealHost().c_str(), xline->reason.c_str());
}
diff --git a/src/coremods/core_xline/core_xline.h b/src/coremods/core_xline/core_xline.h
index 1e0bc74cc..c607797f1 100644
--- a/src/coremods/core_xline/core_xline.h
+++ b/src/coremods/core_xline/core_xline.h
@@ -70,7 +70,7 @@ class InsaneBan
class CommandEline : public Command
{
public:
- /** Constructor for eline.
+ /** Constructor for E-line.
*/
CommandEline(Module* parent);
@@ -87,7 +87,7 @@ class CommandEline : public Command
class CommandGline : public Command
{
public:
- /** Constructor for gline.
+ /** Constructor for G-line.
*/
CommandGline(Module* parent);
@@ -104,7 +104,7 @@ class CommandGline : public Command
class CommandKline : public Command
{
public:
- /** Constructor for kline.
+ /** Constructor for K-line.
*/
CommandKline(Module* parent);
@@ -127,7 +127,7 @@ class CommandQline : public Command
};
public:
- /** Constructor for qline.
+ /** Constructor for Q-line.
*/
CommandQline(Module* parent);
@@ -150,7 +150,7 @@ class CommandZline : public Command
};
public:
- /** Constructor for zline.
+ /** Constructor for Z-line.
*/
CommandZline(Module* parent);
diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp
index 8febcbb5f..a51430a4b 100644
--- a/src/hashcomp.cpp
+++ b/src/hashcomp.cpp
@@ -193,8 +193,8 @@ size_t irc::insensitive::operator()(const std::string &s) const
return t;
}
-irc::tokenstream::tokenstream(const std::string& msg, size_t start)
- : message(msg, start)
+irc::tokenstream::tokenstream(const std::string& msg, size_t start, size_t end)
+ : message(msg, start, end)
, position(0)
{
}
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 7e299700b..09e48ea1f 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -442,7 +442,6 @@ InspIRCd::InspIRCd(int argc, char** argv) :
// Build ISupport as ModuleManager::LoadAll() does not do it
this->ISupport.Build();
- Config->ApplyDisabledCommands();
if (!pl.empty())
{
diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp
index 69c427212..ebbff448e 100644
--- a/src/inspsocket.cpp
+++ b/src/inspsocket.cpp
@@ -358,6 +358,11 @@ void StreamSocket::FlushSendQ(SendQueue& sq)
}
}
+bool StreamSocket::OnSetEndPoint(const irc::sockets::sockaddrs& local, const irc::sockets::sockaddrs& remote)
+{
+ return false;
+}
+
void StreamSocket::WriteData(const std::string &data)
{
if (fd < 0)
diff --git a/src/mode.cpp b/src/mode.cpp
index 0bb97cc9e..459eb21c8 100644
--- a/src/mode.cpp
+++ b/src/mode.cpp
@@ -312,17 +312,6 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode
}
}
- if (IS_LOCAL(user) && !user->IsOper())
- {
- 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));
- return MODEACTION_DENY;
- }
- }
-
if ((adding) && (IS_LOCAL(user)) && (mh->NeedsOper()) && (!user->HasModePermission(mh)))
{
/* It's an oper only mode, and they don't have access to it. */
@@ -587,7 +576,8 @@ ModeHandler::Id ModeParser::AllocateModeId(ModeType mt)
void ModeParser::AddMode(ModeHandler* mh)
{
if (!ModeParser::IsModeChar(mh->GetModeChar()))
- throw ModuleException("Invalid letter for mode " + mh->name);
+ throw ModuleException(InspIRCd::Format("Mode letter for %s is invalid: %c",
+ mh->name.c_str(), mh->GetModeChar()));
/* A mode prefix of ',' is not acceptable, it would fuck up server to server.
* A mode prefix of ':' will fuck up both server to server, and client to server.
@@ -597,15 +587,19 @@ void ModeParser::AddMode(ModeHandler* mh)
if (pm)
{
if ((pm->GetPrefix() > 126) || (pm->GetPrefix() == ',') || (pm->GetPrefix() == ':') || (pm->GetPrefix() == '#'))
- throw ModuleException("Invalid prefix for mode " + mh->name);
+ throw ModuleException(InspIRCd::Format("Mode prefix for %s is invalid: %c",
+ mh->name.c_str(), pm->GetPrefix()));
- if (FindPrefix(pm->GetPrefix()))
- throw ModuleException("Prefix already exists for mode " + mh->name);
+ PrefixMode* otherpm = FindPrefix(pm->GetPrefix());
+ if (otherpm)
+ throw ModuleException(InspIRCd::Format("Mode prefix for %s already by used by %s from %s: %c",
+ mh->name.c_str(), otherpm->name.c_str(), otherpm->creator->ModuleSourceFile.c_str(), pm->GetPrefix()));
}
ModeHandler*& slot = modehandlers[mh->GetModeType()][mh->GetModeChar()-65];
if (slot)
- throw ModuleException("Letter is already in use for mode " + mh->name);
+ throw ModuleException(InspIRCd::Format("Mode letter for %s already by used by %s from %s: %c",
+ mh->name.c_str(), slot->name.c_str(), slot->creator->ModuleSourceFile.c_str(), mh->GetModeChar()));
// The mode needs an id if it is either a user mode, a simple mode (flag) or a parameter mode.
// Otherwise (for listmodes and prefix modes) the id remains MODEID_MAX, which is invalid.
@@ -613,8 +607,13 @@ void ModeParser::AddMode(ModeHandler* mh)
if ((mh->GetModeType() == MODETYPE_USER) || (mh->IsParameterMode()) || (!mh->IsListMode()))
modeid = AllocateModeId(mh->GetModeType());
- if (!modehandlersbyname[mh->GetModeType()].insert(std::make_pair(mh->name, mh)).second)
- throw ModuleException("Mode name already in use: " + mh->name);
+ std::pair<ModeHandlerMap::iterator, bool> res = modehandlersbyname[mh->GetModeType()].insert(std::make_pair(mh->name, mh));
+ if (!res.second)
+ {
+ ModeHandler* othermh = res.first->second;
+ throw ModuleException(InspIRCd::Format("Mode name %s already used by %c from %s",
+ mh->name.c_str(), othermh->GetModeChar(), othermh->creator->ModuleSourceFile.c_str()));
+ }
// Everything is fine, add the mode
diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp
index 4d1dd65c9..3e00db765 100644
--- a/src/modules/m_alias.cpp
+++ b/src/modules/m_alias.cpp
@@ -107,6 +107,7 @@ class ModuleAlias : public Module
ModuleAlias()
: botmode(this, "bot")
+ , active(false)
{
}
diff --git a/src/modules/m_cban.cpp b/src/modules/m_cban.cpp
index e0768aa88..3cdbbbdfb 100644
--- a/src/modules/m_cban.cpp
+++ b/src/modules/m_cban.cpp
@@ -114,7 +114,7 @@ class CommandCBan : public Command
unsigned long duration;
if (!InspIRCd::Duration(parameters[1], duration))
{
- user->WriteNotice("*** Invalid duration for CBan");
+ user->WriteNotice("*** Invalid duration for CBan.");
return CMD_FAILURE;
}
const char *reason = (parameters.size() > 2) ? parameters[2].c_str() : "No reason supplied";
@@ -202,7 +202,7 @@ class ModuleCBan : public Module, public Stats::EventListener
Version GetVersion() CXX11_OVERRIDE
{
- return Version("Gives /cban, aka C:lines. Think Q:lines, for channels.", VF_COMMON | VF_VENDOR);
+ return Version("Gives /cban, aka C-lines. Think Q-lines, for channels.", VF_COMMON | VF_VENDOR);
}
};
diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp
index 4a5a4fb03..df8201bde 100644
--- a/src/modules/m_cgiirc.cpp
+++ b/src/modules/m_cgiirc.cpp
@@ -34,29 +34,6 @@ enum
RPL_WHOISGATEWAY = 350
};
-// We need this method up here so that it can be accessed from anywhere
-static void ChangeIP(LocalUser* user, const irc::sockets::sockaddrs& sa)
-{
- // Set the users IP address and make sure they are in the right clone pool.
- ServerInstance->Users->RemoveCloneCounts(user);
- user->SetClientIP(sa);
- ServerInstance->Users->AddClone(user);
- if (user->quitting)
- return;
-
- // Recheck the connect class.
- user->MyClass = NULL;
- user->SetClass();
- user->CheckClass();
- if (user->quitting)
- return;
-
- // Check if this user matches any XLines.
- user->CheckLines(true);
- if (user->quitting)
- return;
-}
-
// Encapsulates information about an ident host.
class IdentHost
{
@@ -215,7 +192,7 @@ class CommandWebIRC : public SplitCommand
// Set the IP address sent via WEBIRC. We ignore the hostname and lookup
// instead do our own DNS lookups because of unreliable gateways.
- ChangeIP(user, ipaddr);
+ user->SetClientIP(ipaddr);
return CMD_SUCCESS;
}
@@ -391,7 +368,7 @@ class ModuleCgiIRC
user->uuid.c_str(), user->GetIPString().c_str(), address.addr().c_str(), user->ident.c_str(), newident.c_str());
user->ChangeIdent(newident);
- ChangeIP(user, address);
+ user->SetClientIP(address);
break;
}
return MOD_RES_PASSTHRU;
diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp
index f820f2bd0..1d030acc6 100644
--- a/src/modules/m_check.cpp
+++ b/src/modules/m_check.cpp
@@ -200,7 +200,7 @@ class CommandCheck : public Command
opcmdlist.Add(oper->AllowedOperCommands.ToString());
opcmdlist.Flush();
CheckContext::List privlist(context, "permissions");
- opcmdlist.Add(oper->AllowedPrivs.ToString());
+ privlist.Add(oper->AllowedPrivs.ToString());
privlist.Flush();
}
}
diff --git a/src/modules/m_clearchan.cpp b/src/modules/m_clearchan.cpp
index 016d28737..dec49866c 100644
--- a/src/modules/m_clearchan.cpp
+++ b/src/modules/m_clearchan.cpp
@@ -211,7 +211,7 @@ class ModuleClearChan : public Module
Version GetVersion() CXX11_OVERRIDE
{
- return Version("Adds /CLEARCHAN that allows opers to masskick, masskill or mass-G/ZLine users on a channel", VF_VENDOR|VF_OPTCOMMON);
+ return Version("Adds /CLEARCHAN that allows opers to masskick, masskill or mass G/Z-line users on a channel.", VF_VENDOR|VF_OPTCOMMON);
}
};
diff --git a/src/modules/m_conn_umodes.cpp b/src/modules/m_conn_umodes.cpp
index 1f2fe7455..3132aed40 100644
--- a/src/modules/m_conn_umodes.cpp
+++ b/src/modules/m_conn_umodes.cpp
@@ -38,10 +38,6 @@ class ModuleModesOnConnect : public Module
void OnUserConnect(LocalUser* user) CXX11_OVERRIDE
{
- // Backup and zero out the disabled usermodes, so that we can override them here.
- const std::bitset<64> save = ServerInstance->Config->DisabledUModes;
- ServerInstance->Config->DisabledUModes.reset();
-
ConfigTag* tag = user->MyClass->config;
std::string ThisModes = tag->getString("modes");
if (!ThisModes.empty())
@@ -58,8 +54,6 @@ class ModuleModesOnConnect : public Module
ServerInstance->Parser.CallHandler("MODE", modes, user);
}
-
- ServerInstance->Config->DisabledUModes = save;
}
};
diff --git a/src/modules/m_connectban.cpp b/src/modules/m_connectban.cpp
index d57ffca02..20121f5f9 100644
--- a/src/modules/m_connectban.cpp
+++ b/src/modules/m_connectban.cpp
@@ -73,7 +73,7 @@ class ModuleConnectBan : public Module
if (i->second >= threshold)
{
- // Create zline for set duration.
+ // Create Z-line for set duration.
ZLine* zl = new ZLine(ServerInstance->Time(), banduration, ServerInstance->Config->ServerName, banmessage, mask.str());
if (!ServerInstance->XLines->AddLine(zl, NULL))
{
@@ -83,7 +83,7 @@ class ModuleConnectBan : public Module
ServerInstance->XLines->ApplyLines();
std::string maskstr = mask.str();
std::string timestr = InspIRCd::TimeString(zl->expiry);
- ServerInstance->SNO->WriteGlobalSno('x',"Module m_connectban added Z:line on *@%s to expire on %s: Connect flooding",
+ ServerInstance->SNO->WriteGlobalSno('x',"Module m_connectban added Z-line on %s to expire on %s: Connect flooding",
maskstr.c_str(), timestr.c_str());
ServerInstance->SNO->WriteGlobalSno('a', "Connect flooding from IP range %s (%d)", maskstr.c_str(), threshold);
connects.erase(i);
diff --git a/src/modules/m_disable.cpp b/src/modules/m_disable.cpp
new file mode 100644
index 000000000..203f9ee64
--- /dev/null
+++ b/src/modules/m_disable.cpp
@@ -0,0 +1,189 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2019 Peter Powell <petpow@saberuk.com>
+ *
+ * This file is part of InspIRCd. InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "inspircd.h"
+
+enum
+{
+ // From ircu.
+ ERR_DISABLED = 517
+};
+
+// Holds a list of disabled commands.
+typedef std::vector<std::string> CommandList;
+
+// Holds whether modes are disabled or not.
+typedef std::bitset<64> ModeStatus;
+
+class ModuleDisable : public Module
+{
+ private:
+ CommandList commands;
+ ModeStatus chanmodes;
+ bool fakenonexistent;
+ bool notifyopers;
+ ModeStatus usermodes;
+
+ void ReadModes(ConfigTag* tag, const std::string& field, ModeType type, ModeStatus& status)
+ {
+ const std::string modes = tag->getString(field);
+ for (std::string::const_iterator iter = modes.begin(); iter != modes.end(); ++iter)
+ {
+ const char& chr = *iter;
+
+ // Check that the character is a valid mode letter.
+ if (!ModeParser::IsModeChar(chr))
+ throw ModuleException(InspIRCd::Format("Invalid mode '%c' was specified in <disabled:%s> at %s",
+ chr, field.c_str(), tag->getTagLocation().c_str()));
+
+ // Check that the mode actually exists.
+ ModeHandler* mh = ServerInstance->Modes->FindMode(chr, type);
+ if (!chr)
+ throw ModuleException(InspIRCd::Format("Non-existent mode '%c' was specified in <disabled:%s> at %s",
+ chr, field.c_str(), tag->getTagLocation().c_str()));
+
+ // Disable the mode.
+ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "The %c (%s) %s mode has been disabled",
+ mh->GetModeChar(), mh->name.c_str(), type == MODETYPE_CHANNEL ? "channel" : "user");
+ status.set(chr - 'A');
+ }
+ }
+
+ void WriteLog(const char* message, ...) CUSTOM_PRINTF(2, 3)
+ {
+ std::string buffer;
+ VAFORMAT(buffer, message, message);
+
+ if (notifyopers)
+ ServerInstance->SNO->WriteToSnoMask('a', buffer);
+ else
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, buffer);
+ }
+
+ public:
+ void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
+ {
+ ConfigTag* tag = ServerInstance->Config->ConfValue("disabled");
+
+ // Parse the disabled commands.
+ CommandList newcommands;
+ irc::spacesepstream commandlist(tag->getString("commands"));
+ for (std::string command; commandlist.GetToken(command); )
+ {
+ // Check that the command actually exists.
+ Command* handler = ServerInstance->Parser.GetHandler(command);
+ if (!handler)
+ throw ModuleException(InspIRCd::Format("Non-existent command '%s' was specified in <disabled:commands> at %s",
+ command.c_str(), tag->getTagLocation().c_str()));
+
+ // Prevent admins from disabling COMMANDS and MODULES for transparency reasons.
+ if (handler->name == "COMMANDS" || handler->name == "MODULES")
+ continue;
+
+ // Disable the command.
+ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "The %s command has been disabled", handler->name.c_str());
+ newcommands.push_back(handler->name);
+ }
+
+ // Parse the disabled channel modes.
+ ModeStatus newchanmodes;
+ ReadModes(tag, "chanmodes", MODETYPE_CHANNEL, newchanmodes);
+
+ // Parse the disabled user modes.
+ ModeStatus newusermodes;
+ ReadModes(tag, "usermodes", MODETYPE_USER, newusermodes);
+
+ // The server config was valid so we can use these now.
+ chanmodes = newchanmodes;
+ usermodes = newusermodes;
+ commands.swap(newcommands);
+
+ // Whether we should fake the non-existence of disabled things.
+ fakenonexistent = tag->getBool("fakenonexistent", tag->getBool("fakenonexistant"));
+
+ // Whether to notify server operators via snomask `a` about the attempted use of disabled commands/modes.
+ notifyopers = tag->getBool("notifyopers");
+ }
+
+ ModResult OnPreCommand(std::string& command, CommandBase::Params& parameters, LocalUser* user, bool validated) CXX11_OVERRIDE
+ {
+ // If a command is unvalidated or the source is not registered we do nothing.
+ if (!validated || user->registered != REG_ALL)
+ return MOD_RES_PASSTHRU;
+
+ // If the command is not disabled or the user has the servers/use-disabled-commands priv we do nothing.
+ if (!stdalgo::isin(commands, command) || user->HasPrivPermission("servers/use-disabled-commands"))
+ return MOD_RES_PASSTHRU;
+
+ // The user has tried to execute a disabled command!
+ user->CommandFloodPenalty += 2000;
+ WriteLog("%s was blocked from executing the disabled %s command", user->GetFullRealHost().c_str(), command.c_str());
+
+ if (fakenonexistent)
+ {
+ // The server administrator has specified that disabled commands should be
+ // treated as if they do not exist.
+ user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "Unknown command");
+ ServerInstance->stats.Unknown++;
+ return MOD_RES_DENY;
+ }
+
+ // Inform the user that the command they executed has been disabled.
+ user->WriteNumeric(ERR_DISABLED, command, "Command disabled");
+ return MOD_RES_DENY;
+ }
+
+ ModResult OnRawMode(User* user, Channel* chan, ModeHandler* mh, const std::string& param, bool adding) CXX11_OVERRIDE
+ {
+ // If a mode change is remote or the source is not registered we do nothing.
+ if (!IS_LOCAL(user) || user->registered != REG_ALL)
+ return MOD_RES_PASSTHRU;
+
+ // If the mode is not disabled or the user has the servers/use-disabled-modes priv we do nothing.
+ const std::bitset<64>& disabled = (mh->GetModeType() == MODETYPE_CHANNEL) ? chanmodes : usermodes;
+ if (!disabled.test(mh->GetModeChar() - 'A') || user->HasPrivPermission("servers/use-disabled-modes"))
+ return MOD_RES_PASSTHRU;
+
+ // The user has tried to change a disabled mode!
+ const char* what = mh->GetModeType() == MODETYPE_CHANNEL ? "channel" : "user";
+ WriteLog("%s was blocked from executing the disabled %s mode %c (%s)",
+ user->GetFullRealHost().c_str(), what, mh->GetModeChar(), mh->name.c_str());
+
+ if (fakenonexistent)
+ {
+ // The server administrator has specified that disabled modes should be
+ // treated as if they do not exist.
+ user->WriteNumeric(mh->GetModeType() == MODETYPE_CHANNEL ? ERR_UNKNOWNMODE : ERR_UNKNOWNSNOMASK,
+ mh->GetModeChar(), "is unknown mode char to me");
+ return MOD_RES_DENY;
+ }
+
+ // Inform the user that the mode they changed has been disabled.
+ user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - %s mode %c (%s) is disabled",
+ what, mh->GetModeChar(), mh->name.c_str()));
+ return MOD_RES_DENY;
+ }
+
+ Version GetVersion() CXX11_OVERRIDE
+ {
+ return Version("Provides support for disabling commands and modes", VF_VENDOR);
+ }
+};
+
+MODULE_INIT(ModuleDisable)
diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp
index d1ca800b3..eade39bd7 100644
--- a/src/modules/m_dnsbl.cpp
+++ b/src/modules/m_dnsbl.cpp
@@ -148,7 +148,7 @@ class DNSBLResolver : public DNS::Request
if (ServerInstance->XLines->AddLine(kl,NULL))
{
std::string timestr = InspIRCd::TimeString(kl->expiry);
- ServerInstance->SNO->WriteGlobalSno('x',"K:line added due to DNSBL match on *@%s to expire on %s: %s",
+ ServerInstance->SNO->WriteGlobalSno('x', "K-line added due to DNSBL match on *@%s to expire on %s: %s",
them->GetIPString().c_str(), timestr.c_str(), reason.c_str());
ServerInstance->XLines->ApplyLines();
}
@@ -166,7 +166,7 @@ class DNSBLResolver : public DNS::Request
if (ServerInstance->XLines->AddLine(gl,NULL))
{
std::string timestr = InspIRCd::TimeString(gl->expiry);
- ServerInstance->SNO->WriteGlobalSno('x',"G:line added due to DNSBL match on *@%s to expire on %s: %s",
+ ServerInstance->SNO->WriteGlobalSno('x', "G-line added due to DNSBL match on *@%s to expire on %s: %s",
them->GetIPString().c_str(), timestr.c_str(), reason.c_str());
ServerInstance->XLines->ApplyLines();
}
@@ -184,7 +184,7 @@ class DNSBLResolver : public DNS::Request
if (ServerInstance->XLines->AddLine(zl,NULL))
{
std::string timestr = InspIRCd::TimeString(zl->expiry);
- ServerInstance->SNO->WriteGlobalSno('x',"Z:line added due to DNSBL match on %s to expire on %s: %s",
+ ServerInstance->SNO->WriteGlobalSno('x', "Z-line added due to DNSBL match on %s to expire on %s: %s",
them->GetIPString().c_str(), timestr.c_str(), reason.c_str());
ServerInstance->XLines->ApplyLines();
}
@@ -420,10 +420,14 @@ class ModuleDNSBL : public Module, public Stats::EventListener
std::string dnsbl;
if (!myclass->config->readString("dnsbl", dnsbl))
return MOD_RES_PASSTHRU;
+
std::string* match = nameExt.get(user);
- std::string myname = match ? *match : "";
- if (dnsbl == myname)
+ if (!match)
+ return MOD_RES_PASSTHRU;
+
+ if (InspIRCd::Match(*match, dnsbl))
return MOD_RES_PASSTHRU;
+
return MOD_RES_DENY;
}
diff --git a/src/modules/m_filter.cpp b/src/modules/m_filter.cpp
index 0c8b81e4b..849f99086 100644
--- a/src/modules/m_filter.cpp
+++ b/src/modules/m_filter.cpp
@@ -421,7 +421,7 @@ ModResult ModuleFilter::OnUserPreMessage(User* user, const MessageTarget& msgtar
else if (f->action == FA_GLINE)
{
GLine* gl = new GLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), "*", user->GetIPString());
- ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was glined because their message to %s matched %s (%s)",
+ ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was G-lined because their message to %s matched %s (%s)",
user->nick.c_str(), target.c_str(), f->freeform.c_str(), f->reason.c_str()));
if (ServerInstance->XLines->AddLine(gl,NULL))
{
@@ -433,7 +433,7 @@ ModResult ModuleFilter::OnUserPreMessage(User* user, const MessageTarget& msgtar
else if (f->action == FA_ZLINE)
{
ZLine* zl = new ZLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), user->GetIPString());
- ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was zlined because their message to %s matched %s (%s)",
+ ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was Z-lined because their message to %s matched %s (%s)",
user->nick.c_str(), target.c_str(), f->freeform.c_str(), f->reason.c_str()));
if (ServerInstance->XLines->AddLine(zl,NULL))
{
@@ -506,9 +506,9 @@ ModResult ModuleFilter::OnPreCommand(std::string& command, CommandBase::Params&
}
if (f->action == FA_GLINE)
{
- /* Note: We gline *@IP so that if their host doesnt resolve the gline still applies. */
+ /* Note: We G-line *@IP so that if their host doesn't resolve the G-line still applies. */
GLine* gl = new GLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), "*", user->GetIPString());
- ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was glined because their %s message matched %s (%s)",
+ ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was G-lined because their %s message matched %s (%s)",
user->nick.c_str(), command.c_str(), f->freeform.c_str(), f->reason.c_str()));
if (ServerInstance->XLines->AddLine(gl,NULL))
@@ -521,7 +521,7 @@ ModResult ModuleFilter::OnPreCommand(std::string& command, CommandBase::Params&
if (f->action == FA_ZLINE)
{
ZLine* zl = new ZLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), user->GetIPString());
- ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was zlined because their %s message matched %s (%s)",
+ ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was Z-lined because their %s message matched %s (%s)",
user->nick.c_str(), command.c_str(), f->freeform.c_str(), f->reason.c_str()));
if (ServerInstance->XLines->AddLine(zl,NULL))
diff --git a/src/modules/m_haproxy.cpp b/src/modules/m_haproxy.cpp
index e92c45686..ee9079cbf 100644
--- a/src/modules/m_haproxy.cpp
+++ b/src/modules/m_haproxy.cpp
@@ -240,7 +240,7 @@ class HAProxyHook : public IOHookMiddle
{
case AF_INET:
memcpy(&client.in4.sin_addr.s_addr, &recvq[0], 4);
- memcpy(&server.in4.sin_addr.s_addr, &recvq[4], 8);
+ memcpy(&server.in4.sin_addr.s_addr, &recvq[4], 4);
memcpy(&client.in4.sin_port, &recvq[8], 2);
memcpy(&server.in4.sin_port, &recvq[10], 2);
tlv_index = 12;
@@ -256,12 +256,13 @@ class HAProxyHook : public IOHookMiddle
case AF_UNIX:
memcpy(client.un.sun_path, &recvq[0], 108);
- memcpy(client.un.sun_path, &recvq[108], 108);
+ memcpy(server.un.sun_path, &recvq[108], 108);
tlv_index = 216;
break;
}
- sock->OnSetEndPoint(server, client);
+ if (!sock->OnSetEndPoint(server, client))
+ return -1;
// Parse any available TLVs.
while (tlv_index < address_length)
diff --git a/src/modules/m_hostchange.cpp b/src/modules/m_hostchange.cpp
index 201c4b59b..4c9b24140 100644
--- a/src/modules/m_hostchange.cpp
+++ b/src/modules/m_hostchange.cpp
@@ -47,7 +47,7 @@ class HostRule
std::string suffix;
public:
- HostRule(const std::string& Host, const std::string& Mask, const insp::flat_set<int>& Ports)
+ HostRule(const std::string& Mask, const std::string& Host, const insp::flat_set<int>& Ports)
: action(HCA_SET)
, host(Host)
, mask(Mask)
diff --git a/src/modules/m_ident.cpp b/src/modules/m_ident.cpp
index ca12a9ba3..803c19846 100644
--- a/src/modules/m_ident.cpp
+++ b/src/modules/m_ident.cpp
@@ -275,12 +275,24 @@ class ModuleIdent : public Module
NoLookupPrefix = tag->getBool("nolookupprefix", false);
}
- void OnUserInit(LocalUser *user) CXX11_OVERRIDE
+ void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE
{
+ IdentRequestSocket* isock = ext.get(user);
+ if (isock)
+ {
+ // If an ident lookup request was in progress then cancel it.
+ isock->Close();
+ ext.unset(user);
+ }
+
// The ident protocol requires that clients are connecting over a protocol with ports.
if (user->client_sa.family() != AF_INET && user->client_sa.family() != AF_INET6)
return;
+ // We don't want to look this up once the user has connected.
+ if (user->registered == REG_ALL)
+ return;
+
ConfigTag* tag = user->MyClass->config;
if (!tag->getBool("useident", true))
return;
@@ -289,7 +301,7 @@ class ModuleIdent : public Module
try
{
- IdentRequestSocket *isock = new IdentRequestSocket(user);
+ isock = new IdentRequestSocket(user);
ext.set(user, isock);
}
catch (ModuleException &e)
diff --git a/src/modules/m_ircv3_echomessage.cpp b/src/modules/m_ircv3_echomessage.cpp
index f6eae5a00..b407aece4 100644
--- a/src/modules/m_ircv3_echomessage.cpp
+++ b/src/modules/m_ircv3_echomessage.cpp
@@ -40,25 +40,26 @@ class ModuleIRCv3EchoMessage : public Module
LocalUser* const localuser = static_cast<LocalUser*>(user);
const std::string& text = details.echo_original ? details.original_text : details.text;
+ const ClientProtocol::TagMap& tags = details.echo_original ? details.tags_in : details.tags_out;
if (target.type == MessageTarget::TYPE_USER)
{
User* destuser = target.Get<User>();
ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, destuser, text, details.type);
- privmsg.AddTags(details.tags_in);
+ privmsg.AddTags(tags);
localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg);
}
else if (target.type == MessageTarget::TYPE_CHANNEL)
{
Channel* chan = target.Get<Channel>();
ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, chan, text, details.type, target.status);
- privmsg.AddTags(details.tags_in);
+ privmsg.AddTags(tags);
localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg);
}
else
{
const std::string* servername = target.Get<std::string>();
ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, *servername, text, details.type);
- privmsg.AddTags(details.tags_in);
+ privmsg.AddTags(tags);
localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg);
}
}
diff --git a/src/modules/m_passforward.cpp b/src/modules/m_passforward.cpp
index 08d3533cd..37efec02b 100644
--- a/src/modules/m_passforward.cpp
+++ b/src/modules/m_passforward.cpp
@@ -18,6 +18,7 @@
#include "inspircd.h"
+#include "modules/account.h"
class ModulePassForward : public Module
{
@@ -82,6 +83,13 @@ class ModulePassForward : public Module
if (!user->MyClass->config->getString("password").empty())
return;
+ AccountExtItem* actext = GetAccountExtItem();
+ if (actext && actext->get(user))
+ {
+ // User is logged in already (probably via SASL) don't forward the password
+ return;
+ }
+
if (!nickrequired.empty())
{
/* Check if nick exists and its server is ulined */
diff --git a/src/modules/m_rline.cpp b/src/modules/m_rline.cpp
index 77b3bc3aa..1247e81d3 100644
--- a/src/modules/m_rline.cpp
+++ b/src/modules/m_rline.cpp
@@ -32,7 +32,7 @@ class RLine : public XLine
{
public:
- /** Create a R-Line.
+ /** Create a R-line.
* @param s_time The set time
* @param d The duration of the xline
* @param src The sender of the xline
@@ -81,7 +81,7 @@ class RLine : public XLine
if (ServerInstance->XLines->AddLine(zl, NULL))
{
std::string timestr = InspIRCd::TimeString(zl->expiry);
- ServerInstance->SNO->WriteToSnoMask('x', "Z-line added due to R-line match on *@%s%s%s: %s",
+ ServerInstance->SNO->WriteToSnoMask('x', "Z-line added due to R-line match on %s%s%s: %s",
zl->ipaddr.c_str(), zl->duration ? " to expire on " : "", zl->duration ? timestr.c_str() : "", zl->reason.c_str());
added_zline = true;
}
@@ -150,7 +150,7 @@ class CommandRLine : public Command
unsigned long duration;
if (!InspIRCd::Duration(parameters[1], duration))
{
- user->WriteNotice("*** Invalid duration for R-line");
+ user->WriteNotice("*** Invalid duration for R-line.");
return CMD_FAILURE;
}
XLine *r = NULL;
@@ -184,7 +184,7 @@ class CommandRLine : public Command
else
{
delete r;
- user->WriteNotice("*** R-Line for " + parameters[0] + " already exists");
+ user->WriteNotice("*** R-line for " + parameters[0] + " already exists.");
}
}
}
@@ -196,7 +196,7 @@ class CommandRLine : public Command
}
else
{
- user->WriteNotice("*** R-Line " + parameters[0] + " not found in list, try /stats R.");
+ user->WriteNotice("*** R-line " + parameters[0] + " not found in list, try /stats R.");
}
}
@@ -279,15 +279,15 @@ class ModuleRLine : public Module, public Stats::EventListener
if (!rxfactory)
{
if (newrxengine.empty())
- ServerInstance->SNO->WriteToSnoMask('a', "WARNING: No regex engine loaded - R-Line functionality disabled until this is corrected.");
+ ServerInstance->SNO->WriteToSnoMask('a', "WARNING: No regex engine loaded - R-line functionality disabled until this is corrected.");
else
- ServerInstance->SNO->WriteToSnoMask('a', "WARNING: Regex engine '%s' is not loaded - R-Line functionality disabled until this is corrected.", newrxengine.c_str());
+ ServerInstance->SNO->WriteToSnoMask('a', "WARNING: Regex engine '%s' is not loaded - R-line functionality disabled until this is corrected.", newrxengine.c_str());
ServerInstance->XLines->DelAll(f.GetType());
}
else if ((!initing) && (rxfactory.operator->() != factory))
{
- ServerInstance->SNO->WriteToSnoMask('a', "Regex engine has changed, removing all R-Lines");
+ ServerInstance->SNO->WriteToSnoMask('a', "Regex engine has changed, removing all R-lines.");
ServerInstance->XLines->DelAll(f.GetType());
}
@@ -331,7 +331,7 @@ class ModuleRLine : public Module, public Stats::EventListener
void OnUnloadModule(Module* mod) CXX11_OVERRIDE
{
- // If the regex engine became unavailable or has changed, remove all rlines
+ // If the regex engine became unavailable or has changed, remove all R-lines.
if (!rxfactory)
{
ServerInstance->XLines->DelAll(f.GetType());
diff --git a/src/modules/m_samode.cpp b/src/modules/m_samode.cpp
index 8f28a7e9c..db3345b98 100644
--- a/src/modules/m_samode.cpp
+++ b/src/modules/m_samode.cpp
@@ -124,6 +124,9 @@ class ModuleSaMode : public Module
void Prioritize() CXX11_OVERRIDE
{
+ Module* disabled = ServerInstance->Modules->Find("m_disabled.so");
+ ServerInstance->Modules->SetPriority(this, I_OnRawMode, PRIORITY_BEFORE, disabled);
+
Module *override = ServerInstance->Modules->Find("m_override.so");
ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_BEFORE, override);
}
diff --git a/src/modules/m_shun.cpp b/src/modules/m_shun.cpp
index e4fb2c11d..6453ace81 100644
--- a/src/modules/m_shun.cpp
+++ b/src/modules/m_shun.cpp
@@ -92,7 +92,7 @@ class CommandShun : public Command
{
if (!InspIRCd::Duration(parameters[1], duration))
{
- user->WriteNotice("*** Invalid duration for SHUN");
+ user->WriteNotice("*** Invalid duration for SHUN.");
return CMD_FAILURE;
}
expr = parameters[2];
@@ -122,7 +122,7 @@ class CommandShun : public Command
else
{
delete r;
- user->WriteNotice("*** Shun for " + target + " already exists");
+ user->WriteNotice("*** Shun for " + target + " already exists.");
return CMD_FAILURE;
}
}
diff --git a/src/modules/m_spanningtree/away.cpp b/src/modules/m_spanningtree/away.cpp
index 13972589b..62300580f 100644
--- a/src/modules/m_spanningtree/away.cpp
+++ b/src/modules/m_spanningtree/away.cpp
@@ -47,6 +47,6 @@ CmdResult CommandAway::HandleRemote(::RemoteUser* u, Params& params)
CommandAway::Builder::Builder(User* user)
: CmdBuilder(user, "AWAY")
{
- if (user->awaymsg.empty())
+ if (!user->awaymsg.empty())
push_int(user->awaytime).push_last(user->awaymsg);
}
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp
index 985762872..de1e8eb19 100644
--- a/src/modules/m_spanningtree/main.cpp
+++ b/src/modules/m_spanningtree/main.cpp
@@ -324,8 +324,12 @@ ModResult ModuleSpanningTree::HandleVersion(const CommandBase::Params& parameter
// If it's empty it might be that the server is still syncing (full version hasn't arrived yet)
// or the server is a 2.0 server and does not send a full version.
bool showfull = ((user->IsOper()) && (!found->GetFullVersion().empty()));
- const std::string& Version = (showfull ? found->GetFullVersion() : found->GetVersion());
- user->WriteNumeric(RPL_VERSION, Version);
+
+ Numeric::Numeric numeric(RPL_VERSION);
+ irc::tokenstream tokens(showfull ? found->GetFullVersion() : found->GetVersion());
+ for (std::string token; tokens.GetTrailing(token); )
+ numeric.push(token);
+ user->WriteNumeric(numeric);
}
else
{
diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h
index 878b34ad7..6206448c1 100644
--- a/src/modules/m_spanningtree/treesocket.h
+++ b/src/modules/m_spanningtree/treesocket.h
@@ -259,7 +259,7 @@ class TreeSocket : public BufferedSocket
*/
void SendFJoins(Channel* c);
- /** Send G, Q, Z and E lines */
+ /** Send G-, Q-, Z- and E-lines */
void SendXLines();
/** Send all known information about a channel */
diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp
index dc24802fb..45f8a380f 100644
--- a/src/modules/m_spanningtree/treesocket2.cpp
+++ b/src/modules/m_spanningtree/treesocket2.cpp
@@ -292,7 +292,7 @@ void TreeSocket::ProcessTag(User* source, const std::string& tag, ClientProtocol
for (Events::ModuleEventProvider::SubscriberList::const_iterator i = list.begin(); i != list.end(); ++i)
{
ClientProtocol::MessageTagProvider* const tagprov = static_cast<ClientProtocol::MessageTagProvider*>(*i);
- const ModResult res = tagprov->OnClientProtocolProcessTag(source, tagkey, tagval);
+ const ModResult res = tagprov->OnProcessTag(source, tagkey, tagval);
if (res == MOD_RES_ALLOW)
tags.insert(std::make_pair(tagkey, ClientProtocol::MessageTagData(tagprov, tagval)));
else if (res == MOD_RES_DENY)
diff --git a/src/modules/m_sslinfo.cpp b/src/modules/m_sslinfo.cpp
index 54aeb9755..30dfd9a76 100644
--- a/src/modules/m_sslinfo.cpp
+++ b/src/modules/m_sslinfo.cpp
@@ -54,8 +54,7 @@ class SSLCertExt : public ExtensionItem
void unset(Extensible* container)
{
- void* old = unset_raw(container);
- delete static_cast<std::string*>(old);
+ free(container, unset_raw(container));
}
std::string serialize(SerializeFormat format, const Extensible* container, void* item) const CXX11_OVERRIDE
diff --git a/src/modules/m_svshold.cpp b/src/modules/m_svshold.cpp
index 52c250fef..0aaf113f0 100644
--- a/src/modules/m_svshold.cpp
+++ b/src/modules/m_svshold.cpp
@@ -76,7 +76,7 @@ class SVSHoldFactory : public XLineFactory
public:
SVSHoldFactory() : XLineFactory("SVSHOLD") { }
- /** Generate a shun
+ /** Generate an SVSHOLD
*/
XLine* Generate(time_t set_time, unsigned long duration, const std::string& source, const std::string& reason, const std::string& xline_specific_mask) CXX11_OVERRIDE
{
@@ -130,7 +130,7 @@ class CommandSvshold : public Command
unsigned long duration;
if (!InspIRCd::Duration(parameters[1], duration))
{
- user->WriteNotice("*** Invalid duration for SVSHOLD");
+ user->WriteNotice("*** Invalid duration for SVSHOLD.");
return CMD_FAILURE;
}
SVSHold* r = new SVSHold(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str());
@@ -221,7 +221,7 @@ class ModuleSVSHold : public Module, public Stats::EventListener
Version GetVersion() CXX11_OVERRIDE
{
- return Version("Implements SVSHOLD. Like Q:Lines, but can only be added/removed by Services.", VF_COMMON | VF_VENDOR);
+ return Version("Implements SVSHOLD. Like Q-lines, but can only be added/removed by Services.", VF_COMMON | VF_VENDOR);
}
};
diff --git a/src/snomasks.cpp b/src/snomasks.cpp
index 0b266ff7e..e39fb84fb 100644
--- a/src/snomasks.cpp
+++ b/src/snomasks.cpp
@@ -69,8 +69,8 @@ SnomaskManager::SnomaskManager()
EnableSnomask('q',"QUIT"); /* Local quit notices */
EnableSnomask('k',"KILL"); /* Kill notices */
EnableSnomask('o',"OPER"); /* Oper up/down notices */
- EnableSnomask('a',"ANNOUNCEMENT"); /* formerly WriteOpers() - generic notices to all opers */
- EnableSnomask('x',"XLINE"); /* Xline notice (g/z/q/k/e) */
+ EnableSnomask('a',"ANNOUNCEMENT"); /* formerly WriteOpers() - generic notices to all opers */
+ EnableSnomask('x',"XLINE"); /* X-line notices (G/Z/Q/K/E/R/SHUN/CBan) */
EnableSnomask('t',"STATS"); /* Local or remote stats request */
}
diff --git a/src/usermanager.cpp b/src/usermanager.cpp
index 6f9d15502..053a308cb 100644
--- a/src/usermanager.cpp
+++ b/src/usermanager.cpp
@@ -76,6 +76,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs
this->clientlist[New->nick] = New;
this->AddClone(New);
this->local_users.push_front(New);
+ FOREACH_MOD(OnUserInit, (New));
if (!SocketEngine::AddFd(eh, FD_WANT_FAST_READ | FD_WANT_EDGE_WRITE))
{
@@ -132,7 +133,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs
New->WriteNumeric(ERR_YOUREBANNEDCREEP, ServerInstance->Config->XLineMessage);
if (ServerInstance->Config->HideBans)
- this->QuitUser(New, b->Type + "-Lined", &b->Reason);
+ this->QuitUser(New, b->Type + "-lined", &b->Reason);
else
this->QuitUser(New, b->Reason);
return;
@@ -162,8 +163,6 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs
FOREACH_MOD(OnSetUserIP, (New));
if (New->quitting)
return;
-
- FOREACH_MOD(OnUserInit, (New));
}
void UserManager::QuitUser(User* user, const std::string& quitreason, const std::string* operreason)
diff --git a/src/users.cpp b/src/users.cpp
index f11a7a380..506cdf6d8 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -239,23 +239,30 @@ void UserIOHandler::OnDataReady()
if (!user->HasPrivPermission("users/flood/no-fakelag"))
penaltymax = user->MyClass->GetPenaltyThreshold() * 1000;
- // The maximum size of an IRC message minus the terminating CR+LF.
- const size_t maxmessage = ServerInstance->Config->Limits.MaxLine - 2;
+ // The cleaned message sent by the user or empty if not found yet.
std::string line;
- line.reserve(maxmessage);
- bool eol_found;
+ // The position of the most \n character or npos if not found yet.
+ std::string::size_type eolpos;
+
+ // The position within the recvq of the current character.
std::string::size_type qpos;
while (user->CommandFloodPenalty < penaltymax && getSendQSize() < sendqmax)
{
- qpos = 0;
- eol_found = false;
+ // Check the newly received data for an EOL.
+ eolpos = recvq.find('\n', checked_until);
+ if (eolpos == std::string::npos)
+ {
+ checked_until = recvq.length();
+ return;
+ }
- const size_t qlen = recvq.length();
- while (qpos < qlen)
+ // We've found a line! Clean it up and move it to the line buffer.
+ line.reserve(eolpos);
+ for (qpos = 0; qpos < eolpos; ++qpos)
{
- char c = recvq[qpos++];
+ char c = recvq[qpos];
switch (c)
{
case '\0':
@@ -263,25 +270,14 @@ void UserIOHandler::OnDataReady()
break;
case '\r':
continue;
- case '\n':
- eol_found = true;
- break;
}
- if (eol_found)
- break;
-
- if (line.length() < maxmessage)
- line.push_back(c);
+ line.push_back(c);
}
- // if we return here, we haven't found a newline and make no modifications to recvq
- // so we can wait for more data
- if (!eol_found)
- return;
-
// just found a newline. Terminate the string, and pull it out of recvq
- recvq.erase(0, qpos);
+ recvq.erase(0, eolpos + 1);
+ checked_until = 0;
// TODO should this be moved to when it was inserted in recvq?
ServerInstance->stats.Recv += qpos;
@@ -318,10 +314,11 @@ void UserIOHandler::AddWriteBuf(const std::string &data)
WriteData(data);
}
-void UserIOHandler::OnSetEndPoint(const irc::sockets::sockaddrs& server, const irc::sockets::sockaddrs& client)
+bool UserIOHandler::OnSetEndPoint(const irc::sockets::sockaddrs& server, const irc::sockets::sockaddrs& client)
{
memcpy(&user->server_sa, &server, sizeof(irc::sockets::sockaddrs));
user->SetClientIP(client);
+ return !user->quitting;
}
void UserIOHandler::OnError(BufferedSocketError)
@@ -723,17 +720,17 @@ irc::sockets::cidr_mask User::GetCIDRMask()
return irc::sockets::cidr_mask(client_sa, range);
}
-bool User::SetClientIP(const std::string& address, bool recheck_eline)
+bool User::SetClientIP(const std::string& address)
{
irc::sockets::sockaddrs sa;
if (!irc::sockets::aptosa(address, client_sa.port(), sa))
return false;
- User::SetClientIP(sa, recheck_eline);
+ User::SetClientIP(sa);
return true;
}
-void User::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline)
+void User::SetClientIP(const irc::sockets::sockaddrs& sa)
{
const std::string oldip(GetIPString());
memcpy(&client_sa, &sa, sizeof(irc::sockets::sockaddrs));
@@ -746,26 +743,33 @@ void User::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline)
ChangeDisplayedHost(GetIPString());
}
-bool LocalUser::SetClientIP(const std::string& address, bool recheck_eline)
+bool LocalUser::SetClientIP(const std::string& address)
{
irc::sockets::sockaddrs sa;
if (!irc::sockets::aptosa(address, client_sa.port(), sa))
return false;
- LocalUser::SetClientIP(sa, recheck_eline);
+ LocalUser::SetClientIP(sa);
return true;
}
-void LocalUser::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline)
+void LocalUser::SetClientIP(const irc::sockets::sockaddrs& sa)
{
- if (sa != client_sa)
- {
- User::SetClientIP(sa);
- if (recheck_eline)
- this->exempt = (ServerInstance->XLines->MatchesLine("E", this) != NULL);
+ if (sa == client_sa)
+ return;
- FOREACH_MOD(OnSetUserIP, (this));
- }
+ ServerInstance->Users->RemoveCloneCounts(this);
+
+ User::SetClientIP(sa);
+
+ FOREACH_MOD(OnSetUserIP, (this));
+
+ ServerInstance->Users->AddClone(this);
+
+ // Recheck the connect class.
+ this->MyClass = NULL;
+ this->SetClass();
+ this->CheckClass();
}
void LocalUser::Write(const ClientProtocol::SerializedMessage& text)
@@ -796,7 +800,11 @@ void LocalUser::Write(const ClientProtocol::SerializedMessage& text)
void LocalUser::Send(ClientProtocol::Event& protoev)
{
if (!serializer)
+ {
+ ServerInstance->Logs->Log("USERS", LOG_DEBUG, "BUG: LocalUser::Send() called on %s who does not have a serializer!",
+ GetFullRealHost().c_str());
return;
+ }
// In the most common case a static LocalUser field, sendmsglist, is passed to the event to be
// populated. The list is cleared before returning.
diff --git a/src/xline.cpp b/src/xline.cpp
index 9c84101e1..55496b424 100644
--- a/src/xline.cpp
+++ b/src/xline.cpp
@@ -329,7 +329,7 @@ void ELine::Unset()
ServerInstance->XLines->CheckELines();
}
-// returns a pointer to the reason if a nickname matches a qline, NULL if it didnt match
+// returns a pointer to the reason if a nickname matches a Q-line, NULL if it didn't match
XLine* XLineManager::MatchesLine(const std::string &type, User* user)
{
@@ -523,13 +523,13 @@ bool XLine::IsBurstable()
void XLine::DefaultApply(User* u, const std::string &line, bool bancache)
{
- const std::string banReason = line + "-Lined: " + reason;
+ const std::string banReason = line + "-lined: " + reason;
if (!ServerInstance->Config->XLineMessage.empty())
u->WriteNumeric(ERR_YOUREBANNEDCREEP, ServerInstance->Config->XLineMessage);
if (ServerInstance->Config->HideBans)
- ServerInstance->Users->QuitUser(u, line + "-Lined", &banReason);
+ ServerInstance->Users->QuitUser(u, line + "-lined", &banReason);
else
ServerInstance->Users->QuitUser(u, banReason);
@@ -629,7 +629,7 @@ bool QLine::Matches(User *u)
void QLine::Apply(User* u)
{
- /* Force to uuid on apply of qline, no need to disconnect any more :) */
+ /* Force to uuid on apply of Q-line, no need to disconnect anymore :) */
u->ChangeNick(u->uuid);
}
@@ -667,7 +667,7 @@ bool GLine::Matches(const std::string &str)
void ELine::OnAdd()
{
- /* When adding one eline, only check the one eline */
+ /* When adding one E-line, only check the one E-line */
const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
for (UserManager::LocalList::const_iterator u2 = list.begin(); u2 != list.end(); u2++)
{
@@ -681,7 +681,7 @@ void XLine::DisplayExpiry()
{
bool onechar = (type.length() == 1);
ServerInstance->SNO->WriteToSnoMask('x', "Removing expired %s%s %s (set by %s %ld seconds ago): %s",
- type.c_str(), (onechar ? "-Line" : ""), Displayable().c_str(), source.c_str(), (long)(ServerInstance->Time() - set_time), reason.c_str());
+ type.c_str(), (onechar ? "-line" : ""), Displayable().c_str(), source.c_str(), (long)(ServerInstance->Time() - set_time), reason.c_str());
}
const std::string& ELine::Displayable()