X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fconfigparser.cpp;h=d3723d35036a790d4d360babb6611d3f469e081c;hb=e950f568d0f571e9475aa38177486468714de4d3;hp=056ed54a4b3e5fb019d88122f1359c4fee06e448;hpb=44f42a13de52c8025942ddab42f51feb36821782;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/configparser.cpp b/src/configparser.cpp index 056ed54a4..d3723d350 100644 --- a/src/configparser.cpp +++ b/src/configparser.cpp @@ -30,9 +30,10 @@ struct Parser fpos last_tag; reference tag; int ungot; + std::string mandatory_tag; - Parser(ParseStack& me, int myflags, FILE* conf, const std::string& name) - : stack(me), flags(myflags), file(conf), current(name), last_tag(name), ungot(-1) + Parser(ParseStack& me, int myflags, FILE* conf, const std::string& name, const std::string& mandatorytag) + : stack(me), flags(myflags), file(conf), current(name), last_tag(name), ungot(-1), mandatory_tag(mandatorytag) { } int next(bool eof_ok = false) @@ -118,7 +119,7 @@ struct Parser while (1) { ch = next(); - if (ch == '&' && (flags & FLAG_USE_XML)) + if (ch == '&' && !(flags & FLAG_USE_COMPAT)) { std::string varname; while (1) @@ -140,7 +141,7 @@ struct Parser throw CoreException("Undefined XML entity reference '&" + varname + ";'"); value.append(var->second); } - else if (ch == '\\' && !(flags & FLAG_USE_XML)) + else if (ch == '\\' && (flags & FLAG_USE_COMPAT)) { int esc = next(); if (esc == 'n') @@ -182,7 +183,16 @@ struct Parser std::set seen; tag = ConfigTag::create(name, current.filename, current.line, items); - while (kv(items, seen)); + while (kv(items, seen)) + { + // Do nothing here (silences a GCC warning). + } + + if (name == mandatory_tag) + { + // Found the mandatory tag + mandatory_tag.clear(); + } if (name == "include") { @@ -204,7 +214,7 @@ struct Parser } else if (name == "define") { - if (!(flags & FLAG_USE_XML)) + if (flags & FLAG_USE_COMPAT) throw CoreException(" tags may only be used in XML-style config (add )"); std::string varname = tag->getString("name"); std::string value = tag->getString("value"); @@ -216,9 +226,9 @@ struct Parser { std::string format = tag->getString("format"); if (format == "xml") - flags |= FLAG_USE_XML; + flags &= ~FLAG_USE_COMPAT; else if (format == "compat") - flags &= ~FLAG_USE_XML; + flags |= FLAG_USE_COMPAT; else if (!format.empty()) throw CoreException("Unknown configuration format " + format); } @@ -241,6 +251,8 @@ struct Parser { case EOF: // this is the one place where an EOF is not an error + if (!mandatory_tag.empty()) + throw CoreException("Mandatory tag \"" + mandatory_tag + "\" not found"); return true; case '#': comment(); @@ -277,6 +289,10 @@ void ParseStack::DoInclude(ConfigTag* tag, int flags) { if (flags & FLAG_NO_INC) throw CoreException("Invalid tag in file included with noinclude=\"yes\""); + + std::string mandatorytag; + tag->readString("mandatorytag", mandatorytag); + std::string name; if (tag->readString("file", name)) { @@ -284,7 +300,7 @@ void ParseStack::DoInclude(ConfigTag* tag, int flags) flags |= FLAG_NO_INC; if (tag->getBool("noexec", false)) flags |= FLAG_NO_EXEC; - if (!ParseFile(name, flags)) + if (!ParseFile(name, flags, mandatorytag)) throw CoreException("Included"); } else if (tag->readString("executable", name)) @@ -295,7 +311,7 @@ void ParseStack::DoInclude(ConfigTag* tag, int flags) flags |= FLAG_NO_INC; if (tag->getBool("noexec", true)) flags |= FLAG_NO_EXEC; - if (!ParseExec(name, flags)) + if (!ParseExec(name, flags, mandatorytag)) throw CoreException("Included"); } } @@ -307,49 +323,55 @@ void ParseStack::DoReadFile(const std::string& key, const std::string& name, int if (exec && (flags & FLAG_NO_EXEC)) throw CoreException("Invalid tag in file included with noexec=\"yes\""); - FileWrapper file(exec ? popen(name.c_str(), "r") : fopen(name.c_str(), "r")); + std::string path = ServerInstance->Config->Paths.PrependConfig(name); + FileWrapper file(exec ? popen(name.c_str(), "r") : fopen(path.c_str(), "r"), exec); if (!file) - throw CoreException("Could not read \"" + name + "\" for \"" + key + "\" file"); + throw CoreException("Could not read \"" + path + "\" for \"" + key + "\" file"); file_cache& cache = FilesOutput[key]; cache.clear(); - char linebuf[MAXBUF*10]; + char linebuf[5120]; while (fgets(linebuf, sizeof(linebuf), file)) { - int len = strlen(linebuf); + size_t len = strlen(linebuf); if (len) - cache.push_back(std::string(linebuf, len - 1)); + { + if (linebuf[len-1] == '\n') + len--; + cache.push_back(std::string(linebuf, len)); + } } } -bool ParseStack::ParseFile(const std::string& name, int flags) +bool ParseStack::ParseFile(const std::string& name, int flags, const std::string& mandatory_tag) { - ServerInstance->Logs->Log("CONFIG", DEBUG, "Reading file %s", name.c_str()); + std::string path = ServerInstance->Config->Paths.PrependConfig(name); + ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "Reading file %s", path.c_str()); for (unsigned int t = 0; t < reading.size(); t++) { if (std::string(name) == reading[t]) { - throw CoreException("File " + name + " is included recursively (looped inclusion)"); + throw CoreException("File " + path + " is included recursively (looped inclusion)"); } } /* It's not already included, add it to the list of files we've loaded */ - FileWrapper file(fopen(name.c_str(), "r")); + FileWrapper file(fopen(path.c_str(), "r")); if (!file) - throw CoreException("Could not read \"" + name + "\" for include"); + throw CoreException("Could not read \"" + path + "\" for include"); - reading.push_back(name); - Parser p(*this, flags, file, name); + reading.push_back(path); + Parser p(*this, flags, file, path, mandatory_tag); bool ok = p.outer_parse(); reading.pop_back(); return ok; } -bool ParseStack::ParseExec(const std::string& name, int flags) +bool ParseStack::ParseExec(const std::string& name, int flags, const std::string& mandatory_tag) { - ServerInstance->Logs->Log("CONFIG", DEBUG, "Reading executable %s", name.c_str()); + ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "Reading executable %s", name.c_str()); for (unsigned int t = 0; t < reading.size(); t++) { if (std::string(name) == reading[t]) @@ -360,12 +382,12 @@ bool ParseStack::ParseExec(const std::string& name, int flags) /* It's not already included, add it to the list of files we've loaded */ - FileWrapper file(popen(name.c_str(), "r")); + FileWrapper file(popen(name.c_str(), "r"), true); if (!file) throw CoreException("Could not open executable \"" + name + "\" for include"); reading.push_back(name); - Parser p(*this, flags, file, name); + Parser p(*this, flags, file, name, mandatory_tag); bool ok = p.outer_parse(); reading.pop_back(); return ok; @@ -382,7 +404,7 @@ bool ConfigTag::readString(const std::string& key, std::string& value, bool allo value = j->second; if (!allow_lf && (value.find('\n') != std::string::npos)) { - ServerInstance->Logs->Log("CONFIG",DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() + + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() + " contains a linefeed, and linefeeds in this value are not permitted -- stripped to spaces."); for (std::string::iterator n = value.begin(); n != value.end(); n++) if (*n == '\n') @@ -400,7 +422,7 @@ std::string ConfigTag::getString(const std::string& key, const std::string& def) return res; } -long ConfigTag::getInt(const std::string &key, long def) +long ConfigTag::getInt(const std::string &key, long def, long min, long max) { std::string result; if(!readString(key, result)) @@ -414,18 +436,41 @@ long ConfigTag::getInt(const std::string &key, long def) switch (toupper(*res_tail)) { case 'K': - res= res* 1024; + res = res * 1024; break; case 'M': - res= res* 1024 * 1024; + res = res * 1024 * 1024; break; case 'G': - res= res* 1024 * 1024 * 1024; + res = res * 1024 * 1024 * 1024; break; } + + CheckRange(key, res, def, min, max); return res; } +void ConfigTag::CheckRange(const std::string& key, long& res, long def, long min, 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; + } +} + +time_t ConfigTag::getDuration(const std::string& key, long def, long min, long max) +{ + std::string duration; + if (!readString(key, duration)) + return def; + + time_t ret = InspIRCd::Duration(duration); + CheckRange(key, ret, def, min, max); + return ret; +} + double ConfigTag::getFloat(const std::string &key, double def) { std::string result; @@ -445,7 +490,7 @@ bool ConfigTag::getBool(const std::string &key, bool def) if (result == "no" || result == "false" || result == "0" || result == "off") return false; - ServerInstance->Logs->Log("CONFIG",DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() + + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() + " is not valid, ignoring"); return def; }