]> granicus.if.org Git - icinga2/blobdiff - lib/icinga/macroprocessor.cpp
Workaround for GCC bug 61321
[icinga2] / lib / icinga / macroprocessor.cpp
index c33289a5ed06a34f2d70fab2dbea7f0d8693eb94..9789313f7601dceefa437105e2623041b5e94a24 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  * Icinga 2                                                                   *
- * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org)    *
+ * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/)  *
  *                                                                            *
  * This program is free software; you can redistribute it and/or              *
  * modify it under the terms of the GNU General Public License                *
@@ -28,7 +28,6 @@
 #include "base/scriptframe.hpp"
 #include "base/convert.hpp"
 #include "base/exception.hpp"
-#include <boost/foreach.hpp>
 #include <boost/algorithm/string/split.hpp>
 #include <boost/algorithm/string/join.hpp>
 #include <boost/algorithm/string/classification.hpp>
@@ -54,7 +53,7 @@ Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolv
 
                ObjectLock olock(arr);
 
-               BOOST_FOREACH(const Value& arg, arr) {
+               for (const Value& arg : arr) {
                        /* Note: don't escape macros here. */
                        Value value = InternalResolveMacros(arg, resolvers, cr, missingMacro,
                            EscapeCallback(), resolvedMacros, useResolvedMacros, recursionLevel + 1);
@@ -72,7 +71,7 @@ Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolv
 
                ObjectLock olock(dict);
 
-               BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
+               for (const Dictionary::Pair& kv : dict) {
                        /* Note: don't escape macros here. */
                        resultDict->Set(kv.first, InternalResolveMacros(kv.second, resolvers, cr, missingMacro,
                            EscapeCallback(), resolvedMacros, useResolvedMacros, recursionLevel + 1));
@@ -104,7 +103,7 @@ bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resol
                tokens.erase(tokens.begin());
        }
 
-       BOOST_FOREACH(const ResolverSpec& resolver, resolvers) {
+       for (const ResolverSpec& resolver : resolvers) {
                if (!objName.IsEmpty() && objName != resolver.first)
                        continue;
 
@@ -130,7 +129,7 @@ bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resol
                Value ref = resolver.second;
                bool valid = true;
 
-               BOOST_FOREACH(const String& token, tokens) {
+               for (const String& token : tokens) {
                        if (ref.IsObjectType<Dictionary>()) {
                                Dictionary::Ptr dict = ref;
                                if (dict->Contains(token)) {
@@ -158,6 +157,11 @@ bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resol
                                }
 
                                ref = object->GetField(field);
+
+                               Field fieldInfo = type->GetFieldInfo(field);
+
+                               if (strcmp(fieldInfo.TypeName, "Timestamp") == 0)
+                                       ref = static_cast<long>(ref);
                        }
                }
 
@@ -176,49 +180,39 @@ bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resol
        return false;
 }
 
-Value MacroProcessor::InternalResolveMacrosShim(const std::vector<Value>& args, const ResolverList& resolvers,
-    const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros,
-    bool useResolvedMacros, int recursionLevel)
-{
-       if (args.size() < 1)
-               BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function"));
-
-       String missingMacro;
-
-       return MacroProcessor::InternalResolveMacros(args[0], resolvers, cr, &missingMacro, escapeFn,
-           resolvedMacros, useResolvedMacros, recursionLevel);
-}
-
-Value MacroProcessor::InternalResolveArgumentsShim(const std::vector<Value>& args, const ResolverList& resolvers,
-    const CheckResult::Ptr& cr, const Dictionary::Ptr& resolvedMacros,
-    bool useResolvedMacros, int recursionLevel)
-{
-       if (args.size() < 2)
-               BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function"));
-
-       return MacroProcessor::ResolveArguments(args[0], args[1], resolvers, cr,
-           resolvedMacros, useResolvedMacros, recursionLevel);
-}
-
 Value MacroProcessor::EvaluateFunction(const Function::Ptr& func, const ResolverList& resolvers,
     const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn,
     const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel)
 {
        Dictionary::Ptr resolvers_this = new Dictionary();
 
-       BOOST_FOREACH(const ResolverSpec& resolver, resolvers) {
+       for (const ResolverSpec& resolver : resolvers) {
                resolvers_this->Set(resolver.first, resolver.second);
        }
 
-       resolvers_this->Set("macro", new Function(boost::bind(&MacroProcessor::InternalResolveMacrosShim,
-           _1, boost::cref(resolvers), cr, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros,
-           recursionLevel + 1)));
-       resolvers_this->Set("resolve_arguments", new Function(boost::bind(&MacroProcessor::InternalResolveArgumentsShim,
-           _1, boost::cref(resolvers), cr, resolvedMacros, useResolvedMacros,
-           recursionLevel + 1)));
+       auto internalResolveMacrosShim = [resolvers, cr, resolvedMacros, useResolvedMacros, recursionLevel](const std::vector<Value>& args) {
+               if (args.size() < 1)
+                       BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function"));
+
+               String missingMacro;
+
+               return MacroProcessor::InternalResolveMacros(args[0], resolvers, cr, &missingMacro, MacroProcessor::EscapeCallback(),
+                   resolvedMacros, useResolvedMacros, recursionLevel);
+       };
+
+       resolvers_this->Set("macro", new Function("macro (temporary)", internalResolveMacrosShim, { "str" }));
+
+       auto internalResolveArgumentsShim = [resolvers, cr, resolvedMacros, useResolvedMacros, recursionLevel](const std::vector<Value>& args) {
+               if (args.size() < 2)
+                       BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function"));
+
+               return MacroProcessor::ResolveArguments(args[0], args[1], resolvers, cr,
+                   resolvedMacros, useResolvedMacros, recursionLevel + 1);
+       };
+
+       resolvers_this->Set("resolve_arguments", new Function("resolve_arguments (temporary)", internalResolveArgumentsShim, { "command", "args" }));
 
-       ScriptFrame frame(resolvers_this);
-       return func->Invoke();
+       return func->InvokeThis(resolvers_this);
 }
 
 Value MacroProcessor::InternalResolveMacros(const String& str, const ResolverList& resolvers,
@@ -284,10 +278,10 @@ Value MacroProcessor::InternalResolveMacros(const String& str, const ResolverLis
                                Array::Ptr resolved_arr = new Array();
 
                                ObjectLock olock(arr);
-                               BOOST_FOREACH(const Value& value, arr) {
+                               for (const Value& value : arr) {
                                        if (value.IsScalar()) {
                                                resolved_arr->Add(InternalResolveMacros(value,
-                                                       resolvers, cr, missingMacro, EscapeCallback(), Dictionary::Ptr(),
+                                                       resolvers, cr, missingMacro, EscapeCallback(), nullptr,
                                                        false, recursionLevel + 1));
                                        } else
                                                resolved_arr->Add(value);
@@ -296,7 +290,7 @@ Value MacroProcessor::InternalResolveMacros(const String& str, const ResolverLis
                                resolved_macro = resolved_arr;
                        } else if (resolved_macro.IsString()) {
                                resolved_macro = InternalResolveMacros(resolved_macro,
-                                       resolvers, cr, missingMacro, EscapeCallback(), Dictionary::Ptr(),
+                                       resolvers, cr, missingMacro, EscapeCallback(), nullptr,
                                        false, recursionLevel + 1);
                        }
                }
@@ -351,6 +345,51 @@ bool MacroProcessor::ValidateMacroString(const String& macro)
        return true;
 }
 
+void MacroProcessor::ValidateCustomVars(const ConfigObject::Ptr& object, const Dictionary::Ptr& value)
+{
+       if (!value)
+               return;
+
+       /* string, array, dictionary */
+       ObjectLock olock(value);
+       for (const Dictionary::Pair& kv : value) {
+               const Value& varval = kv.second;
+
+               if (varval.IsObjectType<Dictionary>()) {
+                       /* only one dictonary level */
+                       Dictionary::Ptr varval_dict = varval;
+
+                       ObjectLock xlock(varval_dict);
+                       for (const Dictionary::Pair& kv_var : varval_dict) {
+                               if (!kv_var.second.IsString())
+                                       continue;
+
+                               if (!ValidateMacroString(kv_var.second))
+                                       BOOST_THROW_EXCEPTION(ValidationError(object.get(), { "vars", kv.first, kv_var.first }, "Closing $ not found in macro format string '" + kv_var.second + "'."));
+                       }
+               } else if (varval.IsObjectType<Array>()) {
+                       /* check all array entries */
+                       Array::Ptr varval_arr = varval;
+
+                       ObjectLock ylock (varval_arr);
+                       for (const Value& arrval : varval_arr) {
+                               if (!arrval.IsString())
+                                       continue;
+
+                               if (!ValidateMacroString(arrval)) {
+                                       BOOST_THROW_EXCEPTION(ValidationError(object.get(), { "vars", kv.first }, "Closing $ not found in macro format string '" + arrval + "'."));
+                               }
+                       }
+               } else {
+                       if (!varval.IsString())
+                               continue;
+
+                       if (!ValidateMacroString(varval))
+                               BOOST_THROW_EXCEPTION(ValidationError(object.get(), { "vars", kv.first }, "Closing $ not found in macro format string '" + varval + "'."));
+               }
+       }
+}
+
 void MacroProcessor::AddArgumentHelper(const Array::Ptr& args, const String& key, const String& value,
     bool add_key, bool add_value)
 {
@@ -369,7 +408,7 @@ Value MacroProcessor::EscapeMacroShellArg(const Value& value)
                Array::Ptr arr = value;
 
                ObjectLock olock(arr);
-               BOOST_FOREACH(const Value& arg, arr) {
+               for (const Value& arg : arr) {
                        if (result.GetLength() > 0)
                                result += " ";
 
@@ -406,7 +445,7 @@ Value MacroProcessor::ResolveArguments(const Value& command, const Dictionary::P
 {
        Value resolvedCommand;
        if (!arguments || command.IsObjectType<Array>() || command.IsObjectType<Function>())
-               resolvedCommand = MacroProcessor::ResolveMacros(command, resolvers, cr, NULL,
+               resolvedCommand = MacroProcessor::ResolveMacros(command, resolvers, cr, nullptr,
                    EscapeMacroShellArg, resolvedMacros, useResolvedMacros, recursionLevel + 1);
        else {
                Array::Ptr arr = new Array();
@@ -418,7 +457,7 @@ Value MacroProcessor::ResolveArguments(const Value& command, const Dictionary::P
                std::vector<CommandArgument> args;
 
                ObjectLock olock(arguments);
-               BOOST_FOREACH(const Dictionary::Pair& kv, arguments) {
+               for (const Dictionary::Pair& kv : arguments) {
                        const Value& arginfo = kv.second;
 
                        CommandArgument arg;
@@ -462,7 +501,8 @@ Value MacroProcessor::ResolveArguments(const Value& command, const Dictionary::P
                                                } catch (const std::exception& ex) {
                                                        /* tried to convert a string */
                                                        Log(LogWarning, "PluginUtility")
-                                                           << "Error evaluating set_if value '" << set_if_resolved << "': " << ex.what();
+                                                           << "Error evaluating set_if value '" << set_if_resolved
+                                                           << "' used in argument '" << arg.Key << "': " << ex.what();
                                                        continue;
                                                }
                                        }
@@ -491,23 +531,24 @@ Value MacroProcessor::ResolveArguments(const Value& command, const Dictionary::P
                                continue;
                        }
 
-                       args.push_back(arg);
+                       args.emplace_back(std::move(arg));
                }
 
                std::sort(args.begin(), args.end());
 
                Array::Ptr command_arr = resolvedCommand;
-               BOOST_FOREACH(const CommandArgument& arg, args) {
+               for (const CommandArgument& arg : args) {
 
                        if (arg.AValue.IsObjectType<Dictionary>()) {
-                               Log(LogWarning, "PluginUtility", "Tried to use dictionary in argument");
+                               Log(LogWarning, "PluginUtility")
+                                   << "Tried to use dictionary in argument '" << arg.Key << "'.";
                                continue;
                        } else if (arg.AValue.IsObjectType<Array>()) {
                                bool first = true;
                                Array::Ptr arr = static_cast<Array::Ptr>(arg.AValue);
 
                                ObjectLock olock(arr);
-                               BOOST_FOREACH(const Value& value, arr) {
+                               for (const Value& value : arr) {
                                        bool add_key;
 
                                        if (first) {