summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlinuxdaemon <linuxdaemon@users.noreply.github.com>2018-12-18 19:06:56 -0600
committerPeter Powell <petpow@saberuk.com>2018-12-19 01:06:56 +0000
commit4fbd6681fedbff9b4cb04cc774f785cbe8b5c35b (patch)
tree9df58ec3e4cf2c191b4ae0051118606957d89db6 /src
parentbf0bf05ac07a4bd0afeba5a276ef86308f0f9e54 (diff)
Make more modules rehash atomically (#1535)
Have each module validate the values it loads before setting them, so any errors don't result in partial application of the configs
Diffstat (limited to 'src')
-rw-r--r--src/coremods/core_channel/core_channel.cpp39
-rw-r--r--src/coremods/core_info/core_info.cpp22
-rw-r--r--src/coremods/core_loadmodule.cpp14
-rw-r--r--src/coremods/core_oper/cmd_die.cpp7
-rw-r--r--src/coremods/core_oper/cmd_restart.cpp5
-rw-r--r--src/coremods/core_oper/core_oper.cpp31
-rw-r--r--src/coremods/core_oper/core_oper.h19
-rw-r--r--src/coremods/core_whois.cpp8
-rw-r--r--src/listmode.cpp18
-rw-r--r--src/modules/m_alias.cpp22
-rw-r--r--src/modules/m_censor.cpp7
-rw-r--r--src/modules/m_chanlog.cpp9
-rw-r--r--src/modules/m_customtitle.cpp89
-rw-r--r--src/modules/m_dccallow.cpp26
-rw-r--r--src/modules/m_dnsbl.cpp22
-rw-r--r--src/modules/m_flashpolicyd.cpp7
-rw-r--r--src/modules/m_hidelist.cpp15
-rw-r--r--src/modules/m_hidemode.cpp20
-rw-r--r--src/modules/m_httpd_acl.cpp5
-rw-r--r--src/modules/m_inviteexception.cpp2
-rw-r--r--src/modules/m_pbkdf2.cpp58
-rw-r--r--src/modules/m_restrictchans.cpp15
-rw-r--r--src/modules/m_securelist.cpp15
-rw-r--r--src/modules/m_vhost.cpp82
24 files changed, 371 insertions, 186 deletions
diff --git a/src/coremods/core_channel/core_channel.cpp b/src/coremods/core_channel/core_channel.cpp
index 05bf113ed..76e220765 100644
--- a/src/coremods/core_channel/core_channel.cpp
+++ b/src/coremods/core_channel/core_channel.cpp
@@ -148,16 +148,6 @@ class CoreModChannel : public Module, public CheckExemption::EventListener
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
ConfigTag* optionstag = ServerInstance->Config->ConfValue("options");
- Implementation events[] = { I_OnCheckKey, I_OnCheckLimit, I_OnCheckChannelBan };
- if (optionstag->getBool("invitebypassmodes", true))
- ServerInstance->Modules.Attach(events, this, sizeof(events)/sizeof(Implementation));
- else
- {
- for (unsigned int i = 0; i < sizeof(events)/sizeof(Implementation); i++)
- ServerInstance->Modules.Detach(events[i], this);
- }
-
- joinhook.modefromuser = optionstag->getBool("cyclehostsfromuser");
std::string current;
irc::spacesepstream defaultstream(optionstag->getString("exemptchanops"));
@@ -174,26 +164,41 @@ class CoreModChannel : public Module, public CheckExemption::EventListener
ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Exempting prefix %c from %s", prefix, restriction.c_str());
exempts[restriction] = prefix;
}
- exemptions.swap(exempts);
ConfigTag* securitytag = ServerInstance->Config->ConfValue("security");
const std::string announceinvites = securitytag->getString("announceinvites", "dynamic");
+ Invite::AnnounceState newannouncestate;
if (stdalgo::string::equalsci(announceinvites, "none"))
- cmdinvite.announceinvites = Invite::ANNOUNCE_NONE;
+ newannouncestate = Invite::ANNOUNCE_NONE;
else if (stdalgo::string::equalsci(announceinvites, "all"))
- cmdinvite.announceinvites = Invite::ANNOUNCE_ALL;
+ newannouncestate = Invite::ANNOUNCE_ALL;
else if (stdalgo::string::equalsci(announceinvites, "ops"))
- cmdinvite.announceinvites = Invite::ANNOUNCE_OPS;
+ newannouncestate = Invite::ANNOUNCE_OPS;
else if (stdalgo::string::equalsci(announceinvites, "dynamic"))
- cmdinvite.announceinvites = Invite::ANNOUNCE_DYNAMIC;
+ newannouncestate = Invite::ANNOUNCE_DYNAMIC;
else
throw ModuleException(announceinvites + " is an invalid <security:announceinvites> value, at " + securitytag->getTagLocation());
+ // Config is valid, apply it
+
+ // Validates and applies <banlist> tags, so do it first
+ banmode.DoRehash();
+
+ exemptions.swap(exempts);
// In 2.0 we allowed limits of 0 to be set. This is non-standard behaviour
// and will be removed in the next major release.
- limitmode.minlimit = optionstag->getBool("allowzerolimit", true) ? 0 : 1;
+ limitmode.minlimit = optionstag->getBool("allowzerolimit", true) ? 0 : 1;;
+ cmdinvite.announceinvites = newannouncestate;
+ joinhook.modefromuser = optionstag->getBool("cyclehostsfromuser");
- banmode.DoRehash();
+ Implementation events[] = { I_OnCheckKey, I_OnCheckLimit, I_OnCheckChannelBan };
+ if (optionstag->getBool("invitebypassmodes", true))
+ ServerInstance->Modules.Attach(events, this, sizeof(events)/sizeof(Implementation));
+ else
+ {
+ for (unsigned int i = 0; i < sizeof(events)/sizeof(Implementation); i++)
+ ServerInstance->Modules.Detach(events[i], this);
+ }
}
void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
diff --git a/src/coremods/core_info/core_info.cpp b/src/coremods/core_info/core_info.cpp
index 08e3df9bb..2b56e5e51 100644
--- a/src/coremods/core_info/core_info.cpp
+++ b/src/coremods/core_info/core_info.cpp
@@ -99,18 +99,14 @@ class CoreModInfo : public Module
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- ConfigTag* tag = ServerInstance->Config->ConfValue("admin");
- cmdadmin.AdminName = tag->getString("name");
- cmdadmin.AdminEmail = tag->getString("email", "null@example.com");
- cmdadmin.AdminNick = tag->getString("nick", "admin");
-
// Process the escape codes in the MOTDs.
- cmdmotd.motds.clear();
+ ConfigFileCache newmotds;
for (ServerConfig::ClassVector::const_iterator iter = ServerInstance->Config->Classes.begin(); iter != ServerInstance->Config->Classes.end(); ++iter)
{
+ ConfigTag* tag = (*iter)->config;
// Don't process the file if it has already been processed.
- const std::string motd = (*iter)->config->getString("motd", "motd");
- if (cmdmotd.motds.find(motd) != cmdmotd.motds.end())
+ const std::string motd = tag->getString("motd", "motd");
+ if (newmotds.find(motd) != newmotds.end())
continue;
// We can't process the file if it doesn't exist.
@@ -119,10 +115,16 @@ class CoreModInfo : public Module
continue;
// Process escape codes.
- cmdmotd.motds[file->first] = file->second;
- InspIRCd::ProcessColors(cmdmotd.motds[file->first]);
+ newmotds[file->first] = file->second;
+ InspIRCd::ProcessColors(newmotds[file->first]);
}
+ cmdmotd.motds.swap(newmotds);
+
+ ConfigTag* tag = ServerInstance->Config->ConfValue("admin");
+ cmdadmin.AdminName = tag->getString("name");
+ cmdadmin.AdminEmail = tag->getString("email", "null@example.com");
+ cmdadmin.AdminNick = tag->getString("nick", "admin");
}
void OnUserConnect(LocalUser* user) CXX11_OVERRIDE
diff --git a/src/coremods/core_loadmodule.cpp b/src/coremods/core_loadmodule.cpp
index 69c6bbcef..faecab213 100644
--- a/src/coremods/core_loadmodule.cpp
+++ b/src/coremods/core_loadmodule.cpp
@@ -58,10 +58,13 @@ CmdResult CommandLoadmodule::Handle(User* user, const Params& parameters)
class CommandUnloadmodule : public Command
{
public:
+ bool allowcoreunload;
+
/** Constructor for unloadmodule.
*/
CommandUnloadmodule(Module* parent)
- : Command(parent,"UNLOADMODULE", 1)
+ : Command(parent, "UNLOADMODULE", 1)
+ , allowcoreunload(false)
{
flags_needed = 'o';
syntax = "<modulename>";
@@ -77,8 +80,7 @@ class CommandUnloadmodule : public Command
CmdResult CommandUnloadmodule::Handle(User* user, const Params& parameters)
{
- if (!ServerInstance->Config->ConfValue("security")->getBool("allowcoreunload") &&
- InspIRCd::Match(parameters[0], "core_*.so", ascii_case_insensitive_map))
+ if (!allowcoreunload && InspIRCd::Match(parameters[0], "core_*.so", ascii_case_insensitive_map))
{
user->WriteNumeric(ERR_CANTUNLOADMODULE, parameters[0], "You cannot unload core commands!");
return CMD_FAILURE;
@@ -120,6 +122,12 @@ class CoreModLoadModule : public Module
{
return Version("Provides the LOADMODULE and UNLOADMODULE commands", VF_VENDOR|VF_CORE);
}
+
+ void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
+ {
+ ConfigTag* tag = ServerInstance->Config->ConfValue("security");
+ cmdunloadmod.allowcoreunload = tag->getBool("allowcoreunload");
+ }
};
MODULE_INIT(CoreModLoadModule)
diff --git a/src/coremods/core_oper/cmd_die.cpp b/src/coremods/core_oper/cmd_die.cpp
index b25fe2407..8b80dd115 100644
--- a/src/coremods/core_oper/cmd_die.cpp
+++ b/src/coremods/core_oper/cmd_die.cpp
@@ -22,8 +22,9 @@
#include "exitcodes.h"
#include "core_oper.h"
-CommandDie::CommandDie(Module* parent)
- : Command(parent, "DIE", 1)
+CommandDie::CommandDie(Module* parent, std::string& hashref)
+ : Command(parent, "DIE", 1, 1)
+ , hash(hashref)
{
flags_needed = 'o';
syntax = "<server>";
@@ -61,7 +62,7 @@ void DieRestart::SendError(const std::string& message)
*/
CmdResult CommandDie::Handle(User* user, const Params& parameters)
{
- if (DieRestart::CheckPass(user, parameters[0], "diepass"))
+ if (ServerInstance->PassCompare(user, password, parameters[0], hash))
{
{
std::string diebuf = "*** DIE command from " + user->GetFullHost() + ". Terminating.";
diff --git a/src/coremods/core_oper/cmd_restart.cpp b/src/coremods/core_oper/cmd_restart.cpp
index 936348f95..afadb911a 100644
--- a/src/coremods/core_oper/cmd_restart.cpp
+++ b/src/coremods/core_oper/cmd_restart.cpp
@@ -21,8 +21,9 @@
#include "inspircd.h"
#include "core_oper.h"
-CommandRestart::CommandRestart(Module* parent)
+CommandRestart::CommandRestart(Module* parent, std::string& hashref)
: Command(parent, "RESTART", 1, 1)
+ , hash(hashref)
{
flags_needed = 'o';
syntax = "<server>";
@@ -31,7 +32,7 @@ CommandRestart::CommandRestart(Module* parent)
CmdResult CommandRestart::Handle(User* user, const Params& parameters)
{
ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Restart: %s", user->nick.c_str());
- if (DieRestart::CheckPass(user, parameters[0], "restartpass"))
+ if (ServerInstance->PassCompare(user, password, parameters[0], hash))
{
ServerInstance->SNO->WriteGlobalSno('a', "RESTART command from %s, restarting server.", user->GetFullRealHost().c_str());
diff --git a/src/coremods/core_oper/core_oper.cpp b/src/coremods/core_oper/core_oper.cpp
index 54814b589..d4afab3b8 100644
--- a/src/coremods/core_oper/core_oper.cpp
+++ b/src/coremods/core_oper/core_oper.cpp
@@ -20,20 +20,10 @@
#include "inspircd.h"
#include "core_oper.h"
-namespace DieRestart
-{
- bool CheckPass(User* user, const std::string& inputpass, const char* confentry)
- {
- ConfigTag* tag = ServerInstance->Config->ConfValue("power");
- // The hash method for *BOTH* the die and restart passwords
- const std::string hash = tag->getString("hash");
- const std::string correctpass = tag->getString(confentry, ServerInstance->Config->ServerName);
- return ServerInstance->PassCompare(user, correctpass, inputpass, hash);
- }
-}
-
class CoreModOper : public Module
{
+ std::string powerhash;
+
CommandDie cmddie;
CommandKill cmdkill;
CommandOper cmdoper;
@@ -42,12 +32,25 @@ class CoreModOper : public Module
public:
CoreModOper()
- : cmddie(this), cmdkill(this), cmdoper(this), cmdrehash(this), cmdrestart(this)
+ : cmddie(this, powerhash)
+ , cmdkill(this)
+ , cmdoper(this)
+ , cmdrehash(this)
+ , cmdrestart(this, powerhash)
{
}
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
+
+ ConfigTag* tag = ServerInstance->Config->ConfValue("power");
+
+ // The hash method for *BOTH* the die and restart passwords
+ powerhash = tag->getString("hash");
+
+ cmddie.password = tag->getString("diepass", ServerInstance->Config->ServerName, 1);
+ cmdrestart.password = tag->getString("restartpass", ServerInstance->Config->ServerName, 1);
+
ConfigTag* security = ServerInstance->Config->ConfValue("security");
cmdkill.hidenick = security->getString("hidekills");
cmdkill.hideuline = security->getBool("hideulinekills");
@@ -55,7 +58,7 @@ class CoreModOper : public Module
Version GetVersion() CXX11_OVERRIDE
{
- return Version("Provides the DIE, KILL, OPER, REHASH, and RESTART commands", VF_VENDOR|VF_CORE);
+ return Version("Provides the DIE, KILL, OPER, REHASH, and RESTART commands", VF_VENDOR | VF_CORE);
}
};
diff --git a/src/coremods/core_oper/core_oper.h b/src/coremods/core_oper/core_oper.h
index bdb1ae9ee..7589b86d6 100644
--- a/src/coremods/core_oper/core_oper.h
+++ b/src/coremods/core_oper/core_oper.h
@@ -23,14 +23,6 @@
namespace DieRestart
{
- /** Checks a die or restart password
- * @param user The user executing /DIE or /RESTART
- * @param inputpass The password given by the user
- * @param confkey The name of the key in the power tag containing the correct password
- * @return True if the given password was correct, false if it was not
- */
- bool CheckPass(User* user, const std::string& inputpass, const char* confkey);
-
/** Send an ERROR to unregistered users and a NOTICE to all registered local users
* @param message Message to send
*/
@@ -42,9 +34,12 @@ namespace DieRestart
class CommandDie : public Command
{
public:
+ std::string& hash;
+ std::string password;
+
/** Constructor for die.
*/
- CommandDie(Module* parent);
+ CommandDie(Module* parent, std::string& hashref);
/** Handle command.
* @param parameters The parameters to the command
@@ -79,6 +74,7 @@ class CommandKill : public Command
* @return A value from CmdResult to indicate command success or failure.
*/
CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE;
+
RouteDescriptor GetRouting(User* user, const Params& parameters) CXX11_OVERRIDE;
void EncodeParameter(std::string& param, unsigned int index) CXX11_OVERRIDE;
@@ -123,9 +119,12 @@ class CommandRehash : public Command
class CommandRestart : public Command
{
public:
+ std::string& hash;
+ std::string password;
+
/** Constructor for restart.
*/
- CommandRestart(Module* parent);
+ CommandRestart(Module* parent, std::string& hashref);
/** Handle command.
* @param user User issuing the command
diff --git a/src/coremods/core_whois.cpp b/src/coremods/core_whois.cpp
index 455260051..0db634810 100644
--- a/src/coremods/core_whois.cpp
+++ b/src/coremods/core_whois.cpp
@@ -357,17 +357,19 @@ class CoreModWhois : public Module
{
ConfigTag* tag = ServerInstance->Config->ConfValue("options");
const std::string splitwhois = tag->getString("splitwhois", "no");
+ SplitWhoisState newsplitstate;
if (stdalgo::string::equalsci(splitwhois, "no"))
- cmd.splitwhois = SPLITWHOIS_NONE;
+ newsplitstate = SPLITWHOIS_NONE;
else if (stdalgo::string::equalsci(splitwhois, "split"))
- cmd.splitwhois = SPLITWHOIS_SPLIT;
+ newsplitstate = SPLITWHOIS_SPLIT;
else if (stdalgo::string::equalsci(splitwhois, "splitmsg"))
- cmd.splitwhois = SPLITWHOIS_SPLITMSG;
+ newsplitstate = SPLITWHOIS_SPLITMSG;
else
throw ModuleException(splitwhois + " is an invalid <security:splitwhois> value, at " + tag->getTagLocation());
ConfigTag* security = ServerInstance->Config->ConfValue("security");
cmd.genericoper = security->getBool("genericoper");
+ cmd.splitwhois = newsplitstate;
}
Version GetVersion() CXX11_OVERRIDE
diff --git a/src/listmode.cpp b/src/listmode.cpp
index 61fadcade..6b5fb13c5 100644
--- a/src/listmode.cpp
+++ b/src/listmode.cpp
@@ -62,8 +62,7 @@ void ListModeBase::DoRehash()
{
ConfigTagList tags = ServerInstance->Config->ConfTags(configtag);
- limitlist oldlimits = chanlimits;
- chanlimits.clear();
+ limitlist newlimits;
for (ConfigIter i = tags.first; i != tags.second; i++)
{
@@ -71,18 +70,25 @@ void ListModeBase::DoRehash()
ConfigTag* c = i->second;
ListLimit limit(c->getString("chan"), c->getUInt("limit", 0));
- if (limit.mask.size() && limit.limit > 0)
- chanlimits.push_back(limit);
+ if (limit.mask.empty())
+ throw ModuleException(InspIRCd::Format("<%s:chan> is empty at %s", configtag.c_str(), c->getTagLocation().c_str()));
+
+ if (limit.limit <= 0)
+ throw ModuleException(InspIRCd::Format("<%s:limit> must be greater than 0, at %s", configtag.c_str(), c->getTagLocation().c_str()));
+
+ newlimits.push_back(limit);
}
// Add the default entry. This is inserted last so if the user specifies a
// wildcard record in the config it will take precedence over this entry.
- chanlimits.push_back(ListLimit("*", DEFAULT_LIST_SIZE));
+ newlimits.push_back(ListLimit("*", DEFAULT_LIST_SIZE));
// Most of the time our settings are unchanged, so we can avoid iterating the chanlist
- if (oldlimits == chanlimits)
+ if (chanlimits == newlimits)
return;
+ chanlimits.swap(newlimits);
+
const chan_hash& chans = ServerInstance->GetChans();
for (chan_hash::const_iterator i = chans.begin(); i != chans.end(); ++i)
{
diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp
index 6f27ecc09..4d1dd65c9 100644
--- a/src/modules/m_alias.cpp
+++ b/src/modules/m_alias.cpp
@@ -74,27 +74,35 @@ class ModuleAlias : public Module
public:
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- ConfigTag* fantasy = ServerInstance->Config->ConfValue("fantasy");
- AllowBots = fantasy->getBool("allowbots", false);
- fprefix = fantasy->getString("prefix", "!", 1, ServerInstance->Config->Limits.MaxLine);
-
- Aliases.clear();
+ AliasMap newAliases;
ConfigTagList tags = ServerInstance->Config->ConfTags("alias");
for(ConfigIter i = tags.first; i != tags.second; ++i)
{
ConfigTag* tag = i->second;
Alias a;
a.AliasedCommand = tag->getString("text");
- std::transform(a.AliasedCommand.begin(), a.AliasedCommand.end(), a.AliasedCommand.begin(), ::toupper);
+ if (a.AliasedCommand.empty())
+ throw ModuleException("<alias:text> is empty! at " + tag->getTagLocation());
+
tag->readString("replace", a.ReplaceFormat, true);
+ if (a.ReplaceFormat.empty())
+ throw ModuleException("<alias:replace> is empty! at " + tag->getTagLocation());
+
a.RequiredNick = tag->getString("requires");
a.ULineOnly = tag->getBool("uline");
a.ChannelCommand = tag->getBool("channelcommand", false);
a.UserCommand = tag->getBool("usercommand", true);
a.OperOnly = tag->getBool("operonly");
a.format = tag->getString("format");
- Aliases.insert(std::make_pair(a.AliasedCommand, a));
+
+ std::transform(a.AliasedCommand.begin(), a.AliasedCommand.end(), a.AliasedCommand.begin(), ::toupper);
+ newAliases.insert(std::make_pair(a.AliasedCommand, a));
}
+
+ ConfigTag* fantasy = ServerInstance->Config->ConfValue("fantasy");
+ AllowBots = fantasy->getBool("allowbots", false);
+ fprefix = fantasy->getString("prefix", "!", 1, ServerInstance->Config->Limits.MaxLine);
+ Aliases.swap(newAliases);
}
ModuleAlias()
diff --git a/src/modules/m_censor.cpp b/src/modules/m_censor.cpp
index a9c55386c..31309ed2f 100644
--- a/src/modules/m_censor.cpp
+++ b/src/modules/m_censor.cpp
@@ -104,7 +104,7 @@ class ModuleCensor : public Module
* reload our config file on rehash - we must destroy and re-allocate the classes
* to call the constructor again and re-read our data.
*/
- censors.clear();
+ censor_t newcensors;
ConfigTagList badwords = ServerInstance->Config->ConfTags("badword");
for (ConfigIter i = badwords.first; i != badwords.second; ++i)
@@ -112,11 +112,12 @@ class ModuleCensor : public Module
ConfigTag* tag = i->second;
const std::string text = tag->getString("text");
if (text.empty())
- continue;
+ throw ModuleException("<badword:text> is empty! at " + tag->getTagLocation());
const std::string replace = tag->getString("replace");
- censors[text] = replace;
+ newcensors[text] = replace;
}
+ censors.swap(newcensors);
}
Version GetVersion() CXX11_OVERRIDE
diff --git a/src/modules/m_chanlog.cpp b/src/modules/m_chanlog.cpp
index 85e7ca2eb..afe213f61 100644
--- a/src/modules/m_chanlog.cpp
+++ b/src/modules/m_chanlog.cpp
@@ -33,8 +33,7 @@ class ModuleChanLog : public Module
{
std::string snomasks;
std::string channel;
-
- logstreams.clear();
+ ChanLogTargets newlogs;
ConfigTagList tags = ServerInstance->Config->ConfTags("chanlog");
for (ConfigIter i = tags.first; i != tags.second; ++i)
@@ -44,16 +43,16 @@ class ModuleChanLog : public Module
if (channel.empty() || snomasks.empty())
{
- ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Malformed chanlog tag, ignoring");
- continue;
+ throw ModuleException("Malformed chanlog tag at " + i->second->getTagLocation());
}
for (std::string::const_iterator it = snomasks.begin(); it != snomasks.end(); it++)
{
- logstreams.insert(std::make_pair(*it, channel));
+ newlogs.insert(std::make_pair(*it, channel));
ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Logging %c to %s", *it, channel.c_str());
}
}
+ logstreams.swap(newlogs);
}
diff --git a/src/modules/m_customtitle.cpp b/src/modules/m_customtitle.cpp
index c16b1eda2..2dd378062 100644
--- a/src/modules/m_customtitle.cpp
+++ b/src/modules/m_customtitle.cpp
@@ -28,12 +28,49 @@ enum
RPL_WHOISSPECIAL = 320
};
+struct CustomTitle
+{
+ const std::string name;
+ const std::string password;
+ const std::string hash;
+ const std::string host;
+ const std::string title;
+ const std::string vhost;
+
+ CustomTitle(const std::string& n, const std::string& p, const std::string& h, const std::string& hst, const std::string& t, const std::string& v)
+ : name(n)
+ , password(p)
+ , hash(h)
+ , host(hst)
+ , title(t)
+ , vhost(v)
+ {
+ }
+
+ bool MatchUser(User* user) const
+ {
+ const std::string userHost = user->ident + "@" + user->GetRealHost();
+ const std::string userIP = user->ident + "@" + user->GetIPString();
+ return InspIRCd::MatchMask(host, userHost, userIP);
+ }
+
+ bool CheckPass(User* user, const std::string& pass) const
+ {
+ return ServerInstance->PassCompare(user, password, pass, hash);
+ }
+};
+
+typedef std::multimap<std::string, CustomTitle> CustomVhostMap;
+typedef std::pair<CustomVhostMap::iterator, CustomVhostMap::iterator> MatchingConfigs;
+
/** Handle /TITLE
*/
class CommandTitle : public Command
{
public:
StringExtItem ctitle;
+ CustomVhostMap configs;
+
CommandTitle(Module* Creator) : Command(Creator,"TITLE", 2),
ctitle("ctitle", ExtensionItem::EXT_USER, Creator)
{
@@ -42,30 +79,21 @@ class CommandTitle : public Command
CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE
{
- const std::string userHost = user->ident + "@" + user->GetRealHost();
- const std::string userIP = user->ident + "@" + user->GetIPString();
+ MatchingConfigs matching = configs.equal_range(parameters[0]);
- ConfigTagList tags = ServerInstance->Config->ConfTags("title");
- for (ConfigIter i = tags.first; i != tags.second; ++i)
+ for (MatchingConfigs::first_type i = matching.first; i != matching.second; ++i)
{
- std::string Name = i->second->getString("name");
- std::string pass = i->second->getString("password");
- std::string hash = i->second->getString("hash");
- std::string host = i->second->getString("host", "*@*");
- std::string title = i->second->getString("title");
- std::string vhost = i->second->getString("vhost");
-
- if (Name == parameters[0] && ServerInstance->PassCompare(user, pass, parameters[1], hash) &&
- InspIRCd::MatchMask(host, userHost, userIP) && !title.empty())
+ CustomTitle config = i->second;
+ if (config.MatchUser(user) && config.CheckPass(user, parameters[1]))
{
- ctitle.set(user, title);
+ ctitle.set(user, config.title);
- ServerInstance->PI->SendMetaData(user, "ctitle", title);
+ ServerInstance->PI->SendMetaData(user, "ctitle", config.title);
- if (!vhost.empty())
- user->ChangeDisplayedHost(vhost);
+ if (!config.vhost.empty())
+ user->ChangeDisplayedHost(config.vhost);
- user->WriteNotice("Custom title set to '" + title + "'");
+ user->WriteNotice("Custom title set to '" + config.title + "'");
return CMD_SUCCESS;
}
@@ -88,6 +116,31 @@ class ModuleCustomTitle : public Module, public Whois::LineEventListener
{
}
+ void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
+ {
+ ConfigTagList tags = ServerInstance->Config->ConfTags("title");
+ CustomVhostMap newtitles;
+ for (ConfigIter i = tags.first; i != tags.second; ++i)
+ {
+ reference<ConfigTag> tag = i->second;
+ std::string name = tag->getString("name", "", 1);
+ if (name.empty())
+ throw ModuleException("<title:name> is empty at " + tag->getTagLocation());
+
+ std::string pass = tag->getString("password");
+ if (pass.empty())
+ throw ModuleException("<title:password> is empty at " + tag->getTagLocation());
+
+ std::string hash = tag->getString("hash");
+ std::string host = tag->getString("host", "*@*");
+ std::string title = tag->getString("title");
+ std::string vhost = tag->getString("vhost");
+ CustomTitle config(name, pass, hash, host, title, vhost);
+ newtitles.insert(std::make_pair(name, config));
+ }
+ cmd.configs.swap(newtitles);
+ }
+
// :kenny.chatspike.net 320 Brain Azhrarn :is getting paid to play games.
ModResult OnWhoisLine(Whois::Context& whois, Numeric::Numeric& numeric) CXX11_OVERRIDE
{
diff --git a/src/modules/m_dccallow.cpp b/src/modules/m_dccallow.cpp
index eb364089a..85f9d20d0 100644
--- a/src/modules/m_dccallow.cpp
+++ b/src/modules/m_dccallow.cpp
@@ -106,6 +106,7 @@ class CommandDccallow : public Command
public:
unsigned int maxentries;
+ unsigned long defaultlength;
CommandDccallow(Module* parent, DCCAllowExt& Ext)
: Command(parent, "DCCALLOW", 0)
, ext(Ext)
@@ -206,12 +207,10 @@ class CommandDccallow : public Command
}
std::string mask = target->nick+"!"+target->ident+"@"+target->GetDisplayedHost();
- std::string default_length = ServerInstance->Config->ConfValue("dccallow")->getString("length");
-
unsigned long length;
if (parameters.size() < 2)
{
- length = InspIRCd::Duration(default_length);
+ length = defaultlength;
}
else if (!InspIRCd::IsValidDuration(parameters[1]))
{
@@ -293,11 +292,14 @@ class ModuleDCCAllow : public Module
{
DCCAllowExt ext;
CommandDccallow cmd;
+ bool blockchat;
+ std::string defaultaction;
public:
ModuleDCCAllow()
: ext("dccallow", ExtensionItem::EXT_USER, this)
, cmd(this, ext)
+ , blockchat(false)
{
}
@@ -356,9 +358,6 @@ class ModuleDCCAllow : public Module
const std::string type = buf.substr(0, s);
- ConfigTag* conftag = ServerInstance->Config->ConfValue("dccallow");
- bool blockchat = conftag->getBool("blockchat");
-
if (stdalgo::string::equalsci(type, "SEND"))
{
size_t first;
@@ -384,7 +383,6 @@ class ModuleDCCAllow : public Module
if (s == std::string::npos)
return MOD_RES_PASSTHRU;
- std::string defaultaction = conftag->getString("action");
std::string filename = buf.substr(first, s);
bool found = false;
@@ -507,18 +505,22 @@ class ModuleDCCAllow : public Module
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- ConfigTag* tag = ServerInstance->Config->ConfValue("dccallow");
- cmd.maxentries = tag->getUInt("maxentries", 20);
-
- bfl.clear();
+ bannedfilelist newbfl;
ConfigTagList tags = ServerInstance->Config->ConfTags("banfile");
for (ConfigIter i = tags.first; i != tags.second; ++i)
{
BannedFileList bf;
bf.filemask = i->second->getString("pattern");
bf.action = i->second->getString("action");
- bfl.push_back(bf);
+ newbfl.push_back(bf);
}
+ bfl.swap(newbfl);
+
+ ConfigTag* tag = ServerInstance->Config->ConfValue("dccallow");
+ cmd.maxentries = tag->getUInt("maxentries", 20);
+ cmd.defaultlength = tag->getDuration("length", 0);
+ blockchat = tag->getBool("blockchat");
+ defaultaction = tag->getString("action");
}
Version GetVersion() CXX11_OVERRIDE
diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp
index 7b88bc961..d1ca800b3 100644
--- a/src/modules/m_dnsbl.cpp
+++ b/src/modules/m_dnsbl.cpp
@@ -228,9 +228,11 @@ class DNSBLResolver : public DNS::Request
}
};
+typedef std::vector<reference<DNSBLConfEntry> > DNSBLConfList;
+
class ModuleDNSBL : public Module, public Stats::EventListener
{
- std::vector<reference<DNSBLConfEntry> > DNSBLConfEntries;
+ DNSBLConfList DNSBLConfEntries;
dynamic_reference<DNS::Manager> DNS;
LocalStringExt nameExt;
LocalIntExt countExt;
@@ -276,7 +278,7 @@ class ModuleDNSBL : public Module, public Stats::EventListener
*/
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- DNSBLConfEntries.clear();
+ DNSBLConfList newentries;
ConfigTagList dnsbls = ServerInstance->Config->ConfTags("dnsbl");
for(ConfigIter i = dnsbls.first; i != dnsbls.second; ++i)
@@ -313,23 +315,19 @@ class ModuleDNSBL : public Module, public Stats::EventListener
/* yeah, logic here is a little messy */
if ((e->bitmask <= 0) && (DNSBLConfEntry::A_BITMASK == e->type))
{
- std::string location = tag->getTagLocation();
- ServerInstance->SNO->WriteGlobalSno('d', "DNSBL(%s): invalid bitmask", location.c_str());
+ throw ModuleException("Invalid <dnsbl:bitmask> at " + tag->getTagLocation());
}
else if (e->name.empty())
{
- std::string location = tag->getTagLocation();
- ServerInstance->SNO->WriteGlobalSno('d', "DNSBL(%s): Invalid name", location.c_str());
+ throw ModuleException("Empty <dnsbl:name> at " + tag->getTagLocation());
}
else if (e->domain.empty())
{
- std::string location = tag->getTagLocation();
- ServerInstance->SNO->WriteGlobalSno('d', "DNSBL(%s): Invalid domain", location.c_str());
+ throw ModuleException("Empty <dnsbl:domain> at " + tag->getTagLocation());
}
else if (e->banaction == DNSBLConfEntry::I_UNKNOWN)
{
- std::string location = tag->getTagLocation();
- ServerInstance->SNO->WriteGlobalSno('d', "DNSBL(%s): Invalid banaction", location.c_str());
+ throw ModuleException("Unknown <dnsbl:action> at " + tag->getTagLocation());
}
else
{
@@ -341,9 +339,11 @@ class ModuleDNSBL : public Module, public Stats::EventListener
}
/* add it, all is ok */
- DNSBLConfEntries.push_back(e);
+ newentries.push_back(e);
}
}
+
+ DNSBLConfEntries.swap(newentries);
}
void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE
diff --git a/src/modules/m_flashpolicyd.cpp b/src/modules/m_flashpolicyd.cpp
index d7f9a793b..db0eeb1f1 100644
--- a/src/modules/m_flashpolicyd.cpp
+++ b/src/modules/m_flashpolicyd.cpp
@@ -97,7 +97,6 @@ class ModuleFlashPD : public Module
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("flashpolicyd");
- timeout = tag->getDuration("timeout", 5, 1);
std::string file = tag->getString("file");
if (!file.empty())
@@ -109,10 +108,7 @@ class ModuleFlashPD : public Module
}
catch (CoreException&)
{
- const std::string error_message = "A file was specified for FlashPD, but it could not be loaded.";
- ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, error_message);
- ServerInstance->SNO->WriteGlobalSno('a', error_message);
- policy_reply.clear();
+ throw ModuleException("A file was specified for FlashPD, but it could not be loaded at " + tag->getTagLocation());
}
return;
}
@@ -144,6 +140,7 @@ class ModuleFlashPD : public Module
<site-control permitted-cross-domain-policies=\"master-only\"/>\
<allow-access-from domain=\"*\" to-ports=\"" + to_ports + "\" />\
</cross-domain-policy>";
+ timeout = tag->getDuration("timeout", 5, 1);
}
CullResult cull() CXX11_OVERRIDE
diff --git a/src/modules/m_hidelist.cpp b/src/modules/m_hidelist.cpp
index 2d3f0be7c..9c8811fb8 100644
--- a/src/modules/m_hidelist.cpp
+++ b/src/modules/m_hidelist.cpp
@@ -58,19 +58,26 @@ class ModuleHideList : public Module
public:
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- stdalgo::delete_all(watchers);
- watchers.clear();
-
ConfigTagList tags = ServerInstance->Config->ConfTags("hidelist");
+ typedef std::vector<std::pair<std::string, unsigned int> > NewConfigs;
+ NewConfigs newconfigs;
for (ConfigIter i = tags.first; i != tags.second; ++i)
{
ConfigTag* tag = i->second;
std::string modename = tag->getString("mode");
+ if (modename.empty())
+ throw ModuleException("Empty <hidelist:mode> at " + tag->getTagLocation());
// If rank is set to 0 everyone inside the channel can view the list,
// but non-members may not
unsigned int rank = tag->getUInt("rank", HALFOP_VALUE);
- watchers.push_back(new ListWatcher(this, modename, rank));
+ newconfigs.push_back(std::make_pair(modename, rank));
}
+
+ stdalgo::delete_all(watchers);
+ watchers.clear();
+
+ for (NewConfigs::const_iterator i = newconfigs.begin(); i != newconfigs.end(); ++i)
+ watchers.push_back(new ListWatcher(this, i->first, i->second));
}
~ModuleHideList()
diff --git a/src/modules/m_hidemode.cpp b/src/modules/m_hidemode.cpp
index d6ae05801..d5ac57115 100644
--- a/src/modules/m_hidemode.cpp
+++ b/src/modules/m_hidemode.cpp
@@ -37,20 +37,24 @@ class Settings
void Load()
{
- rankstosee.clear();
+ RanksToSeeMap newranks;
ConfigTagList tags = ServerInstance->Config->ConfTags("hidemode");
for (ConfigIter i = tags.first; i != tags.second; ++i)
{
ConfigTag* tag = i->second;
- std::string modename = tag->getString("mode");
- unsigned int rank = tag->getInt("rank", 0, 0);
- if (!modename.empty() && rank)
- {
- ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Hiding the %s mode from users below rank %u", modename.c_str(), rank);
- rankstosee.insert(std::make_pair(modename, rank));
- }
+ const std::string modename = tag->getString("mode");
+ if (modename.empty())
+ throw ModuleException("<hidemode:mode> is empty at " + tag->getTagLocation());
+
+ unsigned int rank = tag->getUInt("rank", 0);
+ if (!rank)
+ throw ModuleException("<hidemode:rank> must be greater than 0 at " + tag->getTagLocation());
+
+ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Hiding the %s mode from users below rank %u", modename.c_str(), rank);
+ newranks.insert(std::make_pair(modename, rank));
}
+ rankstosee.swap(newranks);
}
};
diff --git a/src/modules/m_httpd_acl.cpp b/src/modules/m_httpd_acl.cpp
index 2dbc1be69..49710c219 100644
--- a/src/modules/m_httpd_acl.cpp
+++ b/src/modules/m_httpd_acl.cpp
@@ -51,7 +51,7 @@ class ModuleHTTPAccessList : public Module, public HTTPACLEventListener
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- acl_list.clear();
+ std::vector<HTTPACL> new_acls;
ConfigTagList acls = ServerInstance->Config->ConfTags("httpdacl");
for (ConfigIter i = acls.first; i != acls.second; i++)
{
@@ -89,8 +89,9 @@ class ModuleHTTPAccessList : public Module, public HTTPACLEventListener
ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Read ACL: path=%s pass=%s whitelist=%s blacklist=%s", path.c_str(),
password.c_str(), whitelist.c_str(), blacklist.c_str());
- acl_list.push_back(HTTPACL(path, username, password, whitelist, blacklist));
+ new_acls.push_back(HTTPACL(path, username, password, whitelist, blacklist));
}
+ acl_list.swap(new_acls);
}
void BlockAccess(HTTPRequest* http, unsigned int returnval, const std::string &extraheaderkey = "", const std::string &extraheaderval="")
diff --git a/src/modules/m_inviteexception.cpp b/src/modules/m_inviteexception.cpp
index 1317e6e57..bae8f7184 100644
--- a/src/modules/m_inviteexception.cpp
+++ b/src/modules/m_inviteexception.cpp
@@ -82,8 +82,8 @@ public:
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- invite_bypass_key = ServerInstance->Config->ConfValue("inviteexception")->getBool("bypasskey", true);
ie.DoRehash();
+ invite_bypass_key = ServerInstance->Config->ConfValue("inviteexception")->getBool("bypasskey", true);
}
Version GetVersion() CXX11_OVERRIDE
diff --git a/src/modules/m_pbkdf2.cpp b/src/modules/m_pbkdf2.cpp
index 86530c5dd..036538a39 100644
--- a/src/modules/m_pbkdf2.cpp
+++ b/src/modules/m_pbkdf2.cpp
@@ -139,39 +139,65 @@ class PBKDF2Provider : public HashProvider
}
};
+struct ProviderConfig
+{
+ unsigned long dkey_length;
+ unsigned long iterations;
+};
+
+typedef std::map<std::string, ProviderConfig> ProviderConfigMap;
+
class ModulePBKDF2 : public Module
{
std::vector<PBKDF2Provider*> providers;
+ ProviderConfig globalconfig;
+ ProviderConfigMap providerconfigs;
- void GetConfig()
+ ProviderConfig GetConfigForProvider(const std::string& name) const
+ {
+ ProviderConfigMap::const_iterator it = providerconfigs.find(name);
+ if (it == providerconfigs.end())
+ return globalconfig;
+
+ return it->second;
+ }
+
+ void ConfigureProviders()
{
- // First set the common values
- ConfigTag* tag = ServerInstance->Config->ConfValue("pbkdf2");
- unsigned int global_iterations = tag->getUInt("iterations", 12288, 1);
- unsigned int global_dkey_length = tag->getUInt("length", 32, 1, 1024);
for (std::vector<PBKDF2Provider*>::iterator i = providers.begin(); i != providers.end(); ++i)
{
PBKDF2Provider* pi = *i;
- pi->iterations = global_iterations;
- pi->dkey_length = global_dkey_length;
+ ProviderConfig config = GetConfigForProvider(pi->name);
+ pi->iterations = config.iterations;
+ pi->dkey_length = config.dkey_length;
}
+ }
+
+ void GetConfig()
+ {
+ // First set the common values
+ ConfigTag* tag = ServerInstance->Config->ConfValue("pbkdf2");
+ ProviderConfig newglobal;
+ newglobal.iterations = tag->getUInt("iterations", 12288, 1);
+ newglobal.dkey_length = tag->getUInt("length", 32, 1, 1024);
// Then the specific values
+ ProviderConfigMap newconfigs;
ConfigTagList tags = ServerInstance->Config->ConfTags("pbkdf2prov");
for (ConfigIter i = tags.first; i != tags.second; ++i)
{
tag = i->second;
std::string hash_name = "hash/" + tag->getString("hash");
- for (std::vector<PBKDF2Provider*>::iterator j = providers.begin(); j != providers.end(); ++j)
- {
- PBKDF2Provider* pi = *j;
- if (pi->provider->name != hash_name)
- continue;
+ ProviderConfig& config = newconfigs[hash_name];
- pi->iterations = tag->getUInt("iterations", global_iterations, 1);
- pi->dkey_length = tag->getUInt("length", global_dkey_length, 1, 1024);
- }
+ config.iterations = tag->getUInt("iterations", newglobal.iterations, 1);
+ config.dkey_length = tag->getUInt("length", newglobal.dkey_length, 1, 1024);
}
+
+ // Config is valid, apply it
+ providerconfigs.swap(newconfigs);
+ std::swap(globalconfig, newglobal);
+ ConfigureProviders();
}
public:
@@ -194,7 +220,7 @@ class ModulePBKDF2 : public Module
providers.push_back(prov);
ServerInstance->Modules.AddService(*prov);
- GetConfig();
+ ConfigureProviders();
}
void OnServiceDel(ServiceProvider& prov) CXX11_OVERRIDE
diff --git a/src/modules/m_restrictchans.cpp b/src/modules/m_restrictchans.cpp
index 9c7ed1213..348beed2c 100644
--- a/src/modules/m_restrictchans.cpp
+++ b/src/modules/m_restrictchans.cpp
@@ -22,21 +22,26 @@
#include "inspircd.h"
+typedef insp::flat_set<std::string, irc::insensitive_swo> AllowChans;
+
class ModuleRestrictChans : public Module
{
- insp::flat_set<std::string, irc::insensitive_swo> allowchans;
+ AllowChans allowchans;
public:
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- allowchans.clear();
+ AllowChans newallows;
ConfigTagList tags = ServerInstance->Config->ConfTags("allowchannel");
for(ConfigIter i = tags.first; i != tags.second; ++i)
{
- ConfigTag* tag = i->second;
- std::string txt = tag->getString("name");
- allowchans.insert(txt);
+ const std::string name = i->second->getString("name");
+ if (name.empty())
+ throw ModuleException("Empty <allowchannel:name> at " + i->second->getTagLocation());
+
+ newallows.insert(name);
}
+ allowchans.swap(newallows);
}
ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
diff --git a/src/modules/m_securelist.cpp b/src/modules/m_securelist.cpp
index aa14707b1..6d9b64df2 100644
--- a/src/modules/m_securelist.cpp
+++ b/src/modules/m_securelist.cpp
@@ -22,9 +22,11 @@
#include "inspircd.h"
#include "modules/account.h"
+typedef std::vector<std::string> AllowList;
+
class ModuleSecureList : public Module
{
- std::vector<std::string> allowlist;
+ AllowList allowlist;
bool exemptregistered;
unsigned int WaitTime;
@@ -36,15 +38,22 @@ class ModuleSecureList : public Module
void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- allowlist.clear();
+ AllowList newallows;
ConfigTagList tags = ServerInstance->Config->ConfTags("securehost");
for (ConfigIter i = tags.first; i != tags.second; ++i)
- allowlist.push_back(i->second->getString("exception"));
+ {
+ std::string host = i->second->getString("exception");
+ if (host.empty())
+ throw ModuleException("<securehost:exception> is a required field at " + i->second->getTagLocation());
+ newallows.push_back(host);
+ }
ConfigTag* tag = ServerInstance->Config->ConfValue("securelist");
+
exemptregistered = tag->getBool("exemptregistered");
WaitTime = tag->getDuration("waittime", 60, 1);
+ allowlist.swap(newallows);
}
diff --git a/src/modules/m_vhost.cpp b/src/modules/m_vhost.cpp
index 01df33cae..478a5100a 100644
--- a/src/modules/m_vhost.cpp
+++ b/src/modules/m_vhost.cpp
@@ -22,35 +22,55 @@
#include "inspircd.h"
+struct CustomVhost
+{
+ const std::string name;
+ const std::string password;
+ const std::string hash;
+ const std::string vhost;
+
+ CustomVhost(const std::string& n, const std::string& p, const std::string& h, const std::string& v)
+ : name(n)
+ , password(p)
+ , hash(h)
+ , vhost(v)
+ {
+ }
+
+ bool CheckPass(User* user, const std::string& pass) const
+ {
+ return ServerInstance->PassCompare(user, password, pass, hash);
+ }
+};
+
+typedef std::multimap<std::string, CustomVhost> CustomVhostMap;
+typedef std::pair<CustomVhostMap::iterator, CustomVhostMap::iterator> MatchingConfigs;
+
/** Handle /VHOST
*/
class CommandVhost : public Command
{
public:
- CommandVhost(Module* Creator) : Command(Creator,"VHOST", 2)
+ CustomVhostMap vhosts;
+
+ CommandVhost(Module* Creator)
+ : Command(Creator, "VHOST", 2)
{
syntax = "<username> <password>";
}
CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE
{
- ConfigTagList tags = ServerInstance->Config->ConfTags("vhost");
- for(ConfigIter i = tags.first; i != tags.second; ++i)
- {
- ConfigTag* tag = i->second;
- std::string mask = tag->getString("host");
- std::string username = tag->getString("user");
- std::string pass = tag->getString("pass");
- std::string hash = tag->getString("hash");
+ MatchingConfigs matching = vhosts.equal_range(parameters[0]);
- if (parameters[0] == username && ServerInstance->PassCompare(user, pass, parameters[1], hash))
+ for (MatchingConfigs::first_type i = matching.first; i != matching.second; ++i)
+ {
+ CustomVhost config = i->second;
+ if (config.CheckPass(user, parameters[1]))
{
- if (!mask.empty())
- {
- user->WriteNotice("Setting your VHost: " + mask);
- user->ChangeDisplayedHost(mask);
- return CMD_SUCCESS;
- }
+ user->WriteNotice("Setting your VHost: " + config.vhost);
+ user->ChangeDisplayedHost(config.vhost);
+ return CMD_SUCCESS;
}
}
@@ -64,13 +84,39 @@ class ModuleVHost : public Module
CommandVhost cmd;
public:
- ModuleVHost() : cmd(this)
+ ModuleVHost()
+ : cmd(this)
+ {
+ }
+
+ void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
+ CustomVhostMap newhosts;
+ ConfigTagList tags = ServerInstance->Config->ConfTags("vhost");
+ for (ConfigIter i = tags.first; i != tags.second; ++i)
+ {
+ ConfigTag* tag = i->second;
+ std::string mask = tag->getString("host");
+ if (mask.empty())
+ throw ModuleException("<vhost:host> is empty! at " + tag->getTagLocation());
+ std::string username = tag->getString("user");
+ if (username.empty())
+ throw ModuleException("<vhost:user> is empty! at " + tag->getTagLocation());
+ std::string pass = tag->getString("pass");
+ if (pass.empty())
+ throw ModuleException("<vhost:pass> is empty! at " + tag->getTagLocation());
+ std::string hash = tag->getString("hash");
+
+ CustomVhost vhost(username, pass, hash, mask);
+ newhosts.insert(std::make_pair(username, vhost));
+ }
+
+ cmd.vhosts.swap(newhosts);
}
Version GetVersion() CXX11_OVERRIDE
{
- return Version("Provides masking of user hostnames via traditional /VHOST command",VF_VENDOR);
+ return Version("Provides masking of user hostnames via traditional /VHOST command", VF_VENDOR);
}
};