summaryrefslogtreecommitdiff
path: root/src/config.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2013-05-05 01:55:04 -0400
committerAdam <Adam@anope.org>2013-05-05 01:55:04 -0400
commit1d0bb9b26b7ad58ab0bf979ac046f4511b3bf12b (patch)
tree4486f0784bdf050fd7eb225c0cb9df352ce1f45a /src/config.cpp
parent781defb7076ddfddf723ca08cd0a518b6657b64f (diff)
Rework the config file reader to be much more flexible and move many configuration directives to the actual modules they are used in.
Diffstat (limited to 'src/config.cpp')
-rw-r--r--src/config.cpp2119
1 files changed, 509 insertions, 1610 deletions
diff --git a/src/config.cpp b/src/config.cpp
index bc01a1589..38e072de8 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -25,1020 +25,588 @@
#include <grp.h>
#endif
-/*************************************************************************/
+using namespace Configuration;
-ConfigurationFile ServicesConf("services.conf", false); // Services configuration file name
-ServerConfig *Config = NULL;
+File ServicesConf("services.conf", false); // Services configuration file name
+Conf *Config = NULL;
-static Anope::string UlineServers;
-static Anope::string BSDefaults;
-static Anope::string CSDefaults;
-static Anope::string NSDefaults;
-
-/*************************************************************************/
-
-ServerConfig::ServerConfig()
+Block::Block(const Anope::string &n) : name(n)
{
- this->Read();
-
- if (NSDefaults.empty())
- {
- this->NSDefFlags.insert("SECURE");
- this->NSDefFlags.insert("MEMO_SIGNON");
- this->NSDefFlags.insert("MEMO_RECEIVE");
- }
- else if (!NSDefaults.equals_ci("none"))
- {
- spacesepstream options(NSDefaults);
- Anope::string option;
- while (options.GetToken(option))
- {
- if (option.equals_ci("msg"))
- {
- if (!this->UsePrivmsg)
- Log() << "msg in <nickserv:defaults> can only be used when options:useprivmsg is set";
- else
- this->NSDefFlags.insert(option.upper());
- }
- else
- this->NSDefFlags.insert(option.upper());
- }
- }
-
- if (this->CSDefBantype < 0 || this->CSDefBantype > 3)
- {
- throw ConfigException("Value of CSDefBantype must be between 0 and 3 included");
- }
-
- if (CSDefaults.empty())
- {
- this->CSDefFlags.insert("KEEPTOPIC");
- this->CSDefFlags.insert("SECURE");
- this->CSDefFlags.insert("SECUREFOUNDER");
- this->CSDefFlags.insert("SIGNKICK");
- }
- else if (!CSDefaults.equals_ci("none"))
- {
- spacesepstream options(CSDefaults);
- Anope::string option;
- while (options.GetToken(option))
- this->CSDefFlags.insert(option.upper());
- }
-
- if (UseStrictPrivMsg)
- UseStrictPrivMsgString = "/";
- else
- UseStrictPrivMsgString ="/msg ";
-
-
- if (!BSDefaults.empty())
- {
- spacesepstream options(BSDefaults);
- Anope::string option;
- while (options.GetToken(option))
- this->BSDefFlags.insert("BS_" + option.upper());
- }
-
- /* Ulines */
- if (!UlineServers.empty())
- {
- this->Ulines.clear();
-
- spacesepstream ulines(UlineServers);
- Anope::string uline;
- while (ulines.GetToken(uline))
- this->Ulines.push_back(uline);
- }
-
- if (this->LimitSessions)
- {
- if (this->MaxSessionKill && !this->SessionAutoKillExpiry)
- this->SessionAutoKillExpiry = 1800; /* 30 minutes */
- }
-
- /* Check the user keys */
- if (this->Seed == 0)
- Log() << "Configuration option options:seed should be set. It's for YOUR safety! Remember that!";
-
- ModeManager::UpdateDefaultMLock(this);
-
- if (this->CaseMap == "ascii")
- Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<char>());
- else if (this->CaseMap == "rfc1459")
- Anope::casemap = std::locale(std::locale(), new Anope::rfc1459_ctype<char>());
- else
- {
- try
- {
- Anope::casemap = std::locale(this->CaseMap.c_str());
- }
- catch (const std::runtime_error &)
- {
- Log() << "Unknown casemap " << this->CaseMap << " - casemap not changed";
- }
- }
- Anope::CaseMapRebuild();
-
- if (this->SessionIPv4CIDR > 32 || this->SessionIPv6CIDR > 128)
- throw ConfigException("Session CIDR value out of range");
-
- ConfigReader reader(this);
- FOREACH_MOD(I_OnReload, OnReload(this, reader));
-
-#ifndef _WIN32
- if (!this->User.empty())
- {
- errno = 0;
- struct passwd *u = getpwnam(this->User.c_str());
- if (u == NULL)
- Log() << "Unable to setuid to " << this->User << ": " << Anope::LastError();
- else if (setuid(u->pw_uid) == -1)
- Log() << "Unable to setuid to " << this->User << ": " << Anope::LastError();
- else
- Log() << "Successfully set user to " << this->User;
- }
- if (!this->Group.empty())
- {
- errno = 0;
- struct group *g = getgrnam(this->Group.c_str());
- if (g == NULL)
- Log() << "Unable to setgid to " << this->Group << ": " << Anope::LastError();
- else if (setuid(g->gr_gid) == -1)
- Log() << "Unable to setgid to " << this->Group << ": " << Anope::LastError();
- else
- Log() << "Successfully set group to " << this->Group;
- }
-#endif
}
-bool ServerConfig::CheckOnce(const Anope::string &tag)
+const Anope::string &Block::GetName() const
{
- int count = ConfValueEnum(config_data, tag);
- if (count > 1)
- throw ConfigException("You have more than one <" + tag + "> tag, this is not permitted.");
- if (count < 1)
- throw ConfigException("You have not defined a <" + tag + "> tag, this is required.");
- return true;
+ return name;
}
-bool NoValidation(ServerConfig *, const Anope::string &, const Anope::string &, ValueItem &)
+int Block::CountBlock(const Anope::string &bname)
{
- return true;
-}
-
-void ServerConfig::ValidateNoSpaces(const Anope::string &p, const Anope::string &tag, const Anope::string &val) const
-{
- for (Anope::string::const_iterator ptr = p.begin(), end = p.end(); ptr != end; ++ptr)
- if (*ptr == ' ')
- throw ConfigException("The value of <" + tag + ":" + val + "> cannot contain spaces");
+ if (!this)
+ return 0;
+
+ return blocks.count(bname);
}
-/* NOTE: Before anyone asks why we're not using inet_pton for this, it is because inet_pton and friends do not return so much detail,
- * even in LastError(). They just return 'yes' or 'no' to an address without such detail as to whats WRONG with the address.
- * Because ircd users arent as technical as they used to be (;)) we are going to give more of a useful error message.
- */
-void ServerConfig::ValidateIP(const Anope::string &p, const Anope::string &tag, const Anope::string &val, bool wild) const
+Block* Block::GetBlock(const Anope::string &bname, int num)
{
- int num_dots = 0, num_seps = 0;
- bool not_numbers = false, not_hex = false;
-
- if (!p.empty())
- {
- if (p[0] == '.')
- throw ConfigException("The value of <" + tag + ":" + val + "> is not an IP address");
-
- for (Anope::string::const_iterator ptr = p.begin(), end = p.end(); ptr != end; ++ptr)
- {
- if (wild && (*ptr == '*' || *ptr == '?' || *ptr == '/'))
- continue;
-
- if (*ptr != ':' && *ptr != '.' && (*ptr < '0' || *ptr > '9'))
- {
- not_numbers = true;
- if (toupper(*ptr) < 'A' || toupper(*ptr) > 'F')
- not_hex = true;
- }
- switch (*ptr)
- {
- case ' ':
- throw ConfigException("The value of <" + tag + ":" + val + "> is not an IP address");
- case '.':
- ++num_dots;
- break;
- case ':':
- ++num_seps;
- }
- }
- if (num_dots > 3)
- throw ConfigException("The value of <" + tag + ":" + val + "> is an IPv4 address with too many fields!");
-
- if (num_seps > 8)
- throw ConfigException("The value of <" + tag + ":" + val + "> is an IPv6 address with too many fields!");
-
- if (!num_seps && num_dots < 3 && !wild)
- throw ConfigException("The value of <" + tag + ":" + val + "> looks to be a malformed IPv4 address");
-
- if (!num_seps && num_dots == 3 && not_numbers)
- throw ConfigException("The value of <" + tag + ":" + val + "> contains non-numeric characters in an IPv4 address");
-
- if (num_seps && not_hex)
- throw ConfigException("The value of <" + tag + ":" + val + "> contains non-hexdecimal characters in an IPv6 address");
+ if (!this)
+ return NULL;
+
+ std::pair<block_map::iterator, block_map::iterator> it = blocks.equal_range(bname);
- if (num_seps && num_dots != 3 && num_dots && !wild)
- throw ConfigException("The value of <" + tag + ":" + val + "> is a malformed IPv6 4in6 address");
- }
+ for (int i = 0; it.first != it.second; ++it.first, ++i)
+ if (i == num)
+ return &it.first->second;
+ return NULL;
}
-void ServerConfig::ValidateHostname(const Anope::string &p, const Anope::string &tag, const Anope::string &val) const
+bool Block::Set(const Anope::string &tag, const Anope::string &value)
{
- if (p.equals_ci("localhost"))
- return;
-
- int num_dots = 0, num_seps = 0;
- if (!p.empty())
- {
- if (p[0] == '.')
- throw ConfigException("The value of <" + tag + ":" + val + "> is not a valid hostname");
- for (unsigned i = 0, end = p.length(); i < end; ++i)
- {
- switch (p[i])
- {
- case ' ':
- throw ConfigException("The value of <" + tag + ":" + val + "> is not a valid hostname");
- case '.':
- ++num_dots;
- break;
- case ':':
- ++num_seps;
- break;
- }
- }
- if (!num_dots && !num_seps)
- throw ConfigException("The value of <" + tag + ":" + val + "> is not a valid hostname");
- }
-}
+ if (!this)
+ return false;
-static bool ValidateNotEmpty(ServerConfig *, const Anope::string &tag, const Anope::string &value, ValueItem &data)
-{
- if (data.GetValue().empty())
- throw ConfigException("The value for <" + tag + ":" + value + "> cannot be empty!");
+ items[tag] = value;
return true;
}
-static bool ValidateNotZero(ServerConfig *, const Anope::string &tag, const Anope::string &value, ValueItem &data)
+const Block::item_map* Block::GetItems() const
{
- if (!data.GetInteger() && Anope::DoTime(data.GetValue()) <= 0)
- throw ConfigException("The value for <" + tag + ":" + value + "> must be non-zero!");
- return true;
+ if (this)
+ return &items;
+ else
+ return NULL;
}
-static bool ValidateEmailReg(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data)
+template<> const Anope::string& Block::Get(const Anope::string &tag, const Anope::string& def) const
{
- if (!config->NSRegistration.equals_ci("none") && !config->NSRegistration.equals_ci("disable"))
- {
- if (value.equals_ci("unconfirmedexpire"))
- {
- if (!data.GetInteger() && Anope::DoTime(data.GetValue()) <= 0)
- throw ConfigException("The value for <" + tag + ":" + value + "> must be non-zero when e-mail or admin registration is enabled!");
- }
- else
- {
- if (!data.GetBool())
- throw ConfigException("The value for <" + tag + ":" + value + "> must be set to yes when e-mail or admin registrations is enabled!");
- }
- }
- return true;
-}
+ if (!this)
+ return def;
-static bool ValidatePort(ServerConfig *, const Anope::string &tag, const Anope::string &value, ValueItem &data)
-{
- int port = data.GetInteger();
- if (!port)
- return true;
- if (port < 1 || port > 65535)
- throw ConfigException("The value for <" + tag + ":" + value + "> is not a value port, it must be between 1 and 65535!");
- return true;
-}
+ Anope::map<Anope::string>::const_iterator it = items.find(tag);
+ if (it != items.end())
+ return it->second;
-static bool ValidateBantype(ServerConfig *, const Anope::string &, const Anope::string &, ValueItem &data)
-{
- int bantype = data.GetInteger();
- if (bantype < 0 || bantype > 3)
- throw ConfigException("The value for <chanserv:defbantype> must be between 0 and 3!");
- return true;
+ return def;
}
-static bool ValidateNickServ(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data)
+template<> time_t Block::Get(const Anope::string &tag, const Anope::string &def) const
{
- if (!config->NickServ.empty())
- {
- if (value.equals_ci("releasetimeout") || value.equals_ci("accessmax") || value.equals_ci("listmax"))
- return ValidateNotZero(config, tag, value, data);
- else if (value.equals_ci("enforceruser") || value.equals_ci("enforcerhost"))
- return ValidateNotEmpty(config, tag, value, data);
- else if (value.equals_ci("guestnickprefix"))
- {
- ValidateNotEmpty(config, tag, value, data);
- if (data.GetValue().length() > 21)
- throw ConfigException("The value for <nickserv:guestnickprefix> cannot exceed 21 characters in length!");
- }
- else if (value.equals_ci("registration"))
- if (!data.GetValue().equals_ci("none") && !data.GetValue().equals_ci("mail") && !data.GetValue().equals_ci("admin") && !data.GetValue().equals_ci("disable"))
- throw ConfigException("The value for <nickserv:registration> must be one of \"none\", \"mail\", \"admin\", or \"disable\"");
- }
- return true;
+ return Anope::DoTime(Get<const Anope::string &>(tag, def));
}
-static bool ValidateChanServ(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data)
+template<> const char* Block::Get(const Anope::string &tag, const Anope::string &def) const
{
- if (!config->ChanServ.empty())
- {
- if ((value.equals_ci("decription") || value.equals_ci("autokickreason")) && data.GetValue().empty())
- throw ConfigException("The value for <" + tag + ":" + value + "> cannot be empty when ChanServ is enabled!");
- else if (value.equals_ci("defbantype"))
- return ValidateBantype(config, tag, value, data);
- else if (value.equals_ci("accessmax") || value.equals_ci("autokickmax") || value.equals_ci("inhabit") || value.equals_ci("listmax"))
- return ValidateNotZero(config, tag, value, data);
- }
- return true;
+ return this->Get<const Anope::string &>(tag, def).c_str();
}
-static bool ValidateBotServ(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data)
+template<> bool Block::Get(const Anope::string &tag, const Anope::string &def) const
{
- if (!config->BotServ.empty())
- {
- if (value.equals_ci("badwordsmax") || value.equals_ci("keepdata"))
- {
- if (!data.GetInteger() && Anope::DoTime(data.GetValue()) <= 0)
- throw ConfigException("The value for <" + tag + ":" + value + "> must be non-zero when BotServ is enabled!");
- }
- else if (value.equals_ci("minusers"))
- {
- if (data.GetInteger() < 0)
- throw ConfigException("The value for <" + tag + ":" + value + "> must be greater than or equal to zero!");
- }
- }
- return true;
+ const Anope::string &str = Get<const Anope::string &>(tag, def);
+ return str.equals_ci("yes") || str.equals_ci("on") || str.equals_ci("true");
}
-static bool ValidateLimitSessions(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data)
+static void ValidateNotEmpty(const Anope::string &block, const Anope::string &name, const Anope::string &value)
{
- if (config->LimitSessions)
- {
- if (value.equals_ci("maxsessionlimit") || value.equals_ci("exceptionexpiry"))
- {
- if (!data.GetInteger() && Anope::DoTime(data.GetValue()) <= 0)
- throw ConfigException("The value for <" + tag + ":" + value + "> must be non-zero when session limiting is enabled!");
- }
- }
- return true;
+ if (value.empty())
+ throw ConfigException("The value for <" + block + ":" + name + "> cannot be empty!");
}
-static bool ValidateOperServ(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data)
+template<typename T> static void ValidateNotZero(const Anope::string &block, const Anope::string &name, T value)
{
- if (!config->OperServ.empty())
- {
- if (value.equals_ci("autokillexpiry") || value.equals_ci("chankillexpiry") || value.equals_ci("snlineexpiry") || value.equals_ci("sqlineexpiry"))
- return ValidateNotZero(config, tag, value, data);
- else if (value.equals_ci("maxsessionlimit") || value.equals_ci("exceptionexpiry"))
- return ValidateLimitSessions(config, tag, value, data);
- }
- return true;
+ if (!value)
+ throw ConfigException("The value for <" + block + ":" + name + "> cannot be zero!");
}
-static bool ValidateNickLen(ServerConfig *, const Anope::string &, const Anope::string &, ValueItem &data)
+Conf::Conf() : Block("")
{
- int nicklen = data.GetInteger();
- if (!nicklen)
- {
- Log() << "You have not defined the <networkinfo:nicklen> directive. It is strongly";
- Log() << "adviced that you do configure this correctly in your services.conf";
- data.Set(31);
- }
- else if (nicklen < 1)
- {
- Log() << "<networkinfo:nicklen> has an invalid value; setting to 31";
- data.Set(31);
- }
- return true;
-}
+ ReadTimeout = 0;
+ UsePrivmsg = DefPrivmsg = false;
-static bool ValidateMail(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data)
-{
- if (config->UseMail)
- {
- Anope::string check[] = { "sendmailpath", "sendfrom", "registration_subject", "registration_message", "emailchange_subject", "emailchange_message", "memo_subject", "memo_message", "" };
- for (int i = 0; !check[i].empty(); ++i)
- if (value.equals_ci(check[i]))
- if (data.GetValue().empty())
- throw ConfigException("The value for <" + tag + ":" + value + "> cannot be empty when e-mail is enabled!");
- }
- return true;
-}
+ this->LoadConf(ServicesConf);
-static bool ValidateGlobalOnCycle(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data)
-{
- if (config->GlobalOnCycle)
+ for (int i = 0; i < this->CountBlock("include"); ++i)
{
- if (data.GetValue().empty())
- {
- Log() << "<" << tag << ":" << value << "> was undefined, disabling <options:globaloncycle>";
- config->GlobalOnCycle = false;
- }
- }
- return true;
-}
+ Block *include = this->GetBlock("include", i);
-static bool InitUplinks(ServerConfig *config, const Anope::string &)
-{
- if (!config->Uplinks.empty())
- {
- std::vector<ServerConfig::Uplink *>::iterator curr_uplink = config->Uplinks.begin(), end_uplink = config->Uplinks.end();
- for (; curr_uplink != end_uplink; ++curr_uplink)
- delete *curr_uplink;
- }
- config->Uplinks.clear();
- return true;
-}
+ const Anope::string &type = include->Get<const Anope::string &>("type"),
+ &file = include->Get<const Anope::string &>("name");
-static bool DoUplink(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *)
-{
- // Validation variables
- Anope::string host = values[0].GetValue(), password = values[3].GetValue();
- int port = values[2].GetInteger();
- bool ipv6 = values[1].GetBool();
- ValueItem vi_host(host), vi_port(port), vi_password(password);
- // Validate the host to make sure it is not empty
- if (!ValidateNotEmpty(config, "uplink", "host", vi_host))
- throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information.");
- // Validate the port to make sure it is a valid port
- if (!ValidatePort(config, "uplink", "port", vi_port))
- throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information.");
- // Validate the password to make sure it is not empty
- if (!ValidateNotEmpty(config, "uplink", "password", vi_password))
- throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information.");
- // If we get here, all the values are valid, we'll add it to the Uplinks list
- config->Uplinks.push_back(new ServerConfig::Uplink(host, port, password, ipv6));
- return true;
-}
-
-static bool DoneUplinks(ServerConfig *config, const Anope::string &)
-{
- if (config->Uplinks.empty())
- throw ConfigException("You must define at least one uplink block!");
- return true;
-}
-
-static bool InitOperTypes(ServerConfig *config, const Anope::string &)
-{
- for (std::list<OperType *>::iterator it = config->MyOperTypes.begin(), it_end = config->MyOperTypes.end(); it != it_end; ++it)
- delete *it;
+ File f(file, type == "executable");
+ this->LoadConf(f);
+ }
- config->MyOperTypes.clear();
- return true;
-}
+ FOREACH_MOD(I_OnReload, OnReload(this));
-static bool DoOperType(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *)
-{
- Anope::string name = values[0].GetValue();
- Anope::string inherits = values[1].GetValue();
- Anope::string commands = values[2].GetValue();
- Anope::string privs = values[3].GetValue();
- Anope::string modes = values[4].GetValue();
-
- ValueItem vi(name);
- if (!ValidateNotEmpty(config, "opertype", "name", vi))
- throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information.");
-
- OperType *ot = new OperType(name);
- ot->modes = modes;
-
- Anope::string tok;
- spacesepstream cmdstr(commands);
- while (cmdstr.GetToken(tok))
- ot->AddCommand(tok);
-
- spacesepstream privstr(privs);
- while (privstr.GetToken(tok))
- ot->AddPriv(tok);
-
- commasepstream inheritstr(inherits);
- while (inheritstr.GetToken(tok))
+ /* Check for modified values that aren't allowed to be modified */
+ if (Config)
{
- /* Strip leading ' ' after , */
- if (tok.length() > 1 && tok[0] == ' ')
- tok.erase(tok.begin());
- for (std::list<OperType *>::iterator it = config->MyOperTypes.begin(), it_end = config->MyOperTypes.end(); it != it_end; ++it)
+ struct
{
- if ((*it)->GetName().equals_ci(tok))
- {
- Log() << "Inheriting commands and privs from " << (*it)->GetName() << " to " << ot->GetName();
- ot->Inherits(*it);
- break;
- }
- }
+ Anope::string block;
+ Anope::string name;
+ Anope::string def;
+ } noreload[] = {
+ {"serverinfo", "name", ""},
+ {"serverinfo", "description", ""},
+ {"serverinfo", "localhost", ""},
+ {"serverinfo", "id", ""},
+ {"serverinfo", "pid", ""},
+ {"networkinfo", "nicklen", "31"},
+ {"networkinfo", "userlen", "10"},
+ {"networkinfo", "hostlen", "64"},
+ {"networkinfo", "chanlen", "32"},
+ {"options", "passlen", "32"},
+ };
+
+ for (unsigned i = 0; i < sizeof(noreload) / sizeof(noreload[0]); ++i)
+ if (this->GetBlock(noreload[i].block)->Get<const Anope::string &>(noreload[i].name, noreload[i].def) != Config->GetBlock(noreload[i].block)->Get<const Anope::string &>(noreload[i].name, noreload[i].def))
+ throw ConfigException("<" + noreload[i].block + ":" + noreload[i].name + "> can not be modified once set");
}
- config->MyOperTypes.push_back(ot);
- return true;
-}
+ Block *options = this->GetBlock("options"), *mail = this->GetBlock("mail");
-static bool DoneOperTypes(ServerConfig *, const Anope::string &)
-{
- return true;
-}
+ ValidateNotZero("options", "releasetimeout", options->Get<time_t>("releasetimeout"));
+ ValidateNotEmpty("options", "enforceruser", options->Get<const Anope::string &>("enforceruser"));
+ ValidateNotEmpty("options", "enforcerhost", options->Get<const Anope::string &>("enforcerhost"));
+ ValidateNotEmpty("options", "guestnickprefix", options->Get<const Anope::string &>("guestnickprefix"));
+ spacesepstream(options->Get<const Anope::string &>("ulineservers")).GetTokens(this->Ulines);
-/*************************************************************************/
+ if (mail->Get<bool>("usemail"))
+ {
+ Anope::string check[] = { "sendmailpath", "sendfrom", "registration_subject", "registration_message", "emailchange_subject", "emailchange_message", "memo_subject", "memo_message" };
+ for (unsigned i = 0; i < sizeof(check) / sizeof(Anope::string); ++i)
+ ValidateNotEmpty("mail", check[i], mail->Get<const Anope::string &>(check[i]));
+ }
-static bool InitOpers(ServerConfig *config, const Anope::string &)
-{
- for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
+ this->ReadTimeout = options->Get<unsigned>("readtimeout");
+ this->UsePrivmsg = options->Get<bool>("useprivmsg");
+ this->StrictPrivmsg = options->Get<bool>("usestrictprivmsg") ? "/msg " : "/";
{
- NickCore *nc = it->second;
- nc->QueueUpdate();
- if (nc->o && nc->o->config)
- nc->o = NULL;
+ std::vector<Anope::string> defaults;
+ spacesepstream(this->GetModule("nickserv")->Get<const Anope::string &>("defaults")).GetTokens(defaults);
+ this->DefPrivmsg = std::find(defaults.begin(), defaults.end(), "msg") != defaults.end();
}
+ this->DefLanguage = options->Get<const Anope::string &>("defaultlanguage");
- for (unsigned i = 0; i < config->Opers.size(); ++i)
- delete config->Opers[i];
- config->Opers.clear();
+ for (int i = 0; i < this->CountBlock("uplink"); ++i)
+ {
+ Block *uplink = this->GetBlock("uplink", i);
- return true;
-}
+ const Anope::string &host = uplink->Get<const Anope::string &>("host");
+ bool ipv6 = uplink->Get<bool>("ipv6");
+ int port = uplink->Get<int>("port");
+ const Anope::string &password = uplink->Get<const Anope::string &>("password");
-static bool DoOper(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *)
-{
- Anope::string name = values[0].GetValue();
- Anope::string type = values[1].GetValue();
- bool require_oper = values[2].GetBool();
- Anope::string password = values[3].GetValue();
- Anope::string certfp = values[4].GetValue();
- Anope::string host = values[5].GetValue();
- Anope::string vhost = values[6].GetValue();
-
- ValueItem vi(name);
- if (!ValidateNotEmpty(config, "oper", "name", vi))
- throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information.");
-
- ValueItem vi2(type);
- if (!ValidateNotEmpty(config, "oper", "type", vi2))
- throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information.");
-
- OperType *ot = NULL;
- for (std::list<OperType *>::iterator it = config->MyOperTypes.begin(), it_end = config->MyOperTypes.end(); it != it_end; ++it)
- if ((*it)->GetName() == type)
- ot = *it;
- if (ot == NULL)
- throw ConfigException("Oper block for " + name + " has invalid oper type " + type);
-
- Oper *o = new Oper(name, ot);
- o->require_oper = require_oper;
- o->config = true;
- o->password = password;
- o->certfp = certfp;
- spacesepstream(host).GetTokens(o->hosts);
- o->vhost = vhost;
- config->Opers.push_back(o);
+ ValidateNotEmpty("uplink", "host", host);
+ ValidateNotEmpty("uplink", "password", password);
- return true;
-}
+ this->Uplinks.push_back(Uplink(host, port, password, ipv6));
+ }
-static bool DoneOpers(ServerConfig *config, const Anope::string &)
-{
- for (unsigned i = 0; i < config->Opers.size(); ++i)
+ for (int i = 0; i < this->CountBlock("module"); ++i)
{
- Oper *o = config->Opers[i];
+ Block *module = this->GetBlock("module", i);
- const NickAlias *na = NickAlias::Find(o->name);
- if (!na)
- // Nonexistant nick
- continue;
+ const Anope::string &modname = module->Get<const Anope::string &>("name");
- na->nc->o = o;
- Log() << "Tied oper " << na->nc->display << " to type " << o->ot->GetName();
+ ValidateNotEmpty("module", "name", modname);
+
+ this->ModulesAutoLoad.push_back(modname);
}
- return true;
-}
+ for (int i = 0; i < this->CountBlock("opertype"); ++i)
+ {
+ Block *opertype = this->GetBlock("opertype", i);
-/*************************************************************************/
+ const Anope::string &oname = opertype->Get<const Anope::string &>("name"),
+ &modes = opertype->Get<const Anope::string &>("modes"),
+ &inherits = opertype->Get<const Anope::string &>("inherits"),
+ &commands = opertype->Get<const Anope::string &>("commands"),
+ &privs = opertype->Get<const Anope::string &>("privs");
-static std::map<Anope::string, Anope::string> defines;
-static bool InitDefine(ServerConfig *config, const Anope::string &)
-{
- defines.clear();
- return true;
-}
+ ValidateNotEmpty("opertype", "name", oname);
-static bool DoDefine(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *)
-{
- Anope::string name = values[0].GetValue(), value = values[1].GetValue();
- defines[name] = value;
- return true;
-}
+ OperType *ot = new OperType(oname);
+ ot->modes = modes;
-static bool DoneDefine(ServerConfig *config, const Anope::string &)
-{
- return true;
-}
+ spacesepstream cmdstr(commands);
+ for (Anope::string str; cmdstr.GetToken(str);)
+ ot->AddCommand(str);
-/*************************************************************************/
+ spacesepstream privstr(privs);
+ for (Anope::string str; cmdstr.GetToken(str);)
+ ot->AddPriv(str);
-static bool InitInclude(ServerConfig *config, const Anope::string &)
-{
- return true;
-}
+ commasepstream inheritstr(inherits);
+ for (Anope::string str; inheritstr.GetToken(str);)
+ {
+ /* Strip leading ' ' after , */
+ if (str.length() > 1 && str[0] == ' ')
+ str.erase(str.begin());
+ for (unsigned j = 0; j < this->MyOperTypes.size(); ++j)
+ {
+ OperType *ot2 = this->MyOperTypes[j];
-static bool DoInclude(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *)
-{
- Anope::string type = values[0].GetValue();
- Anope::string file = values[1].GetValue();
+ if (ot2->GetName().equals_ci(str))
+ {
+ Log() << "Inheriting commands and privs from " << ot2->GetName() << " to " << ot->GetName();
+ ot->Inherits(ot2);
+ break;
+ }
+ }
+ }
- if (type != "file" && type != "executable")
- throw ConfigException("include:type must be either \"file\" or \"executable\"");
-
- ConfigurationFile f(file, type == "executable");
- config->LoadConf(f);
+ this->MyOperTypes.push_back(ot);
+ }
- return true;
-}
+ for (int i = 0; i < this->CountBlock("oper"); ++i)
+ {
+ Block *oper = this->GetBlock("oper", i);
-static bool DoneInclude(ServerConfig *config, const Anope::string &)
-{
- return true;
-}
+ const Anope::string &nname = oper->Get<const Anope::string &>("name"),
+ &type = oper->Get<const Anope::string &>("type"),
+ &password = oper->Get<const Anope::string &>("password"),
+ &certfp = oper->Get<const Anope::string &>("certfp"),
+ &host = oper->Get<const Anope::string &>("host"),
+ &vhost = oper->Get<const Anope::string &>("vhost");
+ bool require_oper = oper->Get<bool>("require_oper");
-/*************************************************************************/
+ ValidateNotEmpty("oper", "name", nname);
+ ValidateNotEmpty("oper", "type", type);
+
+ OperType *ot = NULL;
+ for (unsigned j = 0; j < this->MyOperTypes.size(); ++j)
+ if (this->MyOperTypes[j]->GetName() == type)
+ ot = this->MyOperTypes[j];
+ if (ot == NULL)
+ throw ConfigException("Oper block for " + nname + " has invalid oper type " + type);
-static bool InitModules(ServerConfig *, const Anope::string &)
-{
- return true;
-}
+ Oper *o = new Oper(nname, ot);
+ o->require_oper = require_oper;
+ o->config = true;
+ o->password = password;
+ o->certfp = certfp;
+ spacesepstream(host).GetTokens(o->hosts);
+ o->vhost = vhost;
-static bool DoModule(ServerConfig *conf, const Anope::string &, const Anope::string *, ValueList &values, int *)
-{
- // First we validate that there was a name in the module block
- Anope::string module = values[0].GetValue();
- ValueItem vi(module);
- if (!ValidateNotEmpty(conf, "module", "name", vi))
- throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information.");
- conf->ModulesAutoLoad.push_back(module);
- return true;
-}
+ this->Opers.push_back(o);
+ }
-static bool DoneModules(ServerConfig *config, const Anope::string &)
-{
- if (Config)
- {
- for (std::list<Anope::string>::iterator it = Config->ModulesAutoLoad.begin(); it != Config->ModulesAutoLoad.end(); ++it)
- if (std::find(config->ModulesAutoLoad.begin(), config->ModulesAutoLoad.end(), *it) == config->ModulesAutoLoad.end())
- ModuleManager::UnloadModule(ModuleManager::FindModule(*it), NULL);
- for (std::list<Anope::string>::iterator it = config->ModulesAutoLoad.begin(); it != config->ModulesAutoLoad.end(); ++it)
- if (std::find(Config->ModulesAutoLoad.begin(), Config->ModulesAutoLoad.end(), *it) == Config->ModulesAutoLoad.end())
- ModuleManager::LoadModule(*it, NULL);
+ for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
+ it->second->conf = false;
+ for (int i = 0; i < this->CountBlock("service"); ++i)
+ {
+ Block *service = this->GetBlock("service", i);
+
+ const Anope::string &nick = service->Get<const Anope::string &>("nick"),
+ &user = service->Get<const Anope::string &>("user"),
+ &host = service->Get<const Anope::string &>("host"),
+ &gecos = service->Get<const Anope::string &>("gecos"),
+ &modes = service->Get<const Anope::string &>("modes"),
+ &channels = service->Get<const Anope::string &>("channels");
+
+ ValidateNotEmpty("service", "nick", nick);
+ ValidateNotEmpty("service", "user", user);
+ ValidateNotEmpty("service", "host", host);
+ ValidateNotEmpty("service", "gecos", gecos);
+
+ BotInfo *bi = BotInfo::Find(nick, true);
+ if (!bi)
+ bi = new BotInfo(nick, user, host, gecos, modes);
+ bi->conf = true;
+
+ std::vector<Anope::string> oldchannels = bi->botchannels;
+ bi->botchannels.clear();
+ commasepstream sep(channels);
+ for (Anope::string token; sep.GetToken(token);)
+ {
+ bi->botchannels.push_back(token);
+ size_t ch = token.find('#');
+ Anope::string chname, want_modes;
+ if (ch == Anope::string::npos)
+ chname = token;
+ else
+ {
+ want_modes = token.substr(0, ch);
+ chname = token.substr(ch);
+ }
+ bi->Join(chname);
+ Channel *c = Channel::Find(chname);
+ if (!c)
+ continue; // Can't happen
+
+ /* Remove all existing modes */
+ ChanUserContainer *cu = c->FindUser(bi);
+ if (cu != NULL)
+ for (size_t j = 0; j < cu->status.Modes().length(); ++j)
+ c->RemoveMode(bi, ModeManager::FindChannelModeByChar(cu->status.Modes()[j]), bi->GetUID());
+ /* Set the new modes */
+ for (unsigned j = 0; j < want_modes.length(); ++j)
+ {
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(want_modes[j]);
+ if (cm == NULL)
+ cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_modes[j]));
+ if (cm && cm->type == MODE_STATUS)
+ c->SetMode(bi, cm, bi->GetUID());
+ }
+ }
+ for (unsigned k = 0; k < oldchannels.size(); ++k)
+ {
+ size_t ch = oldchannels[k].find('#');
+ Anope::string chname = oldchannels[k].substr(ch != Anope::string::npos ? ch : 0);
+
+ bool found = false;
+ for (unsigned j = 0; j < bi->botchannels.size(); ++j)
+ {
+ ch = bi->botchannels[j].find('#');
+ Anope::string ochname = bi->botchannels[j].substr(ch != Anope::string::npos ? ch : 0);
+
+ if (chname.equals_ci(ochname))
+ found = true;
+ }
+
+ if (found)
+ continue;
+
+ Channel *c = Channel::Find(chname);
+ if (c)
+ bi->Part(c);
+ }
+ }
+
+ for (int i = 0; i < this->CountBlock("log"); ++i)
+ {
+ Block *log = this->GetBlock("log", i);
+
+ int logage = log->Get<int>("logage");
+ bool rawio = l