summaryrefslogtreecommitdiff
path: root/src/configreader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/configreader.cpp')
-rw-r--r--src/configreader.cpp425
1 files changed, 1 insertions, 424 deletions
diff --git a/src/configreader.cpp b/src/configreader.cpp
index 9a315fe0b..5fa56ba8f 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -31,343 +31,7 @@
#include "exitcodes.h"
#include "commands/cmd_whowas.h"
#include "modes/cmode_h.h"
-
-struct fpos
-{
- std::string filename;
- int line;
- int col;
- fpos(const std::string& name, int l = 1, int c = 1) : filename(name), line(l), col(c) {}
- std::string str()
- {
- return filename + ":" + ConvToStr(line) + ":" + ConvToStr(col);
- }
-};
-
-enum ParseFlags
-{
- FLAG_NO_EXEC = 1,
- FLAG_NO_INC = 2
-};
-
-struct ParseStack
-{
- std::vector<std::string> reading;
- std::map<std::string, std::string> vars;
- ConfigDataHash& output;
- std::stringstream& errstr;
-
- ParseStack(ServerConfig* conf)
- : output(conf->config_data), errstr(conf->errstr)
- {
- vars["amp"] = "&";
- vars["quot"] = "\"";
- vars["newline"] = vars["nl"] = "\n";
- }
- bool ParseFile(const std::string& name, int flags);
- bool ParseExec(const std::string& name, int flags);
- void DoInclude(ConfigTag* includeTag, int flags);
-};
-
-struct Parser
-{
- ParseStack& stack;
- const int flags;
- FILE* const file;
- fpos current;
- fpos last_tag;
- reference<ConfigTag> tag;
- int ungot;
-
- Parser(ParseStack& me, int myflags, FILE* conf, const std::string& name)
- : stack(me), flags(myflags), file(conf), current(name), last_tag(name), ungot(-1)
- { }
-
- int next(bool eof_ok = false)
- {
- if (ungot != -1)
- {
- int ch = ungot;
- ungot = -1;
- return ch;
- }
- int ch = fgetc(file);
- if (ch == EOF && !eof_ok)
- {
- throw CoreException("Unexpected end-of-file");
- }
- else if (ch == '\n')
- {
- current.line++;
- current.col = 0;
- }
- else
- {
- current.col++;
- }
- return ch;
- }
-
- void unget(int ch)
- {
- if (ungot != -1)
- throw CoreException("INTERNAL ERROR: cannot unget twice");
- ungot = ch;
- }
-
- void comment()
- {
- while (1)
- {
- int ch = next();
- if (ch == '\n')
- return;
- }
- }
-
- void nextword(std::string& rv)
- {
- int ch = next();
- while (isspace(ch))
- ch = next();
- while (isalnum(ch) || ch == '_')
- {
- rv.push_back(ch);
- ch = next();
- }
- unget(ch);
- }
-
- bool kv()
- {
- std::string key;
- nextword(key);
- int ch = next();
- if (ch == '>' && key.empty())
- {
- return false;
- }
- else if (ch == '#' && key.empty())
- {
- comment();
- return true;
- }
- else if (ch != '=')
- {
- throw CoreException("Invalid character " + std::string(1, ch) + " in key (" + key + ")");
- }
-
- std::string value;
- ch = next();
- if (ch != '"')
- {
- throw CoreException("Invalid character in value of <" + tag->tag + ":" + key + ">");
- }
- while (1)
- {
- ch = next();
- if (ch == '&')
- {
- std::string varname;
- while (1)
- {
- ch = next();
- if (isalnum(ch))
- varname.push_back(ch);
- else if (ch == ';')
- break;
- else
- {
- stack.errstr << "Invalid XML entity name in value of <" + tag->tag + ":" + key + ">\n"
- << "To include an ampersand or quote, use &amp; or &quot;\n";
- throw CoreException("Parse error");
- }
- }
- std::map<std::string, std::string>::iterator var = stack.vars.find(varname);
- if (var == stack.vars.end())
- throw CoreException("Undefined XML entity reference '&" + varname + ";'");
- value.append(var->second);
- }
- else if (ch == '"')
- break;
- value.push_back(ch);
- }
- tag->items.push_back(KeyVal(key, value));
- return true;
- }
-
- void dotag()
- {
- last_tag = current;
- std::string name;
- nextword(name);
-
- int spc = next();
- if (spc == '>')
- unget(spc);
- else if (!isspace(spc))
- throw CoreException("Invalid character in tag name");
-
- if (name.empty())
- throw CoreException("Empty tag name");
-
- tag = new ConfigTag(name, current.filename, current.line);
-
- while (kv());
-
- if (name == "include")
- {
- stack.DoInclude(tag, flags);
- }
- else if (name == "define")
- {
- std::string varname = tag->getString("name");
- std::string value = tag->getString("value");
- if (varname.empty())
- throw CoreException("Variable definition must include variable name");
- stack.vars[varname] = value;
- }
- else
- {
- stack.output.insert(std::make_pair(name, tag));
- }
- // this is not a leak; reference<> takes care of the delete
- tag = NULL;
- }
-
- bool outer_parse()
- {
- try
- {
- while (1)
- {
- int ch = next(true);
- switch (ch)
- {
- case EOF:
- // this is the one place where an EOF is not an error
- return true;
- case '#':
- comment();
- break;
- case '<':
- dotag();
- break;
- case ' ':
- case '\r':
- case '\t':
- case '\n':
- break;
- case 0xFE:
- case 0xFF:
- stack.errstr << "Do not save your files as UTF-16; use ASCII!\n";
- default:
- throw CoreException("Syntax error - start of tag expected");
- }
- }
- }
- catch (CoreException& err)
- {
- stack.errstr << err.GetReason() << " at " << current.str();
- if (tag)
- stack.errstr << " (inside tag " << tag->tag << " at line " << tag->src_line << ")\n";
- else
- stack.errstr << " (last tag was on line " << last_tag.line << ")\n";
- }
- return false;
- }
-};
-
-void ParseStack::DoInclude(ConfigTag* tag, int flags)
-{
- if (flags & FLAG_NO_INC)
- throw CoreException("Invalid <include> tag in file included with noinclude=\"yes\"");
- std::string name;
- if (tag->readString("file", name))
- {
- if (tag->getBool("noinclude", false))
- flags |= FLAG_NO_INC;
- if (tag->getBool("noexec", false))
- flags |= FLAG_NO_EXEC;
- if (!ParseFile(name, flags))
- throw CoreException("Included");
- }
- else if (tag->readString("executable", name))
- {
- if (flags & FLAG_NO_EXEC)
- throw CoreException("Invalid <include:executable> tag in file included with noexec=\"yes\"");
- if (tag->getBool("noinclude", false))
- flags |= FLAG_NO_INC;
- if (tag->getBool("noexec", true))
- flags |= FLAG_NO_EXEC;
- if (!ParseExec(name, flags))
- throw CoreException("Included");
- }
-}
-
-/** RAII wrapper on FILE* to close files on exceptions */
-struct FileWrapper
-{
- FILE* const f;
- FileWrapper(FILE* file) : f(file) {}
- operator bool() { return f; }
- operator FILE*() { return f; }
- ~FileWrapper()
- {
- if (f)
- fclose(f);
- }
-};
-
-bool ParseStack::ParseFile(const std::string& name, int flags)
-{
- ServerInstance->Logs->Log("CONFIG", DEBUG, "Reading file %s", name.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)");
- }
- }
-
- /* It's not already included, add it to the list of files we've loaded */
-
- FileWrapper file(fopen(name.c_str(), "r"));
- if (!file)
- throw CoreException("Could not read \"" + name + "\" for include");
-
- reading.push_back(name);
- Parser p(*this, flags, file, name);
- bool ok = p.outer_parse();
- reading.pop_back();
- return ok;
-}
-
-bool ParseStack::ParseExec(const std::string& name, int flags)
-{
- ServerInstance->Logs->Log("CONFIG", DEBUG, "Reading executable %s", name.c_str());
- for (unsigned int t = 0; t < reading.size(); t++)
- {
- if (std::string(name) == reading[t])
- {
- throw CoreException("Executable " + name + " is included recursively (looped inclusion)");
- }
- }
-
- /* It's not already included, add it to the list of files we've loaded */
-
- FileWrapper file(popen(name.c_str(), "r"));
- if (!file)
- throw CoreException("Could not open executable \"" + name + "\" for include");
-
- reading.push_back(name);
- Parser p(*this, flags, file, name);
- bool ok = p.outer_parse();
- reading.pop_back();
- return ok;
-}
-
-/////////////////////////////////////////////////////////////////////////////
+#include "configparser.h"
ServerConfig::ServerConfig()
{
@@ -1200,93 +864,6 @@ ConfigTagList ServerConfig::ConfTags(const std::string& tag)
return config_data.equal_range(tag);
}
-bool ConfigTag::readString(const std::string& key, std::string& value, bool allow_lf)
-{
- if (!this)
- return false;
- for(std::vector<KeyVal>::iterator j = items.begin(); j != items.end(); ++j)
- {
- if(j->first != key)
- continue;
- value = j->second;
- if (!allow_lf && (value.find('\n') != std::string::npos))
- {
- ServerInstance->Logs->Log("CONFIG",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')
- *n = ' ';
- }
- return true;
- }
- return false;
-}
-
-std::string ConfigTag::getString(const std::string& key, const std::string& def)
-{
- std::string res = def;
- readString(key, res);
- return res;
-}
-
-long ConfigTag::getInt(const std::string &key, long def)
-{
- std::string result;
- if(!readString(key, result))
- return def;
-
- const char* res_cstr = result.c_str();
- char* res_tail = NULL;
- 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;
- }
- return res;
-}
-
-double ConfigTag::getFloat(const std::string &key, double def)
-{
- std::string result;
- if (!readString(key, result))
- return def;
- return strtod(result.c_str(), NULL);
-}
-
-bool ConfigTag::getBool(const std::string &key, bool def)
-{
- std::string result;
- if(!readString(key, result))
- return def;
-
- return (result == "yes" || result == "true" || result == "1" || result == "on");
-}
-
-std::string ConfigTag::getTagLocation()
-{
- return src_name + ":" + ConvToStr(src_line);
-}
-
-std::string OperInfo::getConfig(const std::string& key)
-{
- std::string rv;
- if (type_block)
- type_block->readString(key, rv);
- if (oper_block)
- oper_block->readString(key, rv);
- return rv;
-}
-
/** Read the contents of a file located by `fname' into a file_cache pointed at by `F'.
*/
bool ServerConfig::ReadFile(file_cache &F, const std::string& fname)