]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/configparser.cpp
m_ident: Add an option to allow idents of users to still be prefixed with a '~' for...
[user/henk/code/inspircd.git] / src / configparser.cpp
index 1783e901e8f8a23f725a537479fab617a36b2c8e..2f3fbb5b43471a03cfa14a3ffdaa76747dd04ca0 100644 (file)
@@ -125,7 +125,7 @@ struct Parser
                                while (1)
                                {
                                        ch = next();
-                                       if (isalnum(ch))
+                                       if (isalnum(ch) || (varname.empty() && ch == '#'))
                                                varname.push_back(ch);
                                        else if (ch == ';')
                                                break;
@@ -136,10 +136,30 @@ struct Parser
                                                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);
+                               if (varname.empty())
+                                       throw CoreException("Empty XML entity reference");
+                               else if (varname[0] == '#' && (varname.size() == 1 || (varname.size() == 2 && varname[1] == 'x')))
+                                       throw CoreException("Empty numeric character reference");
+                               else if (varname[0] == '#')
+                               {
+                                       const char* cvarname = varname.c_str();
+                                       char* endptr;
+                                       unsigned long lvalue;
+                                       if (cvarname[1] == 'x')
+                                               lvalue = strtoul(cvarname + 2, &endptr, 16);
+                                       else
+                                               lvalue = strtoul(cvarname + 1, &endptr, 10);
+                                       if (*endptr != '\0' || lvalue > 255)
+                                               throw CoreException("Invalid numeric character reference '&" + varname + ";'");
+                                       value.push_back(static_cast<char>(lvalue));
+                               }
+                               else
+                               {
+                                       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 == '\\' && (flags & FLAG_USE_COMPAT))
                        {
@@ -300,7 +320,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, mandatorytag))
+               if (!ParseFile(ServerInstance->Config->Paths.PrependConfig(name), flags, mandatorytag))
                        throw CoreException("Included");
        }
        else if (tag->readString("executable", name))
@@ -344,13 +364,12 @@ void ParseStack::DoReadFile(const std::string& key, const std::string& name, int
        }
 }
 
-bool ParseStack::ParseFile(const std::string& name, int flags, const std::string& mandatory_tag)
+bool ParseStack::ParseFile(const std::string& path, int flags, const std::string& mandatory_tag)
 {
-       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])
+               if (path == reading[t])
                {
                        throw CoreException("File " + path + " is included recursively (looped inclusion)");
                }
@@ -445,13 +464,30 @@ long ConfigTag::getInt(const std::string &key, long def, long min, long max)
                        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;
        }
-       return res;
+}
+
+long ConfigTag::getDuration(const std::string& key, long def, long min, long max)
+{
+       std::string duration;
+       if (!readString(key, duration))
+               return def;
+
+       long ret = InspIRCd::Duration(duration);
+       CheckRange(key, ret, def, min, max);
+       return ret;
 }
 
 double ConfigTag::getFloat(const std::string &key, double def)
@@ -483,10 +519,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<KeyVal>*&items)
+ConfigTag* ConfigTag::create(const std::string& Tag, const std::string& file, int line, std::vector<KeyVal>*& Items)
 {
        ConfigTag* rv = new ConfigTag(Tag, file, line);
-       items = &rv->items;
+       Items = &rv->items;
        return rv;
 }