]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/configparser.cpp
Fix leaking the dccallow list instead of setting it in FromInternal.
[user/henk/code/inspircd.git] / src / configparser.cpp
index efcc6c68bb7859a00b1fb71ee397a20a438e00ff..0102c910c3bf21c72276d04acb2dc3baa25c50ad 100644 (file)
@@ -1,6 +1,12 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
+ *   Copyright (C) 2018 linuxdaemon <linuxdaemon.irc@gmail.com>
+ *   Copyright (C) 2013-2014, 2016-2020 Sadie Powell <sadie@witchery.services>
+ *   Copyright (C) 2013 ChrisTX <xpipe@hotmail.de>
+ *   Copyright (C) 2012-2014 Attila Molnar <attilamolnar@hush.com>
+ *   Copyright (C) 2012 Robby <robby@chatbelgie.be>
+ *   Copyright (C) 2010 Craig Edwards <brain@inspircd.org>
  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
  *
  * This file is part of InspIRCd.  InspIRCd is free software: you can
 #include <fstream>
 #include "configparser.h"
 
+enum ParseFlags
+{
+       // Legacy config parsing should be used.
+       FLAG_USE_COMPAT = 1,
+
+       // Executable includes are disabled.
+       FLAG_NO_EXEC = 2,
+
+       // All includes are disabled.
+       FLAG_NO_INC = 4
+};
+
+// Represents the position within a config file.
+struct FilePosition
+{
+       // The name of the file which is being read.
+       std::string name;
+
+       // The line of the file that this position points to.
+       unsigned int line;
+
+       // The column of the file that this position points to.
+       unsigned int column;
+
+       FilePosition(const std::string& Name)
+               : name(Name)
+               , line(1)
+               , column(1)
+       {
+       }
+
+       /** Returns a string that represents this file position. */
+       std::string str()
+       {
+               return name + ":" + ConvToStr(line) + ":" + ConvToStr(column);
+       }
+};
+
+// RAII wrapper for FILE* which closes the file when it goes out of scope.
+class FileWrapper
+{
+ private:
+       // Whether this file handle should be closed with pclose.
+       bool close_with_pclose;
+
+       // The file handle which is being wrapped.
+       FILE* const file;
+
+ public:
+       FileWrapper(FILE* File, bool CloseWithPClose = false)
+               : close_with_pclose(CloseWithPClose)
+               , file(File)
+       {
+       }
+
+       // Operator which determines whether the file is open.
+       operator bool() { return (file != NULL); }
+
+       // Operator which retrieves the underlying FILE pointer.
+       operator FILE*() { return file; }
+
+       ~FileWrapper()
+       {
+               if (!file)
+                       return;
+
+               if (close_with_pclose)
+                       pclose(file);
+               else
+                       fclose(file);
+       }
+};
+
+
 struct Parser
 {
        ParseStack& stack;
        int flags;
        FILE* const file;
-       fpos current;
-       fpos last_tag;
+       FilePosition current;
+       FilePosition last_tag;
        reference<ConfigTag> tag;
        int ungot;
        std::string mandatory_tag;
@@ -52,11 +132,11 @@ struct Parser
                else if (ch == '\n')
                {
                        current.line++;
-                       current.col = 0;
+                       current.column = 0;
                }
                else
                {
-                       current.col++;
+                       current.column++;
                }
                return ch;
        }
@@ -200,7 +280,7 @@ struct Parser
                        throw CoreException("Empty tag name");
 
                ConfigItems* items;
-               tag = ConfigTag::create(name, current.filename, current.line, items);
+               tag = ConfigTag::create(name, current.name, current.line, items);
 
                while (kv(items))
                {
@@ -320,9 +400,30 @@ void ParseStack::DoInclude(ConfigTag* tag, int flags)
                        flags |= FLAG_NO_INC;
                if (tag->getBool("noexec", false))
                        flags |= FLAG_NO_EXEC;
+
                if (!ParseFile(ServerInstance->Config->Paths.PrependConfig(name), flags, mandatorytag))
                        throw CoreException("Included");
        }
+       else if (tag->readString("directory", name))
+       {
+               if (tag->getBool("noinclude", false))
+                       flags |= FLAG_NO_INC;
+               if (tag->getBool("noexec", false))
+                       flags |= FLAG_NO_EXEC;
+
+               const std::string includedir = ServerInstance->Config->Paths.PrependConfig(name);
+               std::vector<std::string> files;
+               if (!FileSystem::GetFileList(includedir, files, "*.conf"))
+                       throw CoreException("Unable to read directory for include: " + includedir);
+
+               std::sort(files.begin(), files.end()); 
+               for (std::vector<std::string>::const_iterator iter = files.begin(); iter != files.end(); ++iter)
+               {
+                       const std::string path = includedir + '/' + *iter;
+                       if (!ParseFile(path, flags, mandatorytag))
+                               throw CoreException("Included");
+               }
+       }
        else if (tag->readString("executable", name))
        {
                if (flags & FLAG_NO_EXEC)
@@ -331,6 +432,7 @@ void ParseStack::DoInclude(ConfigTag* tag, int flags)
                        flags |= FLAG_NO_INC;
                if (tag->getBool("noexec", true))
                        flags |= FLAG_NO_EXEC;
+
                if (!ParseFile(name, flags, mandatorytag, true))
                        throw CoreException("Included");
        }
@@ -535,14 +637,14 @@ unsigned long ConfigTag::getDuration(const std::string& key, unsigned long def,
        if (!readString(key, duration))
                return def;
 
-       if (!InspIRCd::IsValidDuration(duration))
+       unsigned long ret;
+       if (!InspIRCd::Duration(duration, ret))
        {
                ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() +
                        " is not a duration; value set to " + ConvToStr(def) + ".");
                return def;
        }
 
-       unsigned long ret = InspIRCd::Duration(duration);
        CheckRange(tag, key, ret, def, min, max);
        return ret;
 }
@@ -564,9 +666,10 @@ bool ConfigTag::getBool(const std::string &key, bool def)
        if(!readString(key, result))
                return def;
 
-       if (result == "yes" || result == "true" || result == "1" || result == "on")
+       if (stdalgo::string::equalsci(result, "yes") || stdalgo::string::equalsci(result, "true") || stdalgo::string::equalsci(result, "on") || result == "1")
                return true;
-       if (result == "no" || result == "false" || result == "0" || result == "off")
+
+       if (stdalgo::string::equalsci(result, "no") || stdalgo::string::equalsci(result, "false") || stdalgo::string::equalsci(result, "off") || result == "0")
                return false;
 
        ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() +