X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fconfigparser.cpp;h=94192a71bb9166c2e8bda7124793f96c260fbe91;hb=68211809ee3111bdc9609fbd46dc3c875fbb5ea6;hp=558c49117dd69ff6343015205c354c8a27e04af2;hpb=f2256deeefe9a9f57f6f6b902604c01138ad16cc;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/configparser.cpp b/src/configparser.cpp index 558c49117..94192a71b 100644 --- a/src/configparser.cpp +++ b/src/configparser.cpp @@ -1,16 +1,22 @@ -/* +------------------------------------+ - * | Inspire Internet Relay Chat Daemon | - * +------------------------------------+ +/* + * InspIRCd -- Internet Relay Chat Daemon * - * InspIRCd: (C) 2002-2010 InspIRCd Development Team - * See: http://wiki.inspircd.org/Credits + * Copyright (C) 2009-2010 Daniel De Graaf * - * This program is free but copyrighted software; see - * the file COPYING for details. + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. * - * --------------------------------------------------- + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ + #include "inspircd.h" #include #include "configparser.h" @@ -24,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) @@ -76,7 +83,7 @@ struct Parser int ch = next(); while (isspace(ch)) ch = next(); - while (isalnum(ch) || ch == '_') + while (isalnum(ch) || ch == '_'|| ch == '-') { rv.push_back(ch); ch = next(); @@ -84,7 +91,7 @@ struct Parser unget(ch); } - bool kv(std::vector* items) + bool kv(std::vector* items, std::set& seen) { std::string key; nextword(key); @@ -149,6 +156,10 @@ struct Parser else value.push_back(ch); } + + if (!seen.insert(key).second) + throw CoreException("Duplicate key '" + key + "' found"); + items->push_back(KeyVal(key, value)); return true; } @@ -169,9 +180,16 @@ struct Parser throw CoreException("Empty tag name"); std::vector* items; + std::set seen; tag = ConfigTag::create(name, current.filename, current.line, items); - while (kv(items)); + while (kv(items, seen)); + + if (name == mandatory_tag) + { + // Found the mandatory tag + mandatory_tag.clear(); + } if (name == "include") { @@ -230,6 +248,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(); @@ -266,6 +286,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)) { @@ -273,7 +297,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)) @@ -284,7 +308,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"); } } @@ -296,7 +320,7 @@ 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")); + FileWrapper file(exec ? popen(name.c_str(), "r") : fopen(name.c_str(), "r"), exec); if (!file) throw CoreException("Could not read \"" + name + "\" for \"" + key + "\" file"); @@ -306,13 +330,17 @@ void ParseStack::DoReadFile(const std::string& key, const std::string& name, int char linebuf[MAXBUF*10]; 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()); for (unsigned int t = 0; t < reading.size(); t++) @@ -330,13 +358,13 @@ bool ParseStack::ParseFile(const std::string& name, int flags) throw CoreException("Could not read \"" + 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; } -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()); for (unsigned int t = 0; t < reading.size(); t++) @@ -349,12 +377,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; @@ -362,8 +390,17 @@ bool ParseStack::ParseExec(const std::string& name, int flags) bool ConfigTag::readString(const std::string& key, std::string& value, bool allow_lf) { +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wundefined-bool-conversion" +#endif + // TODO: this is undefined behaviour but changing the API is too risky for 2.0. if (!this) return false; +#ifdef __clang__ +# pragma clang diagnostic pop +#endif for(std::vector::iterator j = items.begin(); j != items.end(); ++j) { if(j->first != key) @@ -429,7 +466,14 @@ bool ConfigTag::getBool(const std::string &key, bool def) if(!readString(key, result)) return def; - return (result == "yes" || result == "true" || result == "1" || result == "on"); + if (result == "yes" || result == "true" || result == "1" || result == "on") + return true; + if (result == "no" || result == "false" || result == "0" || result == "off") + return false; + + ServerInstance->Logs->Log("CONFIG",DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() + + " is not valid, ignoring"); + return def; } std::string ConfigTag::getTagLocation() @@ -437,10 +481,10 @@ 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, std::vector*& Items) { ConfigTag* rv = new ConfigTag(Tag, file, line); - items = &rv->items; + Items = &rv->items; return rv; }