diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/config-manager.cpp | 130 |
1 files changed, 74 insertions, 56 deletions
diff --git a/common/config-manager.cpp b/common/config-manager.cpp index 4b1604bcd7..1dfd546e41 100644 --- a/common/config-manager.cpp +++ b/common/config-manager.cpp @@ -41,14 +41,14 @@ #define MAXLINELEN 256 static char *ltrim(char *t) { - while (*t == ' ') + while (isspace(*t)) t++; return t; } static char *rtrim(char *t) { int l = strlen(t) - 1; - while (l >= 0 && t[l] == ' ') + while (l >= 0 && isspace(t[l])) t[l--] = 0; return t; } @@ -109,60 +109,71 @@ void ConfigManager::switchFile(const String &filename) { void ConfigManager::loadFile(const String &filename) { FILE *cfg_file; - char buf[MAXLINELEN]; - char *t; - String domain; if (!(cfg_file = fopen(filename.c_str(), "r"))) { - debug(1, "Unable to open configuration file: %s", filename.c_str()); + warning("Unable to open configuration file: %s", filename.c_str()); } else { + char buf[MAXLINELEN]; + String domain; + int lineno = 0; + while (!feof(cfg_file)) { - t = buf; - if (!fgets(t, MAXLINELEN, cfg_file)) + lineno++; + if (!fgets(buf, MAXLINELEN, cfg_file)) continue; - if (t[0] && t[0] != '#') { - if (t[0] == '[') { - // It's a new domain which begins here. - char *p = strchr(t, ']'); - if (!p) { - error("Config file buggy: no ] at the end of the domain name.\n"); - } else { - *p = 0; - // TODO: Some kind of domain name verification might be nice. - // E.g. restrict to only a-zA-Z0-9 and maybe -_ or so... - domain = t + 1; - } + if (!buf[0] || buf[0] == '#') { + // Skip empty lines and comments + // TODO: Comments should be preserved here! + } else if (buf[0] == '[') { + // It's a new domain which begins here. + char *p = buf + 1; + // Get the domain name, and check whether it's valid (that + // is, verify that it only consists of alphanumerics, + // dashes and underscores). + while (*p && (isalnum(*p) || *p == '-' || *p == '_')) + p++; + + switch (*p) { + case '\0': + error("Config file buggy: missing ] in line %d", lineno); + break; + case ']': + *p = 0; + domain = buf + 1; + break; + default: + error("Config file buggy: Invalid character '%c' occured in domain name in line %d", *p, lineno); + } + } else { + // Skip leading whitespaces + char *t = ltrim(buf); + + // Skip empty lines + if (*t == 0) + continue; + + // If no domain has been set, this config file is invalid! + if (domain.isEmpty()) { + error("Config file buggy: Key/value pair found outside a domain in line %d", lineno); + } + + // It's a new key in the domain. + char *p = strchr(t, '\n'); + if (p) + *p = 0; + p = strchr(t, '\r'); + if (p) + *p = 0; + + // Split string at '=' into 'key' and 'value'. + p = strchr(t, '='); + if (!p) { + error("Config file buggy: Junk found in line line %d: '%s'", lineno, t); } else { - // Skip leading whitespaces - while (*t && isspace(*t)) { - t++; - } - // Skip empty lines - if (*t == 0) - continue; - - // If no domain has been set, this config file is invalid! - if (domain.isEmpty()) { - error("Config file buggy: we have a key without a domain first.\n"); - } - - // It's a new key in the domain. - char *p = strchr(t, '\n'); - if (p) - *p = 0; - p = strchr(t, '\r'); - if (p) - *p = 0; - - if (!(p = strchr(t, '='))) { - if (strlen(t)) - warning("Config file buggy: there is junk: %s", t); - } else { - *p = 0; - String key = ltrim(rtrim(t)); - String value = ltrim(p + 1); - set(key, value, domain); - } + *p = 0; + String key = rtrim(t); + String value = rtrim(ltrim(p + 1)); + set(key, value, domain); } } } @@ -293,16 +304,23 @@ const String & ConfigManager::get(const String &key, const String &domain) const int ConfigManager::getInt(const String &key, const String &dom) const { String value(get(key, dom)); - // Convert the string to an integer. - // TODO: We should perform some error checking. - return (int)strtol(value.c_str(), 0, 10); + char *errpos; + int ivalue = (int)strtol(value.c_str(), &errpos, 10); + if (value.c_str() == errpos) + error("Config file buggy: '%s' is not a valid integer", errpos); + + return ivalue; } bool ConfigManager::getBool(const String &key, const String &dom) const { String value(get(key, dom)); - // '1', 'true' and 'yes' are accepted as true values; everything else - // maps to value 'false'. - return (value == trueStr) || (value == "yes") || (value == "1"); + + if ((value == trueStr) || (value == "yes") || (value == "1")) + return true; + if ((value == falseStr) || (value == "no") || (value == "0")) + return false; + + error("Config file buggy: '%s' is not a valid bool", value.c_str()); } |