]> granicus.if.org Git - icinga2/commitdiff
Turn includes into AST expressions
authorGunnar Beutner <gunnar@beutner.name>
Thu, 22 Oct 2015 07:46:31 +0000 (09:46 +0200)
committerGunnar Beutner <gunnar@beutner.name>
Thu, 22 Oct 2015 07:46:31 +0000 (09:46 +0200)
fixes #10008

lib/config/config_parser.yy
lib/config/configcompiler.cpp
lib/config/configcompiler.hpp
lib/config/expression.cpp
lib/config/expression.hpp

index 8c81efcd623cc37c6368a9decfd6407b7e18b0f2..a3a22182dca8f50d53ab0ffb400f9b3cb4465e58 100644 (file)
@@ -443,39 +443,30 @@ lterm: T_LIBRARY rterm
        {
                $$ = new SetExpression($1, $2, $3, @$);
        }
-       | T_INCLUDE T_STRING
+       | T_INCLUDE rterm
        {
-               $$ = context->HandleInclude(*$2, false, @$);
-               delete $2;
+               $$ = new IncludeExpression(Utility::DirName(context->GetPath()), $2, NULL, NULL, IncludeRegular, false, context->GetZone(), context->GetPackage(), @$);
        }
        | T_INCLUDE T_STRING_ANGLE
        {
-               $$ = context->HandleInclude(*$2, true, @$);
+               $$ = new IncludeExpression(Utility::DirName(context->GetPath()), MakeLiteral(*$2), NULL, NULL, IncludeRegular, true, context->GetZone(), context->GetPackage(), @$);
                delete $2;
        }
-       | T_INCLUDE_RECURSIVE T_STRING
+       | T_INCLUDE_RECURSIVE rterm
        {
-               $$ = context->HandleIncludeRecursive(*$2, "*.conf", @$);
-               delete $2;
+               $$ = new IncludeExpression(Utility::DirName(context->GetPath()), $2, MakeLiteral("*.conf"), NULL, IncludeRecursive, false, context->GetZone(), context->GetPackage(), @$);
        }
-       | T_INCLUDE_RECURSIVE T_STRING ',' T_STRING
+       | T_INCLUDE_RECURSIVE rterm ',' rterm
        {
-               $$ = context->HandleIncludeRecursive(*$2, *$4, @$);
-               delete $2;
-               delete $4;
+               $$ = new IncludeExpression(Utility::DirName(context->GetPath()), $2, $4, NULL, IncludeRecursive, false, context->GetZone(), context->GetPackage(), @$);
        }
-       | T_INCLUDE_ZONES T_STRING ',' T_STRING
+       | T_INCLUDE_ZONES rterm ',' rterm
        {
-               $$ = context->HandleIncludeZones(*$2, *$4, "*.conf", @$);
-               delete $2;
-               delete $4;
+               $$ = new IncludeExpression(Utility::DirName(context->GetPath()), $4, MakeLiteral("*.conf"), $2, IncludeZones, false, context->GetZone(), context->GetPackage(), @$);
        }
-       | T_INCLUDE_ZONES T_STRING ',' T_STRING ',' T_STRING
+       | T_INCLUDE_ZONES rterm ',' rterm ',' rterm
        {
-               $$ = context->HandleIncludeZones(*$2, *$4, *$6, @$);
-               delete $2;
-               delete $4;
-               delete $6;
+               $$ = new IncludeExpression(Utility::DirName(context->GetPath()), $4, $6, $2, IncludeZones, false, context->GetZone(), context->GetPackage(), @$);
        }
        | T_IMPORT rterm
        {
index 412801a87d88be256610461940f92d16f0c89efa..12ce409188e8502a26eb7224e05da6e01be7f026 100644 (file)
@@ -119,24 +119,26 @@ void ConfigCompiler::CollectIncludes(std::vector<Expression *>& expressions,
 /**
  * Handles an include directive.
  *
- * @param include The path from the include directive.
+ * @param relativeBath The path this include is relative to.
+ * @param path The path from the include directive.
  * @param search Whether to search global include dirs.
  * @param debuginfo Debug information.
  */
-Expression *ConfigCompiler::HandleInclude(const String& include, bool search, const DebugInfo& debuginfo)
+Expression *ConfigCompiler::HandleInclude(const String& relativeBase, const String& path,
+    bool search, const String& zone, const String& package, const DebugInfo& debuginfo)
 {
-       String path;
+       String upath;
 
-       if (search || (include.GetLength() > 0 && include[0] == '/'))
-               path = include;
+       if (search || (path.GetLength() > 0 && path[0] == '/'))
+               upath = path;
        else
-               path = Utility::DirName(GetPath()) + "/" + include;
+               upath = relativeBase + "/" + path;
 
-       String includePath = path;
+       String includePath = upath;
 
        if (search) {
                BOOST_FOREACH(const String& dir, m_IncludeSearchDirs) {
-                       String spath = dir + "/" + include;
+                       String spath = dir + "/" + path;
 
                        if (Utility::PathExists(spath)) {
                                includePath = spath;
@@ -147,9 +149,9 @@ Expression *ConfigCompiler::HandleInclude(const String& include, bool search, co
 
        std::vector<Expression *> expressions;
 
-       if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, m_Zone, m_Package), GlobFile) && includePath.FindFirstOf("*?") == String::NPos) {
+       if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, zone, package), GlobFile) && includePath.FindFirstOf("*?") == String::NPos) {
                std::ostringstream msgbuf;
-               msgbuf << "Include file '" + include + "' does not exist";
+               msgbuf << "Include file '" + path + "' does not exist";
                BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str(), debuginfo));
        }
 
