summaryrefslogtreecommitdiff
path: root/src/config.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2010-06-19 11:54:08 -0400
committerAdam <Adam@anope.org>2010-06-19 11:54:08 -0400
commit52058fe87b4b0475b1775198c725af14e540d355 (patch)
treec3597d6411a006ffbb670d2ce761101b9640e9b6 /src/config.cpp
parent43e951aed54f838ba55a4c1552214773aee2fb2f (diff)
parentdf9d291bcba9788e51d11424ebaf6f05c26cc80f (diff)
Merge remote branch 'origin/1.9.3' into 1.9
Diffstat (limited to 'src/config.cpp')
-rw-r--r--src/config.cpp1788
1 files changed, 1788 insertions, 0 deletions
diff --git a/src/config.cpp b/src/config.cpp
new file mode 100644
index 000000000..a1264abce
--- /dev/null
+++ b/src/config.cpp
@@ -0,0 +1,1788 @@
+/* Configuration file handling.
+ *
+ * (C) 2003-2010 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ *
+ *
+ */
+
+#include "services.h"
+#include "config.h"
+#include "hashcomp.h" // If this gets added to services.h or someplace else later, remove it from here -- CyberBotX
+
+/*************************************************************************/
+
+std::string services_conf = "services.conf"; // Services configuration file name
+ServerConfig Config;
+
+static std::string Modules;
+static std::string EncModules;
+static std::string DBModules;
+static std::string HostCoreModules;
+static std::string MemoCoreModules;
+static std::string BotCoreModules;
+static std::string OperCoreModules;
+static std::string NickCoreModules;
+static std::string ChanCoreModules;
+static std::string DefCon1;
+static std::string DefCon2;
+static std::string DefCon3;
+static std::string DefCon4;
+static char *UlineServers;
+static std::string OSNotifications;
+static std::string BSDefaults;
+static std::string CSDefaults;
+static char *temp_nsuserhost;
+static std::string NSDefaults;
+
+/*************************************************************************/
+
+ServerConfig::ServerConfig() : include_stack(), errstr(""), newconfig(), config_data()
+{
+ this->ClearStack();
+}
+
+void ServerConfig::ClearStack()
+{
+ include_stack.clear();
+}
+
+bool ServerConfig::CheckOnce(const char *tag)
+{
+ int count = ConfValueEnum(config_data, tag);
+ if (count > 1)
+ throw ConfigException(std::string("You have more than one <") + tag + "> tag, this is not permitted.");
+ if (count < 1)
+ throw ConfigException(std::string("You have not defined a <") + tag + "> tag, this is required.");
+ return true;
+}
+
+bool NoValidation(ServerConfig *, const char *, const char *, ValueItem &)
+{
+ return true;
+}
+
+bool DoneConfItem(ServerConfig *, const char *)
+{
+ return true;
+}
+
+void ServerConfig::ValidateNoSpaces(const char *p, const std::string &tag, const std::string &val)
+{
+ for (const char *ptr = p; *ptr; ++ptr)
+ if (*ptr == ' ')
+ throw ConfigException(std::string("The value of <") + tag + ":" + val + "> cannot contain spaces");
+}
+
+/* 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 strerror(errno). 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 char *p, const std::string &tag, const std::string &val, bool wild)
+{
+ int num_dots = 0, num_seps = 0;
+ bool not_numbers = false, not_hex = false;
+
+ if (*p)
+ {
+ if (*p == '.')
+ throw ConfigException(std::string("The value of <") + tag + ":" + val + "> is not an IP address");
+
+ for (const char *ptr = p; *ptr; ++ptr)
+ {
+ if (wild && (*ptr == '*' || *ptr == '?' || *ptr == '/'))
+ continue;
+
+ if (*ptr != ':' && *ptr != '.')
+ {
+ if (*ptr < '0' || *ptr > '9')
+ {
+ not_numbers = true;
+ if (toupper(*ptr) < 'A' || toupper(*ptr) > 'F')
+ not_hex = true;
+ }
+ }
+ switch (*ptr)
+ {
+ case ' ':
+ throw ConfigException(std::string("The value of <") + tag + ":" + val + "> is not an IP address");
+ case '.':
+ ++num_dots;
+ break;
+ case ':':
+ ++num_seps;
+ }
+ }
+ if (num_dots > 3)
+ throw ConfigException(std::string("The value of <") + tag + ":" + val + "> is an IPv4 address with too many fields!");
+
+ if (num_seps > 8)
+ throw ConfigException(std::string("The value of <") + tag + ":" + val + "> is an IPv6 address with too many fields!");
+
+ if (!num_seps && num_dots < 3 && !wild)
+ throw ConfigException(std::string("The value of <") + tag + ":" + val + "> looks to be a malformed IPv4 address");
+
+ if (!num_seps && num_dots == 3 && not_numbers)
+ throw ConfigException(std::string("The value of <") + tag + ":" + val + "> contains non-numeric characters in an IPv4 address");
+
+ if (num_seps && not_hex)
+ throw ConfigException(std::string("The value of <") + tag + ":" + val + "> contains non-hexdecimal characters in an IPv6 address");
+
+ if (num_seps && num_dots != 3 && num_dots && !wild)
+ throw ConfigException(std::string("The value of <") + tag + ":" + val + "> is a malformed IPv6 4in6 address");
+ }
+}
+
+void ServerConfig::ValidateHostname(const char *p, const std::string &tag, const std::string &val)
+{
+ if (!strcasecmp(p, "localhost"))
+ return;
+
+ int num_dots = 0, num_seps = 0;
+ if (*p)
+ {
+ if (*p == '.')
+ throw ConfigException(std::string("The value of <") + tag + ":" + val + "> is not a valid hostname");
+ for (const char *ptr = p; *ptr; ++ptr)
+ {
+ switch (*ptr)
+ {
+ case ' ':
+ throw ConfigException(std::string("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(std::string("The value of <") + tag + ":" + val + "> is not a valid hostname");
+ }
+}
+
+bool ValidateNotEmpty(ServerConfig *, const char *tag, const char *value, ValueItem &data)
+{
+ if (data.GetValue().empty())
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> cannot be empty!");
+ return true;
+}
+
+bool ValidateNotZero(ServerConfig *, const char *tag, const char *value, ValueItem &data)
+{
+ if (!data.GetInteger())
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> must be non-zero!");
+ return true;
+}
+
+bool ValidateEmailReg(ServerConfig *, const char *tag, const char *value, ValueItem &data)
+{
+ if (Config.NSEmailReg)
+ {
+ if (std::string(value) == "preregexpire")
+ {
+ if (!data.GetInteger())
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> must be non-zero when e-mail registration are enabled!");
+ }
+ else
+ {
+ if (!data.GetBool())
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> must be set to yes when e-mail registrations are enabled!");
+ }
+ }
+ return true;
+}
+
+bool ValidatePort(ServerConfig *, const char *tag, const char *value, ValueItem &data)
+{
+ int port = data.GetInteger();
+ if (!port)
+ return true;
+ if (port < 1 || port > 65535)
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> is not a value port, it must be between 1 and 65535!");
+ return true;
+}
+
+bool ValidateLanguage(ServerConfig *, const char *, const char *, ValueItem &data)
+{
+ int language = data.GetInteger();
+ char maxlang[3];
+ snprintf(maxlang, 3, "%d", USED_LANGS);
+ if (language < 1 || language > USED_LANGS)
+ throw ConfigException(std::string("The value for <nickserv:defaultlanguage> must be between 1 and ") + maxlang + "!");
+ data.Set(--language);
+ return true;
+}
+
+bool ValidateGuestPrefix(ServerConfig *conf, const char *tag, const char *value, ValueItem &data)
+{
+ ValidateNotEmpty(conf, tag, value, data);
+ if (data.GetValue().size() > 21)
+ throw ConfigException("The value for <nickserv:guestnickprefix> cannot exceed 21 characters in length!");
+ return true;
+}
+
+bool ValidateBantype(ServerConfig *, const char *, const char *, 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;
+}
+
+bool ValidateBotServ(ServerConfig *, const char *tag, const char *value, ValueItem &data)
+{
+ if (Config.s_BotServ)
+ {
+ if (std::string(value) == "description")
+ {
+ if (data.GetValue().empty())
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> cannot be empty when BotServ is enabled!");
+ }
+ else if (std::string(value) == "minusers" || std::string(value) == "badwordsmax" || std::string(value) == "keepdata")
+ {
+ if (!data.GetInteger())
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> must be non-zero when BotServ is enabled!");
+ }
+ }
+ return true;
+}
+
+bool ValidateHostServ(ServerConfig *, const char *tag, const char *value, ValueItem &data)
+{
+ if (Config.s_HostServ)
+ {
+ if (std::string(value) == "description")
+ {
+ if (data.GetValue().empty())
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> cannot be empty when HostServ is enabled!");
+ }
+ }
+ return true;
+}
+
+bool ValidateLimitSessions(ServerConfig *, const char *tag, const char *value, ValueItem &data)
+{
+ if (Config.LimitSessions)
+ {
+ if (std::string(value) == "maxsessionlimit" || std::string(value) == "exceptionexpiry")
+ {
+ if (!data.GetInteger())
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> must be non-zero when session limiting is enabled!");
+ }
+ }
+ return true;
+}
+
+bool ValidateDefCon(ServerConfig *, const char *tag, const char *value, ValueItem &data)
+{
+ if (std::string(value) == "defaultlevel")
+ {
+ int level = data.GetInteger();
+ if (!level)
+ return true;
+ if (level > 5)
+ throw ConfigException("The value for <defcon:defaultlevel> must be between 1 through 5 if you wish to use DefCon or 0 if you wish to disable it!");
+ }
+ else if (Config.DefConLevel)
+ {
+ if ((std::string(value).substr(0, 5) == "level" && isdigit(value[5])) || std::string(value) == "chanmodes" || std::string(value) == "akillreason")
+ {
+ if (data.GetValue().empty())
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> cannot be empty when DefCon is enabled!");
+ }
+ else if (std::string(value) == "message" && Config.GlobalOnDefconMore)
+ {
+ if (data.GetValue().empty())
+ throw ConfigException("The value for <defcon:message> cannot be empty when globalondefconmore is enabled!");
+ }
+ else if (std::string(value) == "sessionlimit" || std::string(value) == "akillexpire")
+ {
+ if (!data.GetInteger())
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> must be non-zero when DefCon is enabled!");
+ }
+ }
+ return true;
+}
+
+bool ValidateNickLen(ServerConfig *, const char *, const char *, ValueItem &data)
+{
+ int nicklen = data.GetInteger();
+ if (!nicklen)
+ {
+ Alog() << "You have not defined the <networkinfo:nicklen> directive. It is strongly";
+ Alog() << "adviced that you do configure this correctly in your services.conf";
+ data.Set(31);
+ }
+ else if (nicklen < 1)
+ {
+ Alog() << "<networkinfo:nicklen> has an invalid value; setting to 31";
+ data.Set(31);
+ }
+ return true;
+}
+
+bool ValidateMail(ServerConfig *, const char *tag, const char *value, ValueItem &data)
+{
+ if (Config.UseMail)
+ {
+ if (std::string(value) == "sendmailpath" || std::string(value) == "sendfrom")
+ {
+ if (data.GetValue().empty())
+ throw ConfigException(std::string("The value for <") + tag + ":" + value + "> cannot be empty when e-mail is enabled!");
+ }
+ }
+ return true;
+}
+
+bool ValidateGlobalOnCycle(ServerConfig *, const char *tag, const char *value, ValueItem &data)
+{
+ if (Config.GlobalOnCycle)
+ {
+ if (data.GetValue().empty())
+ {
+ Alog() << "<" << tag << ":" << value << "> was undefined, disabling <options:globaloncycle>";
+ Config.GlobalOnCycle = false;
+ }
+ }
+ return true;
+}
+
+void ServerConfig::ReportConfigError(const std::string &errormessage, bool bail)
+{
+ Alog() << "There were errors in your configuration file: " << errormessage;
+ if (bail)
+ {
+ // TODO -- Need a way to stop loading in a safe way -- CyberBotX
+ //ServerInstance->Exit(EXIT_STATUS_CONFIG);
+ }
+}
+
+bool InitUplinks(ServerConfig *, const char *, bool bail)
+{
+ // If bail is false, we were reloading, don't clear anything
+ if (!bail)
+ return true;
+ if (!Config.Uplinks.empty())
+ {
+ std::list<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;
+}
+
+bool DoUplink(ServerConfig *conf, const char *, const char **, ValueList &values, int *, bool bail)
+{
+ // If bail is false, we were reloading, don't even try to add another uplink
+ if (!bail)
+ return true;
+ // Validation variables
+ const char *host = values[0].GetString(), *password = values[3].GetString();
+ 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(conf, "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(conf, "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(conf, "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 Uplink(host, port, password, ipv6));
+ return true;
+}
+
+bool DoneUplinks(ServerConfig *, const char *, bool bail)
+{
+ // If bail is false, we were reloading, ignore this check
+ if (!bail)
+ return true;
+ if (Config.Uplinks.empty())
+ throw ConfigException("You must define at least one uplink block!");
+ return true;
+}
+
+static bool InitOperTypes(ServerConfig *, const char *, bool)
+{
+ for (std::list<OperType *>::iterator it = Config.MyOperTypes.begin(); it != Config.MyOperTypes.end(); ++it)
+ delete *it;
+
+ Config.MyOperTypes.clear();
+ return true;
+}
+
+static bool DoOperType(ServerConfig *conf, const char *, const char **, ValueList &values, int *, bool)
+{
+ const char *name = values[0].GetString();
+ const char *inherits = values[1].GetString();
+ const char *commands = values[2].GetString();
+ const char *privs = values[3].GetString();
+
+ ValueItem vi(name);
+ if (!ValidateNotEmpty(conf, "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);
+
+ std::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))
+ {
+ /* Strip leading ' ' after , */
+ if (tok.size() > 1 && tok[0] == ' ')
+ tok.erase(tok.begin());
+ for (std::list<OperType *>::iterator it = Config.MyOperTypes.begin(); it != Config.MyOperTypes.end(); ++it)
+ {
+ if ((*it)->GetName() == tok)
+ {
+ Alog() << "Inheriting commands and privs from " << (*it)->GetName() << " to " << ot->GetName();
+ ot->Inherits(*it);
+ break;
+ }
+ }
+ }
+
+ Config.MyOperTypes.push_back(ot);
+ return true;
+}
+
+static bool DoneOperTypes(ServerConfig *, const char *, bool)
+{
+ return true;
+}
+
+/*************************************************************************/
+
+static bool InitOpers(ServerConfig *, const char *, bool)
+{
+ for (nickcore_map::const_iterator it = NickCoreList.begin(); it != NickCoreList.end(); ++it)
+ it->second->ot = NULL;
+
+ Config.Opers.clear();
+
+ return true;
+}
+
+static bool DoOper(ServerConfig *conf, const char *, const char **, ValueList &values, int *, bool)
+{
+ const char *name = values[0].GetString();
+ const char *type = values[1].GetString();
+
+ ValueItem vi(name);
+ if (!ValidateNotEmpty(conf, "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(conf, "oper", "type", vi2))
+ throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information.");
+
+ Config.Opers.push_back(std::make_pair(name, type));
+ return true;
+}
+
+static bool DoneOpers(ServerConfig *, const char *, bool)
+{
+ // XXX: this is duplicated in config.c
+ for (std::list<std::pair<std::string, std::string> >::iterator it = Config.Opers.begin(); it != Config.Opers.end(); ++it)
+ {
+ std::string nick = it->first, type = it->second;
+
+ NickAlias *na = findnick(nick);
+ if (!na)
+ // Nonexistant nick
+ continue;
+
+ if (!na->nc)
+ // Nick with no core (wtf?)
+ abort();
+
+ for (std::list<OperType *>::iterator tit = Config.MyOperTypes.begin(); tit != Config.MyOperTypes.end(); ++tit)
+ {
+ OperType *ot = *tit;
+ if (ot->GetName() == type)
+ {
+ Alog() << "Tied oper " << na->nc->display << " to type " << type;
+ na->nc->ot = ot;
+ }
+ }
+ }
+ return true;
+}
+
+/*************************************************************************/
+
+bool InitModules(ServerConfig *, const char *, bool)
+{
+ Modules.clear();
+ return true;
+}
+
+bool DoModule(ServerConfig *conf, const char *, const char **, ValueList &values, int *, bool)
+{
+ // First we validate that there was a name in the module block
+ const char *module = values[0].GetString();
+ 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.");
+ // If the string isn't empty, add a space before we add the module name
+ if (!Modules.empty())
+ Modules += " ";
+ // Add the module name to the string
+ Modules += values[0].GetString();
+ return true;
+}
+
+bool DoneModules(ServerConfig *, const char *, bool)
+{
+ return true;
+}
+
+int ServerConfig::Read(bool bail)
+{
+ errstr.clear();
+ // These tags MUST occur and must ONLY occur once in the config file
+ static const char *Once[] = {"serverinfo", "networkinfo", "options", "nickserv", "chanserv", "memoserv", "operserv", NULL};
+ // These tags can occur ONCE or not at all
+ InitialConfig Values[] = {
+ /* The following comments are from CyberBotX to w00t as examples to use:
+ *
+ * The last argument, for validation, must use one of the functions with the following signature:
+ * bool <function>(ServerConfig *, const char *, const char *, ValueItem &)
+ * Examples are: NoValidation, ValidateNotEmpty, etc.
+ *
+ * If you want to create a directive using an integer:
+ * int blarg;
+ * {"tag", "value", "0", new ValueContainerInt(&blarg), DT_INTEGER, <validation>},
+ *
+ * If you want to create a directive using an unsigned integer:
+ * unsigned blarg;
+ * {"tag", "value", "0", new ValueContainerUInt(&blarg), DT_UINTEGER, <validation>},
+ *
+ * If you want to create a directive using a character pointer without additional validation (see below for hostnames, fields with no spaces, and IP addresses):
+ * char *blarg;
+ * {"tag", "value", "", new ValueContainerChar(&blarg), DT_CHARPTR, <validation>},
+ *
+ * If you want to create a directive using a string:
+ * std::string blarg;
+ * {"tag", "value", "", new ValueContainerString(&blarg), DT_STRING, <validation>},
+ *
+ * If you want to create a directive using a boolean:
+ * bool blarg;
+ * {"tag", "value", "no", new ValueContainerBool(&blarg), DT_BOOLEAN, <validation>},
+ *
+ * If you want to create a directive using a character pointer specifically to hold a hostname (this will call ValidateHostname automatically):
+ * char *blarg;
+ * {"tag", "value", "", new ValueContainerChar(&blarg), DT_HOSTNAME, <validation>},
+ *
+ * If you want to create a directive using a character pointer that specifically can not have spaces in it (this will call ValidateNoSpaces automatically):
+ * char *blarg;
+ * {"tag", "value", "", new ValueContainerChar(&blarg), DT_NOSPACES, <validation>},
+ *
+ * If you want to create a directive using a character pointer specifically to hold an IP address (this will call ValidateIP automatically):
+ * char *blarg;
+ * {"tag", "value", "", new ValueContainerChar(&blarg), DT_IPADDRESS, <validation>},
+ *
+ * If you want to create a directive using a time (a time_t variable converted from a string):
+ * time_t blarg;
+ * {"tag", "value", "", new ValueContainterTime(&blarg), DT_TIME, <validation>},
+ *
+ * For the second-to-last argument, you can or (|) in the following values:
+ * DT_NORELOAD - The variable can't be changed on a reload of the configuration
+ * DT_ALLOW_WILD - Allows wildcards/CIDR in DT_IPADDRESS
+ * DT_ALLOW_NEWLINE - Allows new line characters in DT_CHARPTR and DT_STRING
+ *
+ * We may need to add some other validation functions to handle certain things, we can handle that later.
+ * Any questions about these, w00t, feel free to ask. */
+ {"serverinfo", "name", "", new ValueContainerChar(&Config.ServerName), DT_HOSTNAME | DT_NORELOAD, ValidateNotEmpty},
+ {"serverinfo", "description", "", new ValueContainerChar(&Config.ServerDesc), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"serverinfo", "localhost", "", new ValueContainerChar(&Config.LocalHost), DT_HOSTNAME | DT_NORELOAD, NoValidation},
+ {"serverinfo", "type", "", new ValueContainerChar(&Config.IRCDModule), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"serverinfo", "id", "", new ValueContainerChar(&Config.Numeric), DT_NOSPACES | DT_NORELOAD, NoValidation},
+ {"serverinfo", "ident", "", new ValueContainerChar(&Config.ServiceUser), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"serverinfo", "hostname", "", new ValueContainerChar(&Config.ServiceHost), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"serverinfo", "pid", "services.pid", new ValueContainerChar(&Config.PIDFilename), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"serverinfo", "motd", "services.motd", new ValueContainerChar(&Config.MOTDFilename), DT_CHARPTR, ValidateNotEmpty},
+ {"networkinfo", "helpchannel", "", new ValueContainerChar(&Config.HelpChannel), DT_CHARPTR, NoValidation},
+ {"networkinfo", "logchannel", "", new ValueContainerChar(&Config.LogChannel), DT_CHARPTR, NoValidation},
+ {"networkinfo", "logbot", "no", new ValueContainerBool(&Config.LogBot), DT_BOOLEAN, NoValidation},
+ {"networkinfo", "networkname", "", new ValueContainerChar(&Config.NetworkName), DT_CHARPTR, ValidateNotEmpty},
+ {"networkinfo", "nicklen", "0", new ValueContainerUInt(&Config.NickLen), DT_UINTEGER | DT_NORELOAD, ValidateNickLen},
+ {"networkinfo", "userlen", "10", new ValueContainerUInt(&Config.UserLen), DT_UINTEGER | DT_NORELOAD, NoValidation},
+ {"networkinfo", "hostlen", "64", new ValueContainerUInt(&Config.HostLen), DT_UINTEGER | DT_NORELOAD, NoValidation},
+ {"options", "encryption", "", new ValueContainerString(&EncModules), DT_STRING | DT_NORELOAD, ValidateNotEmpty},
+ {"options", "passlen", "32", new ValueContainerUInt(&Config.PassLen), DT_UINTEGER | DT_NORELOAD, NoValidation},
+ {"options", "database", "", new ValueContainerString(&DBModules), DT_STRING | DT_NORELOAD, ValidateNotEmpty},
+ {"options", "userkey1", "0", new ValueContainerLUInt(&Config.UserKey1), DT_LUINTEGER, NoValidation},
+ {"options", "userkey2", "0", new ValueContainerLUInt(&Config.UserKey2), DT_LUINTEGER, NoValidation},
+ {"options", "userkey3", "0", new ValueContainerLUInt(&Config.UserKey3), DT_LUINTEGER, NoValidation},
+ {"options", "nobackupokay", "no", new ValueContainerBool(&Config.NoBackupOkay), DT_BOOLEAN, NoValidation},
+ {"options", "strictpasswords", "no", new ValueContainerBool(&Config.StrictPasswords), DT_BOOLEAN, NoValidation},
+ {"options", "badpasslimit", "0", new ValueContainerUInt(&Config.BadPassLimit), DT_UINTEGER, NoValidation},
+ {"options", "badpasstimeout", "0", new ValueContainerTime(&Config.BadPassTimeout), DT_TIME, NoValidation},
+ {"options", "updatetimeout", "0", new ValueContainerTime(&Config.UpdateTimeout), DT_TIME, ValidateNotZero},
+ {"options", "expiretimeout", "0", new ValueContainerTime(&Config.ExpireTimeout), DT_TIME, ValidateNotZero},
+ {"options", "readtimeout", "0", new ValueContainerTime(&Config.ReadTimeout), DT_TIME, ValidateNotZero},
+ {"options", "warningtimeout", "0", new ValueContainerTime(&Config.WarningTimeout), DT_TIME, ValidateNotZero},
+ {"options", "timeoutcheck", "0", new ValueContainerTime(&Config.TimeoutCheck), DT_TIME, NoValidation},
+ {"options", "keeplogs", "0", new ValueContainerInt(&Config.KeepLogs), DT_INTEGER, NoValidation},
+ {"options", "keepbackups", "0", new ValueContainerInt(&Config.KeepBackups), DT_INTEGER, NoValidation},
+ {"options", "forceforbidreason", "no", new ValueContainerBool(&Config.ForceForbidReason), DT_BOOLEAN, NoValidation},
+ {"options", "useprivmsg", "no", new ValueContainerBool(&Config.UsePrivmsg), DT_BOOLEAN, NoValidation},
+ {"options", "usestrictprivmsg", "no", new ValueContainerBool(&Config.UseStrictPrivMsg), DT_BOOLEAN, NoValidation},
+ {"options", "dumpcore", "yes", new ValueContainerBool(&Config.DumpCore), DT_BOOLEAN | DT_NORELOAD, NoValidation},
+ {"options", "logusers", "no", new ValueContainerBool(&Config.LogUsers), DT_BOOLEAN, NoValidation},
+ {"options", "hidestatso", "no", new ValueContainerBool(&Config.HideStatsO), DT_BOOLEAN, NoValidation},
+ {"options", "globaloncycle", "no", new ValueContainerBool(&Config.GlobalOnCycle), DT_BOOLEAN, NoValidation},
+ {"options", "globaloncycledown", "", new ValueContainerChar(&Config.GlobalOnCycleMessage), DT_CHARPTR, ValidateGlobalOnCycle},
+ {"options", "globaloncycleup", "", new ValueContainerChar(&Config.GlobalOnCycleUP), DT_CHARPTR, ValidateGlobalOnCycle},
+ {"options", "anonymousglobal", "no", new ValueContainerBool(&Config.AnonymousGlobal), DT_BOOLEAN, NoValidation},
+ {"options", "nickregdelay", "0", new ValueContainerUInt(&Config.NickRegDelay), DT_UINTEGER, NoValidation},
+ {"options", "restrictopernicks", "no", new ValueContainerBool(&Config.RestrictOperNicks), DT_BOOLEAN, NoValidation},
+ {"options", "newscount", "3", new ValueContainerUInt(&Config.NewsCount), DT_UINTEGER, NoValidation},
+ {"options", "ulineservers", "", new ValueContainerChar(&UlineServers), DT_CHARPTR, NoValidation},
+ {"options", "enablelogchannel", "no", new ValueContainerBool(&LogChan), DT_BOOLEAN, NoValidation},
+ {"options", "mlock", "+nrt", new ValueContainerString(&Config.MLock), DT_STRING, NoValidation},
+ {"options", "botmodes", "", new ValueContainerString(&Config.BotModes), DT_STRING, NoValidation},
+ {"options", "maxretries", "10", new ValueContainerUInt(&Config.MaxRetries), DT_UINTEGER, NoValidation},
+ {"options", "retrywait", "60", new ValueContainerInt(&Config.RetryWait), DT_INTEGER, ValidateNotZero},
+ {"nickserv", "nick", "NickServ", new ValueContainerChar(&Config.s_NickServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"nickserv", "description", "Nickname Registration Service", new ValueContainerChar(&Config.desc_NickServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"nickserv", "emailregistration", "no", new ValueContainerBool(&Config.NSEmailReg), DT_BOOLEAN, NoValidation},
+ {"nickserv", "modules", "", new ValueContainerString(&NickCoreModules), DT_STRING, NoValidation},
+ {"nickserv", "forceemail", "no", new ValueContainerBool(&Config.NSForceEmail), DT_BOOLEAN, ValidateEmailReg},
+ {"nickserv", "defaults", "secure memosignon memoreceive", new ValueContainerString(&NSDefaults), DT_STRING, NoValidation},
+ {"nickserv", "defaultlanguage", "0", new ValueContainerUInt(&Config.NSDefLanguage), DT_UINTEGER, ValidateLanguage},
+ {"nickserv", "regdelay", "0", new ValueContainerTime(&Config.NSRegDelay), DT_TIME, NoValidation},
+ {"nickserv", "resenddelay", "0", new ValueContainerTime(&Config.NSResendDelay), DT_TIME, NoValidation},
+ {"nickserv", "expire", "21d", new ValueContainerTime(&Config.NSExpire), DT_TIME, NoValidation},
+ {"nickserv", "preregexpire", "0", new ValueContainerTime(&Config.NSRExpire), DT_TIME, ValidateEmailReg},
+ {"nickserv", "maxaliases", "0", new ValueContainerInt(&Config.NSMaxAliases), DT_INTEGER, NoValidation},
+ {"nickserv", "accessmax", "0", new ValueContainerUInt(&Config.NSAccessMax), DT_UINTEGER, ValidateNotZero},
+ {"nickserv", "enforceruser", "", new ValueContainerChar(&temp_nsuserhost), DT_CHARPTR, ValidateNotEmpty},
+ {"nickserv", "releasetimeout", "0", new ValueContainerTime(&Config.NSReleaseTimeout), DT_TIME, ValidateNotZero},
+ {"nickserv", "allowkillimmed", "no", new ValueContainerBool(&Config.NSAllowKillImmed), DT_BOOLEAN | DT_NORELOAD, NoValidation},
+ {"nickserv", "nogroupchange", "no", new ValueContainerBool(&Config.NSNoGroupChange), DT_BOOLEAN, NoValidation},
+ {"nickserv", "listopersonly", "no", new ValueContainerBool(&Config.NSListOpersOnly), DT_BOOLEAN, NoValidation},
+ {"nickserv", "listmax", "0", new ValueContainerUInt(&Config.NSListMax), DT_UINTEGER, ValidateNotZero},
+ {"nickserv", "guestnickprefix", "", new ValueContainerChar(&Config.NSGuestNickPrefix), DT_CHARPTR, ValidateGuestPrefix},
+ {"nickserv", "secureadmins", "no", new ValueContainerBool(&Config.NSSecureAdmins), DT_BOOLEAN, NoValidation},
+ {"nickserv", "strictprivileges", "no", new ValueContainerBool(&Config.NSStrictPrivileges), DT_BOOLEAN, NoValidation},
+ {"nickserv", "modeonid", "no", new ValueContainerBool(&Config.NSModeOnID), DT_BOOLEAN, NoValidation},
+ {"nickserv", "addaccessonreg", "no", new ValueContainerBool(&Config.NSAddAccessOnReg), DT_BOOLEAN, NoValidation},
+ {"mail", "usemail", "no", new ValueContainerBool(&Config.UseMail), DT_BOOLEAN, ValidateEmailReg},
+ {"mail", "sendmailpath", "", new ValueContainerChar(&Config.SendMailPath), DT_CHARPTR, ValidateMail},
+ {"mail", "sendfrom", "", new ValueContainerChar(&Config.SendFrom), DT_CHARPTR, ValidateMail},
+ {"mail", "restrict", "no", new ValueContainerBool(&Config.RestrictMail), DT_BOOLEAN, NoValidation},
+ {"mail", "delay", "0", new ValueContainerTime(&Config.MailDelay), DT_TIME, NoValidation},
+ {"mail", "dontquoteaddresses", "no", new ValueContainerBool(&Config.DontQuoteAddresses), DT_BOOLEAN, NoValidation},
+ {"chanserv", "nick", "ChanServ", new ValueContainerChar(&Config.s_ChanServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"chanserv", "description", "Channel Registration Service", new ValueContainerChar(&Config.desc_ChanServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"chanserv", "modules", "", new ValueContainerString(&ChanCoreModules), DT_STRING, NoValidation},
+ {"chanserv", "defaults", "keeptopic secure securefounder signkick", new ValueContainerString(&CSDefaults), DT_STRING, NoValidation},
+ {"chanserv", "maxregistered", "0", new ValueContainerUInt(&Config.CSMaxReg), DT_UINTEGER, NoValidation},
+ {"chanserv", "expire", "14d", new ValueContainerTime(&Config.CSExpire), DT_TIME, NoValidation},
+ {"chanserv", "defbantype", "2", new ValueContainerInt(&Config.CSDefBantype), DT_INTEGER, ValidateBantype},
+ {"chanserv", "accessmax", "0", new ValueContainerUInt(&Config.CSAccessMax), DT_UINTEGER, ValidateNotZero},
+ {"chanserv", "autokickmax", "0", new ValueContainerUInt(&Config.CSAutokickMax), DT_UINTEGER, ValidateNotZero},
+ {"chanserv", "autokickreason", "User has been banned from the channel", new ValueContainerChar(&Config.CSAutokickReason), DT_CHARPTR, ValidateNotEmpty},
+ {"chanserv", "inhabit", "0", new ValueContainerTime(&Config.CSInhabit), DT_TIME, ValidateNotZero},
+ {"chanserv", "listopersonly", "no", new ValueContainerBool(&Config.CSListOpersOnly), DT_BOOLEAN, NoValidation},
+ {"chanserv", "listmax", "0", new ValueContainerUInt(&Config.CSListMax), DT_UINTEGER, ValidateNotZero},
+ {"chanserv", "opersonly", "no", new ValueContainerBool(&Config.CSOpersOnly), DT_BOOLEAN, NoValidation},
+ {"memoserv", "nick", "MemoServ", new ValueContainerChar(&Config.s_MemoServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"memoserv", "description", "Memo Service", new ValueContainerChar(&Config.desc_MemoServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"memoserv", "modules", "", new ValueContainerString(&MemoCoreModules), DT_STRING, NoValidation},
+ {"memoserv", "maxmemos", "0", new ValueContainerUInt(&Config.MSMaxMemos), DT_UINTEGER, NoValidation},
+ {"memoserv", "senddelay", "0", new ValueContainerTime(&Config.MSSendDelay), DT_TIME, NoValidation},
+ {"memoserv", "notifyall", "no", new ValueContainerBool(&Config.MSNotifyAll), DT_BOOLEAN, NoValidation},
+ {"memoserv", "memoreceipt", "0", new ValueContainerUInt(&Config.MSMemoReceipt), DT_UINTEGER, NoValidation},
+ {"botserv", "nick", "", new ValueContainerChar(&Config.s_BotServ), DT_CHARPTR | DT_NORELOAD, NoValidation},
+ {"botserv", "description", "Bot Service", new ValueContainerChar(&Config.desc_BotServ), DT_CHARPTR | DT_NORELOAD, ValidateBotServ},
+ {"botserv", "modules", "", new ValueContainerString(&BotCoreModules), DT_STRING, NoValidation},
+ {"botserv", "defaults", "", new ValueContainerString(&BSDefaults), DT_STRING, NoValidation},
+ {"botserv", "minusers", "0", new ValueContainerUInt(&Config.BSMinUsers), DT_UINTEGER, ValidateBotServ},
+ {"botserv", "badwordsmax", "0", new ValueContainerUInt(&Config.BSBadWordsMax), DT_UINTEGER, ValidateBotServ},
+ {"botserv", "keepdata", "0", new ValueContainerTime(&Config.BSKeepData), DT_TIME, ValidateBotServ},
+ {"botserv", "smartjoin", "no", new ValueContainerBool(&Config.BSSmartJoin), DT_BOOLEAN, NoValidation},
+ {"botserv", "gentlebadwordreason", "no", new ValueContainerBool(&Config.BSGentleBWReason), DT_BOOLEAN, NoValidation},
+ {"botserv", "casesensitive", "no", new ValueContainerBool(&Config.BSCaseSensitive), DT_BOOLEAN, NoValidation},
+ {"botserv", "fantasycharacter", "!", new ValueContainerChar(&Config.BSFantasyCharacter), DT_CHARPTR, NoValidation},
+ {"hostserv", "nick", "", new ValueContainerChar(&Config.s_HostServ), DT_CHARPTR | DT_NORELOAD, NoValidation},
+ {"hostserv", "description", "vHost Service", new ValueContainerChar(&Config.desc_HostServ), DT_CHARPTR | DT_NORELOAD, ValidateHostServ},
+ {"hostserv", "modules", "", new ValueContainerString(&HostCoreModules), DT_STRING, NoValidation},
+ {"operserv", "nick", "OperServ", new ValueContainerChar(&Config.s_OperServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"operserv", "description", "Operator Service", new ValueContainerChar(&Config.desc_OperServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"operserv", "globalnick", "Global", new ValueContainerChar(&Config.s_GlobalNoticer), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"operserv", "globaldescription", "Global Noticer", new ValueContainerChar(&Config.desc_GlobalNoticer), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
+ {"operserv", "modules", "", new ValueContainerString(&OperCoreModules), DT_STRING, NoValidation},
+ {"operserv", "superadmin", "no", new ValueContainerBool(&Config.SuperAdmin), DT_BOOLEAN, NoValidation},
+ {"operserv", "logmaxusers", "no", new ValueContainerBool(&Config.LogMaxUsers), DT_BOOLEAN, NoValidation},
+ {"operserv", "autokillexpiry", "0", new ValueContainerTime(&Config.AutokillExpiry), DT_TIME, ValidateNotZero},
+ {"operserv", "chankillexpiry", "0", new ValueContainerTime(&Config.ChankillExpiry), DT_TIME, ValidateNotZero},
+ {"operserv", "snlineexpiry", "0", new ValueContainerTime(&Config.SNLineExpiry), DT_TIME, ValidateNotZero},
+ {"operserv", "sqlineexpiry", "0", new ValueContainerTime(&Config.SQLineExpiry), DT_TIME, ValidateNotZero},
+ {"operserv", "szlineexpiry", "0", new ValueContainerTime(&Config.SZLineExpiry), DT_TIME, ValidateNotZero},
+ {"operserv", "akillonadd", "no", new ValueContainerBool(&Config.AkillOnAdd), DT_BOOLEAN, NoValidation},
+ {"operserv", "killonsnline", "no", new ValueContainerBool(&Config.KillonSNline), DT_BOOLEAN, NoValidation},
+ {"operserv", "killonsqline", "no", new ValueContainerBool(&Config.KillonSQline), DT_BOOLEAN, NoValidation},
+ {"operserv", "notifications", "", new ValueContainerString(&OSNotifications), DT_STRING, NoValidation},
+ {"operserv", "limitsessions", "no", new ValueContainerBool(&Config.LimitSessions), DT_BOOLEAN, NoValidation},
+ {"operserv", "defaultsessionlimit", "0", new ValueContainerUInt(&Config.DefSessionLimit), DT_UINTEGER, NoValidation},
+ {"operserv", "maxsessionlimit", "0", new ValueContainerUInt(&Config.MaxSessionLimit), DT_UINTEGER, ValidateLimitSessions},
+ {"operserv", "exceptionexpiry", "0", new ValueContainerTime(&Config.ExceptionExpiry), DT_TIME, ValidateLimitSessions},
+ {"operserv", "sessionlimitexceeded", "", new ValueContainerChar(&Config.SessionLimitExceeded), DT_CHARPTR, NoValidation},
+ {"operserv", "sessionlimitdetailsloc", "", new ValueContainerChar(&Config.SessionLimitDetailsLoc), DT_CHARPTR, NoValidation},
+ {"operserv", "maxsessionkill", "0", new ValueContainerInt(&Config.MaxSessionKill), DT_INTEGER, NoValidation},
+ {"operserv", "sessionautokillexpiry", "0", new ValueContainerTime(&Config.SessionAutoKillExpiry), DT_TIME, NoValidation},
+ {"operserv", "addakiller", "no", new ValueContainerBool(&Config.AddAkiller), DT_BOOLEAN, NoValidation},
+ {"operserv", "opersonly", "no", new ValueContainerBool(&Config.OSOpersOnly), DT_BOOLEAN, NoValidation},
+ {"defcon", "defaultlevel", "0", new ValueContainerInt(&DefConLevel), DT_INTEGER, ValidateDefCon},
+ {"defcon", "level4", "", new ValueContainerString(&DefCon4), DT_STRING, ValidateDefCon},
+ {"defcon", "level3", "", new ValueContainerString(&DefCon3), DT_STRING, ValidateDefCon},
+ {"defcon", "level2", "", new ValueContainerString(&DefCon2), DT_STRING, ValidateDefCon},
+ {"defcon", "level1", "", new ValueContainerString(&DefCon1), DT_STRING, ValidateDefCon},
+ {"defcon", "sessionlimit", "0", new ValueContainerInt(&Config.DefConSessionLimit), DT_INTEGER, ValidateDefCon},
+ {"defcon", "akillexpire", "0", new ValueContainerTime(&Config.DefConAKILL), DT_TIME, ValidateDefCon},
+ {"defcon", "chanmodes", "", new ValueContainerChar(&Config.DefConChanModes), DT_CHARPTR, ValidateDefCon},
+ {"defcon", "timeout", "0", new ValueContainerTime(&Config.DefConTimeOut), DT_TIME, NoValidation},
+ {"defcon", "globalondefcon", "no", new ValueContainerBool(&Config.GlobalOnDefcon), DT_BOOLEAN, NoValidation},
+ {"defcon", "globalondefconmore", "no", new ValueContainerBool(&Config.GlobalOnDefconMore), DT_BOOLEAN, NoValidation},
+ {"defcon", "message", "", new ValueContainerChar(&Config.DefconMessage), DT_CHARPTR, ValidateDefCon},
+ {"defcon", "offmessage", "", new ValueContainerChar(&Config.DefConOffMessage), DT_CHARPTR, NoValidation},
+ {"defcon", "akillreason", "", new ValueContainerChar(&Config.DefConAkillReason), DT_CHARPTR, ValidateDefCon},
+ {NULL, NULL, NULL, NULL, DT_NOTHING, NoValidation}
+ };
+
+ /* These tags can occur multiple times, and therefore they have special code to read them
+ * which is different to the code for reading the singular tags listed above. */
+ MultiConfig MultiValues[] = {
+ {"uplink",
+ {"host", "ipv6", "port", "password", NULL},
+ {"", "no", "0", "", NULL},
+ {DT_HOSTNAME | DT_NORELOAD, DT_BOOLEAN | DT_NORELOAD, DT_UINTEGER | DT_NORELOAD, DT_NOSPACES | DT_NORELOAD},
+ InitUplinks, DoUplink, DoneUplinks},
+ {"module