-/******************************************************************************
- * Icinga 2 *
- * Copyright (C) 2012-2018 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 *
- * as published by the Free Software Foundation; either version 2 *
- * of the License, or (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software Foundation *
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
- ******************************************************************************/
+/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
#include "config/expression.hpp"
#include "config/configitem.hpp"
#include "base/exception.hpp"
#include "base/scriptglobal.hpp"
#include "base/loader.hpp"
+#include "base/reference.hpp"
+#include "base/namespace.hpp"
#include <boost/exception_ptr.hpp>
#include <boost/exception/errinfo_nested_exception.hpp>
return m_DebugInfo;
}
+VariableExpression::VariableExpression(String variable, std::vector<std::shared_ptr<Expression> > imports, const DebugInfo& debugInfo)
+ : DebuggableExpression(debugInfo), m_Variable(std::move(variable)), m_Imports(std::move(imports))
+{
+ m_Imports.push_back(MakeIndexer(ScopeGlobal, "System"));
+ m_Imports.push_back(std::unique_ptr<Expression>(new IndexerExpression(MakeIndexer(ScopeGlobal, "System"), MakeLiteral("Configuration"))));
+ m_Imports.push_back(MakeIndexer(ScopeGlobal, "Types"));
+ m_Imports.push_back(MakeIndexer(ScopeGlobal, "Icinga"));
+}
+
ExpressionResult VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
Value value;
return value;
else if (frame.Self.IsObject() && frame.Locals != frame.Self.Get<Object::Ptr>() && frame.Self.Get<Object::Ptr>()->GetOwnField(m_Variable, &value))
return value;
- else if (VMOps::FindVarImport(frame, m_Variable, &value, m_DebugInfo))
+ else if (VMOps::FindVarImport(frame, m_Imports, m_Variable, &value, m_DebugInfo))
return value;
else
return ScriptGlobal::Get(m_Variable);
if (dhint && *dhint)
*dhint = new DebugHint((*dhint)->GetChild(m_Variable));
- } else if (VMOps::FindVarImportRef(frame, m_Variable, parent, m_DebugInfo)) {
+ } else if (VMOps::FindVarImportRef(frame, m_Imports, m_Variable, parent, m_DebugInfo)) {
return true;
} else if (ScriptGlobal::Exists(m_Variable)) {
*parent = ScriptGlobal::GetGlobals();
return true;
}
+ExpressionResult RefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
+{
+ Value parent;
+ String index;
+
+ if (!m_Operand->GetReference(frame, false, &parent, &index, &dhint))
+ BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression.", m_DebugInfo));
+
+ if (!parent.IsObject())
+ BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression because parent is not an object.", m_DebugInfo));
+
+ return new Reference(parent, index);
+}
+
+ExpressionResult DerefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
+{
+ ExpressionResult operand = m_Operand->Evaluate(frame);
+ CHECK_RESULT(operand);
+
+ Object::Ptr obj = operand.GetValue();
+ Reference::Ptr ref = dynamic_pointer_cast<Reference>(obj);
+
+ if (!ref)
+ BOOST_THROW_EXCEPTION(ScriptError("Invalid reference specified.", GetDebugInfo()));
+
+ return ref->Get();
+}
+
+bool DerefExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
+{
+ ExpressionResult operand = m_Operand->Evaluate(frame);
+ if (operand.GetCode() != ResultOK)
+ return false;
+
+ Reference::Ptr ref = operand.GetValue();
+
+ *parent = ref->GetParent();
+ *index = ref->GetIndex();
+ return true;
+}
+
ExpressionResult NegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
ExpressionResult operand = m_Operand->Evaluate(frame);
ExpressionResult ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
- Array::Ptr result = new Array();
- result->Reserve(m_Expressions.size());
+ ArrayData result;
+ result.reserve(m_Expressions.size());
for (const auto& aexpr : m_Expressions) {
ExpressionResult element = aexpr->Evaluate(frame);
CHECK_RESULT(element);
- result->Add(element.GetValue());
+ result.push_back(element.GetValue());
}
- return result;
+ return new Array(std::move(result));
}
ExpressionResult DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
}
}
- VMOps::SetField(parent, index, operand2.GetValue(), m_DebugInfo);
+ VMOps::SetField(parent, index, operand2.GetValue(), m_OverrideFrozen, m_DebugInfo);
if (psdhint) {
psdhint->AddMessage("=", m_DebugInfo);
return Empty;
}
+void SetExpression::SetOverrideFrozen()
+{
+ m_OverrideFrozen = true;
+}
+
+ExpressionResult SetConstExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
+{
+ auto globals = ScriptGlobal::GetGlobals();
+
+ auto attr = globals->GetAttribute(m_Name);
+
+ if (dynamic_pointer_cast<ConstEmbeddedNamespaceValue>(attr)) {
+ std::ostringstream msgbuf;
+ msgbuf << "Value for constant '" << m_Name << "' was modified. This behaviour is deprecated.\n";
+ ShowCodeLocation(msgbuf, GetDebugInfo(), false);
+ Log(LogWarning, msgbuf.str());
+ }
+
+ ExpressionResult operandres = m_Operand->Evaluate(frame);
+ CHECK_RESULT(operandres);
+ Value operand = operandres.GetValue();
+
+ globals->SetAttribute(m_Name, std::make_shared<ConstEmbeddedNamespaceValue>(operand));
+
+ return Empty;
+}
+
ExpressionResult ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
if (m_Operand1->GetReference(frame, init_dict, &vparent, &vindex, &psdhint)) {
if (init_dict) {
- Value old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
+ Value old_value;
+ bool has_field = true;
+
+ if (vparent.IsObject()) {
+ Object::Ptr oparent = vparent;
+ has_field = oparent->HasOwnField(vindex);
+ }
+
+ if (has_field)
+ old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
if (old_value.IsEmpty() && !old_value.IsString())
- VMOps::SetField(vparent, vindex, new Dictionary(), m_Operand1->GetDebugInfo());
+ VMOps::SetField(vparent, vindex, new Dictionary(), m_OverrideFrozen, m_Operand1->GetDebugInfo());
}
*parent = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_DebugInfo);
return true;
}
+void IndexerExpression::SetOverrideFrozen()
+{
+ m_OverrideFrozen = true;
+}
+
void icinga::BindToScope(std::unique_ptr<Expression>& expr, ScopeSpecifier scopeSpec)
{
auto *dexpr = dynamic_cast<DictExpression *>(expr.get());
m_Package, m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_IgnoreOnError, m_Expression, m_DebugInfo);
}
+ExpressionResult NamespaceExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
+{
+ Namespace::Ptr ns = new Namespace(new ConstNamespaceBehavior());
+
+ ScriptFrame innerFrame(true, ns);
+ ExpressionResult result = m_Expression->Evaluate(innerFrame);
+ CHECK_RESULT(result);
+
+ return ns;
+}
+
ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
if (frame.Sandboxed)
return Empty;
}
-ExpressionResult UsingExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
-{
- if (frame.Sandboxed)
- BOOST_THROW_EXCEPTION(ScriptError("Using directives are not allowed in sandbox mode.", m_DebugInfo));
-
- ExpressionResult importres = m_Name->Evaluate(frame);
- CHECK_RESULT(importres);
- Value import = importres.GetValue();
-
- if (!import.IsObjectType<Dictionary>())
- BOOST_THROW_EXCEPTION(ScriptError("The parameter must resolve to an object of type 'Dictionary'", m_DebugInfo));
-
- ScriptFrame::AddImport(import);
-
- return Empty;
-}
-
ExpressionResult TryExceptExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
try {