@@ -161,25 +163,27 @@ Expression *ConfigCompiler::HandleInclude(const String& include, bool search, co
 /**
  * Handles recursive includes.
  *
+ * @param relativeBase The path this include is relative to.
  * @param path The directory path.
  * @param pattern The file pattern.
  * @param debuginfo Debug information.
  */
-Expression *ConfigCompiler::HandleIncludeRecursive(const String& path, const String& pattern, const DebugInfo&)
+Expression *ConfigCompiler::HandleIncludeRecursive(const String& relativeBase, const String& path,
+    const String& pattern, const String& zone, const String& package, const DebugInfo&)
 {
        String ppath;
 
        if (path.GetLength() > 0 && path[0] == '/')
                ppath = path;
        else
-               ppath = Utility::DirName(GetPath()) + "/" + path;
+               ppath = relativeBase + "/" + path;
 
        std::vector<Expression *> expressions;
-       Utility::GlobRecursive(ppath, pattern, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, m_Zone, m_Package), GlobFile);
+       Utility::GlobRecursive(ppath, pattern, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, zone, package), GlobFile);
        return new DictExpression(expressions);
 }
 
-void ConfigCompiler::HandleIncludeZone(const String& tag, const String& path, const String& pattern, std::vector<Expression *>& expressions)
+void ConfigCompiler::HandleIncludeZone(const String& relativeBase, const String& tag, const String& path, const String& pattern, const String& package, std::vector<Expression *>& expressions)
 {
        String zoneName = Utility::BaseName(path);
 
@@ -188,32 +192,34 @@ void ConfigCompiler::HandleIncludeZone(const String& tag, const String& path, co
        if (path.GetLength() > 0 && path[0] == '/')
                ppath = path;
        else
-               ppath = Utility::DirName(GetPath()) + "/" + path;
+               ppath = relativeBase + "/" + path;
 
        RegisterZoneDir(tag, ppath, zoneName);
 
-       Utility::GlobRecursive(ppath, pattern, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, zoneName, m_Package), GlobFile);
+       Utility::GlobRecursive(ppath, pattern, boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, zoneName, package), GlobFile);
 }
 
 /**
  * Handles zone includes.
  *
+ * @param relativeBase The path this include is relative to.
  * @param tag The tag name.
  * @param path The directory path.
  * @param pattern The file pattern.
  * @param debuginfo Debug information.
  */
-Expression *ConfigCompiler::HandleIncludeZones(const String& tag, const String& path, const String& pattern, const DebugInfo&)
+Expression *ConfigCompiler::HandleIncludeZones(const String& relativeBase, const String& tag,
+    const String& path, const String& pattern, const String& package, const DebugInfo&)
 {
        String ppath;
 
        if (path.GetLength() > 0 && path[0] == '/')
                ppath = path;
        else
-               ppath = Utility::DirName(GetPath()) + "/" + path;
+               ppath = relativeBase + "/" + path;
 
        std::vector<Expression *> expressions;
-       Utility::Glob(ppath + "/*", boost::bind(&ConfigCompiler::HandleIncludeZone, this, tag, _1, pattern, boost::ref(expressions)), GlobDirectory);
+       Utility::Glob(ppath + "/*", boost::bind(&ConfigCompiler::HandleIncludeZone, relativeBase, tag, _1, pattern, package, boost::ref(expressions)), GlobDirectory);
        return new DictExpression(expressions);
 }
 
index b216b12a198d07c8b79250d4ace38d86a1cf48b8..66e8df177f67a328f64b2f8382332f7eb5d1ac11 100644 (file)
@@ -105,10 +105,12 @@ public:
        static void CollectIncludes(std::vector<Expression *>& expressions,
            const String& file, const String& zone, const String& package);
 
