X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fconfigparser.cpp;h=8250530443c7b38c96aadd93336c21929f8910a5;hb=97a1d642;hp=3be1ac9c53d39ce44f0a79dcd6d81defa55735f9;hpb=7010a92426d2c3ab0cea5ba0d36a04bc6b52349f;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/configparser.cpp b/src/configparser.cpp index 3be1ac9c5..825053044 100644 --- a/src/configparser.cpp +++ b/src/configparser.cpp @@ -91,7 +91,7 @@ struct Parser unget(ch); } - bool kv(std::vector* items, std::set& seen) + bool kv(ConfigItems* items) { std::string key; nextword(key); @@ -173,14 +173,14 @@ struct Parser } else if (ch == '"') break; - else + else if (ch != '\r') value.push_back(ch); } - if (!seen.insert(key).second) + if (items->find(key) != items->end()) throw CoreException("Duplicate key '" + key + "' found"); - items->push_back(KeyVal(key, value)); + (*items)[key] = value; return true; } @@ -199,11 +199,10 @@ struct Parser if (name.empty()) throw CoreException("Empty tag name"); - std::vector* items; - std::set seen; + ConfigItems* items; tag = ConfigTag::create(name, current.filename, current.line, items); - while (kv(items, seen)) + while (kv(items)) { // Do nothing here (silences a GCC warning). } @@ -214,25 +213,25 @@ struct Parser mandatory_tag.clear(); } - if (name == "include") + if (stdalgo::string::equalsci(name, "include")) { stack.DoInclude(tag, flags); } - else if (name == "files") + else if (stdalgo::string::equalsci(name, "files")) { - for(std::vector::iterator i = items->begin(); i != items->end(); i++) + for(ConfigItems::iterator i = items->begin(); i != items->end(); i++) { stack.DoReadFile(i->first, i->second, flags, false); } } - else if (name == "execfiles") + else if (stdalgo::string::equalsci(name, "execfiles")) { - for(std::vector::iterator i = items->begin(); i != items->end(); i++) + for(ConfigItems::iterator i = items->begin(); i != items->end(); i++) { stack.DoReadFile(i->first, i->second, flags, true); } } - else if (name == "define") + else if (stdalgo::string::equalsci(name, "define")) { if (flags & FLAG_USE_COMPAT) throw CoreException(" tags may only be used in XML-style config (add )"); @@ -242,12 +241,12 @@ struct Parser throw CoreException("Variable definition must include variable name"); stack.vars[varname] = value; } - else if (name == "config") + else if (stdalgo::string::equalsci(name, "config")) { std::string format = tag->getString("format"); - if (format == "xml") + if (stdalgo::string::equalsci(format, "xml")) flags &= ~FLAG_USE_COMPAT; - else if (format == "compat") + else if (stdalgo::string::equalsci(format, "compat")) flags |= FLAG_USE_COMPAT; else if (!format.empty()) throw CoreException("Unknown configuration format " + format); @@ -385,7 +384,7 @@ bool ParseStack::ParseFile(const std::string& path, int flags, const std::string bool ConfigTag::readString(const std::string& key, std::string& value, bool allow_lf) { - for(std::vector::iterator j = items.begin(); j != items.end(); ++j) + for(ConfigItems::iterator j = items.begin(); j != items.end(); ++j) { if(j->first != key) continue; @@ -403,13 +402,98 @@ bool ConfigTag::readString(const std::string& key, std::string& value, bool allo return false; } -std::string ConfigTag::getString(const std::string& key, const std::string& def) +std::string ConfigTag::getString(const std::string& key, const std::string& def, const TR1NS::function& validator) { - std::string res = def; - readString(key, res); + std::string res; + if (!readString(key, res)) + return def; + + if (!validator(res)) + { + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "WARNING: The value of <%s:%s> is not valid; value set to %s.", + tag.c_str(), key.c_str(), def.c_str()); + return def; + } + return res; +} + +std::string ConfigTag::getString(const std::string& key, const std::string& def, size_t minlen, size_t maxlen) +{ + std::string res; + if (!readString(key, res)) + return def; + + if (res.length() < minlen || res.length() > maxlen) + { + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "WARNING: The length of <%s:%s> is not between %ld and %ld; value set to %s.", + tag.c_str(), key.c_str(), minlen, maxlen, def.c_str()); + return def; + } return res; } +namespace +{ + /** Check for an invalid magnitude specifier. If one is found a warning is logged and the + * value is corrected (set to \p def). + * @param tag The tag name; used in the warning message. + * @param key The key name; used in the warning message. + * @param val The full value set in the config as a string. + * @param num The value to verify and modify if needed. + * @param def The default value, \p res will be set to this if \p tail does not contain a. + * valid magnitude specifier. + * @param tail The location in the config value at which the magnifier is located. + */ + template + void CheckMagnitude(const std::string& tag, const std::string& key, const std::string& val, Numeric& num, Numeric def, const char* tail) + { + // If this is NULL then no magnitude specifier was given. + if (!*tail) + return; + + switch (toupper(*tail)) + { + case 'K': + num *= 1024; + return; + + case 'M': + num *= 1024 * 1024; + return; + + case 'G': + num *= 1024 * 1024 * 1024; + return; + } + + const std::string message = "WARNING: <" + tag + ":" + key + "> value of " + val + " contains an invalid magnitude specifier '" + + tail + "'; value set to " + ConvToStr(def) + "."; + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, message); + num = def; + } + + /** Check for an out of range value. If the value falls outside the boundaries a warning is + * logged and the value is corrected (set to \p def). + * @param tag The tag name; used in the warning message. + * @param key The key name; used in the warning message. + * @param num The value to verify and modify if needed. + * @param def The default value, \p res will be set to this if (min <= res <= max) doesn't hold true. + * @param min Minimum accepted value for \p res. + * @param max Maximum accepted value for \p res. + */ + template + void CheckRange(const std::string& tag, const std::string& key, Numeric& num, Numeric def, Numeric min, Numeric max) + { + if (num >= min && num <= max) + return; + + const std::string message = "WARNING: <" + tag + ":" + key + "> value of " + ConvToStr(num) + " is not between " + + ConvToStr(min) + " and " + ConvToStr(max) + "; value set to " + ConvToStr(def) + "."; + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, message); + num = def; + } +} + long ConfigTag::getInt(const std::string &key, long def, long min, long max) { std::string result; @@ -421,50 +505,49 @@ long ConfigTag::getInt(const std::string &key, long def, long min, long max) long res = strtol(res_cstr, &res_tail, 0); if (res_tail == res_cstr) return def; - switch (toupper(*res_tail)) - { - case 'K': - res = res * 1024; - break; - case 'M': - res = res * 1024 * 1024; - break; - case 'G': - res = res * 1024 * 1024 * 1024; - break; - } - CheckRange(key, res, def, min, max); + CheckMagnitude(tag, key, result, res, def, res_tail); + CheckRange(tag, key, res, def, min, max); return res; } -void ConfigTag::CheckRange(const std::string& key, long& res, long def, long min, long max) +unsigned long ConfigTag::getUInt(const std::string& key, unsigned long def, unsigned long min, unsigned long max) { - if (res < min || res > max) - { - ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "WARNING: <%s:%s> value of %ld is not between %ld and %ld; set to %ld.", - tag.c_str(), key.c_str(), res, min, max, def); - res = def; - } + std::string result; + if (!readString(key, result)) + return def; + + const char* res_cstr = result.c_str(); + char* res_tail = NULL; + unsigned long res = strtoul(res_cstr, &res_tail, 0); + if (res_tail == res_cstr) + return def; + + CheckMagnitude(tag, key, result, res, def, res_tail); + CheckRange(tag, key, res, def, min, max); + return res; } -long ConfigTag::getDuration(const std::string& key, long def, long min, long max) +unsigned long ConfigTag::getDuration(const std::string& key, unsigned long def, unsigned long min, unsigned long max) { std::string duration; if (!readString(key, duration)) return def; - long ret = InspIRCd::Duration(duration); - CheckRange(key, ret, def, min, max); + unsigned long ret = InspIRCd::Duration(duration); + CheckRange(tag, key, ret, def, min, max); return ret; } -double ConfigTag::getFloat(const std::string &key, double def) +double ConfigTag::getFloat(const std::string& key, double def, double min, double max) { std::string result; if (!readString(key, result)) return def; - return strtod(result.c_str(), NULL); + + double res = strtod(result.c_str(), NULL); + CheckRange(tag, key, res, def, min, max); + return res; } bool ConfigTag::getBool(const std::string &key, bool def) @@ -488,7 +571,7 @@ std::string ConfigTag::getTagLocation() return src_name + ":" + ConvToStr(src_line); } -ConfigTag* ConfigTag::create(const std::string& Tag, const std::string& file, int line, std::vector*& Items) +ConfigTag* ConfigTag::create(const std::string& Tag, const std::string& file, int line, ConfigItems*& Items) { ConfigTag* rv = new ConfigTag(Tag, file, line); Items = &rv->items; @@ -500,6 +583,11 @@ ConfigTag::ConfigTag(const std::string& Tag, const std::string& file, int line) { } +OperInfo::OperInfo(const std::string& Name) + : name(Name) +{ +} + std::string OperInfo::getConfig(const std::string& key) { std::string rv;