]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/configreader.cpp
Move some local-only fields to LocalUser
[user/henk/code/inspircd.git] / src / configreader.cpp
index 35196343dd75e4afed7fc84d3dbe8e2e9a29c3c1..6932e960ee706eeac38453462d30b750c0ce9713 100644 (file)
@@ -23,7 +23,7 @@
 /* $CopyInstall: conf/modules.conf.example $(CONPATH) */
 /* $CopyInstall: conf/opers.conf.example $(CONPATH) */
 /* $CopyInstall: conf/links.conf.example $(CONPATH) */
-/* $CopyInstall: .gdbargs $(BASE) */
+/* $CopyInstall: tools/gdbargs $(BASE)/.gdbargs */
 
 #include "inspircd.h"
 #include <fstream>
@@ -53,12 +53,17 @@ enum ParseFlags
 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);
@@ -161,13 +166,27 @@ struct Parser
                while (1)
                {
                        ch = next();
-                       if (ch == '\\')
+                       if (ch == '&')
                        {
-                               ch = next();
-                               if (ch == 'n')
-                                       ch = '\n';
-                               else if (ch == 'r')
-                                       ch = '\r';
+                               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;
@@ -184,7 +203,9 @@ struct Parser
                nextword(name);
 
                int spc = next();
-               if (!isspace(spc))
+               if (spc == '>')
+                       unget(spc);
+               else if (!isspace(spc))
                        throw CoreException("Invalid character in tag name");
 
                if (name.empty())
@@ -194,13 +215,21 @@ struct Parser
 
                while (kv());
 
-               if (tag->tag == "include")
+               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(tag->tag, tag));
+                       stack.output.insert(std::make_pair(name, tag));
                }
                // this is not a leak; reference<> takes care of the delete
                tag = NULL;
@@ -276,6 +305,20 @@ void ParseStack::DoInclude(ConfigTag* tag, int flags)
        }
 }
 
+/** 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());
@@ -289,7 +332,7 @@ bool ParseStack::ParseFile(const std::string& name, int flags)
 
        /* It's not already included, add it to the list of files we've loaded */
 
-       FILE* file = fopen(name.c_str(), "r");
+       FileWrapper file(fopen(name.c_str(), "r"));
        if (!file)
                throw CoreException("Could not read \"" + name + "\" for include");
 
@@ -313,7 +356,7 @@ bool ParseStack::ParseExec(const std::string& name, int flags)
 
        /* It's not already included, add it to the list of files we've loaded */
 
-       FILE* file = popen(name.c_str(), "r");
+       FileWrapper file(popen(name.c_str(), "r"));
        if (!file)
                throw CoreException("Could not open executable \"" + name + "\" for include");
 
@@ -681,6 +724,7 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
                        me->softsendqmax = tag->getInt("softsendq", me->softsendqmax);
                        me->hardsendqmax = tag->getInt("hardsendq", me->hardsendqmax);
                        me->recvqmax = tag->getInt("recvq", me->recvqmax);
+                       me->penaltythreshold = tag->getInt("threshold", me->penaltythreshold);
                        me->maxlocal = tag->getInt("localmax", me->maxlocal);
                        me->maxglobal = tag->getInt("globalmax", me->maxglobal);
                        me->port = tag->getInt("port", me->port);
@@ -764,7 +808,7 @@ void ServerConfig::Fill()
        AdminName = ConfValue("admin")->getString("name", "");
        AdminEmail = ConfValue("admin")->getString("email", "null@example.com");
        AdminNick = ConfValue("admin")->getString("nick", "admin");
-       ModPath = options->getString("moduledir", MOD_PATH);
+       ModPath = ConfValue("path")->getString("moduledir", MOD_PATH);
        NetBufferSize = ConfValue("performance")->getInt("netbuffersize", 10240);
        MaxWhoResults = ConfValue("performance")->getInt("maxwho", 1024);
        dns_timeout = ConfValue("dns")->getInt("timeout", 5);
@@ -1218,31 +1262,23 @@ bool ServerConfig::ReadFile(file_cache &F, const std::string& fname)
        if (fname.empty())
                return false;
 
-       FILE* file = NULL;
        char linebuf[MAXBUF];
 
        F.clear();
 
-       if (!FileExists(fname.c_str()))
-               return false;
-       file = fopen(fname.c_str(), "r");
+       FileWrapper file(fopen(fname.c_str(), "r"));
 
-       if (file)
+       if (!file)
+               return false;
+       while (!feof(file))
        {
-               while (!feof(file))
-               {
-                       if (fgets(linebuf, sizeof(linebuf), file))
-                               linebuf[strlen(linebuf)-1] = 0;
-                       else
-                               *linebuf = 0;
-
-                       F.push_back(*linebuf ? linebuf : " ");
-               }
+               if (fgets(linebuf, sizeof(linebuf), file))
+                       linebuf[strlen(linebuf)-1] = 0;
+               else
+                       *linebuf = 0;
 
-               fclose(file);
+               F.push_back(*linebuf ? linebuf : " ");
        }
-       else
-               return false;
 
        return true;
 }