-       /* internally used methods */
-       Expression *HandleInclude(const String& include, bool search, const DebugInfo& debuginfo = DebugInfo());
-       Expression *HandleIncludeRecursive(const String& path, const String& pattern, const DebugInfo& debuginfo = DebugInfo());
-       Expression *HandleIncludeZones(const String& tag, const String& path, const String& pattern, const DebugInfo& debuginfo = DebugInfo());
+       static Expression *HandleInclude(const String& relativeBase, const String& path, bool search,
+           const String& zone, const String& package, const DebugInfo& debuginfo = DebugInfo());
+       static Expression *HandleIncludeRecursive(const String& relativeBase, const String& path,
+           const String& pattern, const String& zone, const String& package, const DebugInfo& debuginfo = DebugInfo());
+       static Expression *HandleIncludeZones(const String& relativeBase, const String& tag,
+           const String& path, const String& pattern, const String& package, const DebugInfo& debuginfo = DebugInfo());
 
        size_t ReadInput(char *buffer, size_t max_bytes);
        void *GetScanner(void) const;
@@ -135,7 +137,7 @@ private:
        void InitializeScanner(void);
        void DestroyScanner(void);
 
-       void HandleIncludeZone(const String& tag, const String& path, const String& pattern, std::vector<Expression *>& expressions);
+       static void HandleIncludeZone(const String& relativeBase, const String& tag, const String& path, const String& pattern, const String& package, std::vector<Expression *>& expressions);
 
 public:
        bool m_Eof;
index f1679a84cb41895730fbbfc28a4511ffd5471bff..1c4dcea293d2859f285516ab345c032028e28b77 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "config/expression.hpp"
 #include "config/configitem.hpp"
+#include "config/configcompiler.hpp"
 #include "config/vmops.hpp"
 #include "base/array.hpp"
 #include "base/json.hpp"
@@ -783,3 +784,74 @@ ExpressionResult LibraryExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dh
        return Empty;
 }
 
+ExpressionResult IncludeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
+{
+       if (frame.Sandboxed)
+               BOOST_THROW_EXCEPTION(ScriptError("Includes are not allowed in sandbox mode.", m_DebugInfo));
+
+       Expression *expr;
+       String name, path, pattern;
+
+       switch (m_Type) {
+               case IncludeRegular:
+                       {
+                               ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
+                               CHECK_RESULT(pathres);
+                               path = pathres.GetValue();
+                       }
+
+                       expr = ConfigCompiler::HandleInclude(m_RelativeBase, path, m_SearchIncludes, m_Zone, m_Package, m_DebugInfo);
+                       break;
+
+               case IncludeRecursive:
+                       {
+                               ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
+                               CHECK_RESULT(pathres);
+                               path = pathres.GetValue();
+                       }
+
+                       {
+                               ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
+                               CHECK_RESULT(patternres);
+                               pattern = patternres.GetValue();
+                       }
+
+                       expr = ConfigCompiler::HandleIncludeRecursive(m_RelativeBase, path, pattern, m_Zone, m_Package, m_DebugInfo);
+                       break;
+
+               case IncludeZones:
+                       {
+                               ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
+                               CHECK_RESULT(nameres);
+                               name = nameres.GetValue();
+                       }
+
+                       {
+                               ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
+                               CHECK_RESULT(pathres);
+                               path = pathres.GetValue();
+                       }
+
+                       {
+                               ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
+                               CHECK_RESULT(patternres);
+                               pattern = patternres.GetValue();
+                       }
+
+                       expr = ConfigCompiler::HandleIncludeZones(m_RelativeBase, name, path, pattern, m_Package, m_DebugInfo);
+                       break;
+       }
+
+       ExpressionResult res(Empty);
+
+       try {
+               res = expr->Evaluate(frame, dhint);
+       } catch (const std::exception&) {
+               delete expr;
+               throw;
+       }
+
+       delete expr;
+
+       return res;
+}
index dba2db3ae22e9933e11d3c4a31eaeff3cb13accf..130edf5a5d7e4751e5575ee5fdb0897ef390c4ab 100644 (file)
@@ -899,6 +899,43 @@ protected:
        virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
 };
 
+enum IncludeType
+{
+       IncludeRegular,
+       IncludeRecursive,
+       IncludeZones
+};
+
+class I2_CONFIG_API IncludeExpression : public DebuggableExpression
+{
+public:
+       IncludeExpression(const String& relativeBase, Expression *path, Expression *pattern, Expression *name,
+           IncludeType type, bool searchIncludes, const String& zone, const String& package, const DebugInfo& debugInfo = DebugInfo())
+               : DebuggableExpression(debugInfo), m_RelativeBase(relativeBase), m_Path(path), m_Pattern(pattern),
+                 m_Name(name), m_Type(type), m_SearchIncludes(searchIncludes), m_Zone(zone), m_Package(package)
+       { }
+
+       ~IncludeExpression(void)
+       {
+               delete m_Path;
+               delete m_Pattern;
+               delete m_Name;
+       }
+
+protected:
+       virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
+
+private:
+       String m_RelativeBase;
+       Expression *m_Path;
+       Expression *m_Pattern;
+       Expression *m_Name;
+       IncludeType m_Type;
+       bool m_SearchIncludes;
+       String m_Zone;
+       String m_Package;
+};
+
 }
 
 #endif /* EXPRESSION_H */