1 /******************************************************************************
3 * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License *
7 * as published by the Free Software Foundation; either version 2 *
8 * of the License, or (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software Foundation *
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ******************************************************************************/
20 #include "config/expression.hpp"
21 #include "config/configitem.hpp"
22 #include "config/configcompiler.hpp"
23 #include "config/vmops.hpp"
24 #include "base/array.hpp"
25 #include "base/json.hpp"
26 #include "base/object.hpp"
27 #include "base/logger.hpp"
28 #include "base/exception.hpp"
29 #include "base/scriptglobal.hpp"
30 #include "base/loader.hpp"
31 #include "base/reference.hpp"
32 #include <boost/exception_ptr.hpp>
33 #include <boost/exception/errinfo_nested_exception.hpp>
35 using namespace icinga;
37 boost::signals2::signal<void (ScriptFrame&, ScriptError *ex, const DebugInfo&)> Expression::OnBreakpoint;
38 boost::thread_specific_ptr<bool> l_InBreakpointHandler;
40 Expression::~Expression()
43 void Expression::ScriptBreakpoint(ScriptFrame& frame, ScriptError *ex, const DebugInfo& di)
45 bool *inHandler = l_InBreakpointHandler.get();
46 if (!inHandler || !*inHandler) {
47 inHandler = new bool(true);
48 l_InBreakpointHandler.reset(inHandler);
49 OnBreakpoint(frame, ex, di);
54 ExpressionResult Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) const
58 /* std::ostringstream msgbuf;
59 ShowCodeLocation(msgbuf, GetDebugInfo(), false);
60 Log(LogDebug, "Expression")
61 << "Executing:\n" << msgbuf.str();*/
64 frame.IncreaseStackDepth();
65 ExpressionResult result = DoEvaluate(frame, dhint);
66 frame.DecreaseStackDepth();
68 } catch (ScriptError& ex) {
69 frame.DecreaseStackDepth();
71 ScriptBreakpoint(frame, &ex, GetDebugInfo());
73 } catch (const std::exception& ex) {
74 frame.DecreaseStackDepth();
76 BOOST_THROW_EXCEPTION(ScriptError("Error while evaluating expression: " + String(ex.what()), GetDebugInfo())
77 << boost::errinfo_nested_exception(boost::current_exception()));
80 frame.DecreaseStackDepth();
83 bool Expression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
88 const DebugInfo& Expression::GetDebugInfo() const
90 static DebugInfo debugInfo;
94 std::unique_ptr<Expression> icinga::MakeIndexer(ScopeSpecifier scopeSpec, const String& index)
96 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
97 return std::unique_ptr<Expression>(new IndexerExpression(std::move(scope), MakeLiteral(index)));
100 void DictExpression::MakeInline()
105 LiteralExpression::LiteralExpression(Value value)
106 : m_Value(std::move(value))
109 ExpressionResult LiteralExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
114 const DebugInfo& DebuggableExpression::GetDebugInfo() const
119 ExpressionResult VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
123 if (frame.Locals && frame.Locals->Get(m_Variable, &value))
125 else if (frame.Self.IsObject() && frame.Locals != frame.Self.Get<Object::Ptr>() && frame.Self.Get<Object::Ptr>()->GetOwnField(m_Variable, &value))
127 else if (VMOps::FindVarImport(frame, m_Variable, &value, m_DebugInfo))
130 return ScriptGlobal::Get(m_Variable);
133 bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
137 if (frame.Locals && frame.Locals->Contains(m_Variable)) {
138 *parent = frame.Locals;
142 } else if (frame.Self.IsObject() && frame.Locals != frame.Self.Get<Object::Ptr>() && frame.Self.Get<Object::Ptr>()->HasOwnField(m_Variable)) {
143 *parent = frame.Self;
146 *dhint = new DebugHint((*dhint)->GetChild(m_Variable));
147 } else if (VMOps::FindVarImportRef(frame, m_Variable, parent, m_DebugInfo)) {
149 } else if (ScriptGlobal::Exists(m_Variable)) {
150 *parent = ScriptGlobal::GetGlobals();
155 *parent = frame.Self;
160 ExpressionResult RefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
165 if (!m_Operand->GetReference(frame, false, &parent, &index, &dhint))
166 BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression.", m_DebugInfo));
168 if (!parent.IsObject())
169 BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression because parent is not an object.", m_DebugInfo));
171 return new Reference(parent, index);
174 ExpressionResult DerefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
176 ExpressionResult operand = m_Operand->Evaluate(frame);
177 CHECK_RESULT(operand);
179 Object::Ptr obj = operand.GetValue();
180 Reference::Ptr ref = dynamic_pointer_cast<Reference>(obj);
183 BOOST_THROW_EXCEPTION(ScriptError("Invalid reference specified.", GetDebugInfo()));
188 bool DerefExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
190 ExpressionResult operand = m_Operand->Evaluate(frame);
191 if (operand.GetCode() != ResultOK)
194 Reference::Ptr ref = operand.GetValue();
196 *parent = ref->GetParent();
197 *index = ref->GetIndex();
201 ExpressionResult NegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
203 ExpressionResult operand = m_Operand->Evaluate(frame);
204 CHECK_RESULT(operand);
206 return ~(long)operand.GetValue();
209 ExpressionResult LogicalNegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
211 ExpressionResult operand = m_Operand->Evaluate(frame);
212 CHECK_RESULT(operand);
214 return !operand.GetValue().ToBool();
217 ExpressionResult AddExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
219 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
220 CHECK_RESULT(operand1);
222 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
223 CHECK_RESULT(operand2);
225 return operand1.GetValue() + operand2.GetValue();
228 ExpressionResult SubtractExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
230 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
231 CHECK_RESULT(operand1);
233 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
234 CHECK_RESULT(operand2);
236 return operand1.GetValue() - operand2.GetValue();
239 ExpressionResult MultiplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
241 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
242 CHECK_RESULT(operand1);
244 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
245 CHECK_RESULT(operand2);
247 return operand1.GetValue() * operand2.GetValue();
250 ExpressionResult DivideExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
252 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
253 CHECK_RESULT(operand1);
255 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
256 CHECK_RESULT(operand2);
258 return operand1.GetValue() / operand2.GetValue();
261 ExpressionResult ModuloExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
263 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
264 CHECK_RESULT(operand1);
266 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
267 CHECK_RESULT(operand2);
269 return operand1.GetValue() % operand2.GetValue();
272 ExpressionResult XorExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
274 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
275 CHECK_RESULT(operand1);
277 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
278 CHECK_RESULT(operand2);
280 return operand1.GetValue() ^ operand2.GetValue();
283 ExpressionResult BinaryAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
285 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
286 CHECK_RESULT(operand1);
288 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
289 CHECK_RESULT(operand2);
291 return operand1.GetValue() & operand2.GetValue();
294 ExpressionResult BinaryOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
296 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
297 CHECK_RESULT(operand1);
299 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
300 CHECK_RESULT(operand2);
302 return operand1.GetValue() | operand2.GetValue();
305 ExpressionResult ShiftLeftExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
307 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
308 CHECK_RESULT(operand1);
310 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
311 CHECK_RESULT(operand2);
313 return operand1.GetValue() << operand2.GetValue();
316 ExpressionResult ShiftRightExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
318 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
319 CHECK_RESULT(operand1);
321 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
322 CHECK_RESULT(operand2);
324 return operand1.GetValue() >> operand2.GetValue();
327 ExpressionResult EqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
329 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
330 CHECK_RESULT(operand1);
332 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
333 CHECK_RESULT(operand2);
335 return operand1.GetValue() == operand2.GetValue();
338 ExpressionResult NotEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
340 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
341 CHECK_RESULT(operand1);
343 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
344 CHECK_RESULT(operand2);
346 return operand1.GetValue() != operand2.GetValue();
349 ExpressionResult LessThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
351 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
352 CHECK_RESULT(operand1);
354 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
355 CHECK_RESULT(operand2);
357 return operand1.GetValue() < operand2.GetValue();
360 ExpressionResult GreaterThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
362 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
363 CHECK_RESULT(operand1);
365 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
366 CHECK_RESULT(operand2);
368 return operand1.GetValue() > operand2.GetValue();
371 ExpressionResult LessThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
373 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
374 CHECK_RESULT(operand1);
376 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
377 CHECK_RESULT(operand2);
379 return operand1.GetValue() <= operand2.GetValue();
382 ExpressionResult GreaterThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
384 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
385 CHECK_RESULT(operand1);
387 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
388 CHECK_RESULT(operand2);
390 return operand1.GetValue() >= operand2.GetValue();
393 ExpressionResult InExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
395 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
396 CHECK_RESULT(operand2);
398 if (operand2.GetValue().IsEmpty())
400 else if (!operand2.GetValue().IsObjectType<Array>())
401 BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(operand2.GetValue()), m_DebugInfo));
403 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
404 CHECK_RESULT(operand1)
406 Array::Ptr arr = operand2.GetValue();
407 return arr->Contains(operand1.GetValue());
410 ExpressionResult NotInExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
412 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
413 CHECK_RESULT(operand2);
415 if (operand2.GetValue().IsEmpty())
417 else if (!operand2.GetValue().IsObjectType<Array>())
418 BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(operand2.GetValue()), m_DebugInfo));
420 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
421 CHECK_RESULT(operand1);
423 Array::Ptr arr = operand2.GetValue();
424 return !arr->Contains(operand1.GetValue());
427 ExpressionResult LogicalAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
429 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
430 CHECK_RESULT(operand1);
432 if (!operand1.GetValue().ToBool())
435 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
436 CHECK_RESULT(operand2);
438 return operand2.GetValue();
442 ExpressionResult LogicalOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
444 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
445 CHECK_RESULT(operand1);
447 if (operand1.GetValue().ToBool())
450 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
451 CHECK_RESULT(operand2);
453 return operand2.GetValue();
457 ExpressionResult FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
462 if (m_FName->GetReference(frame, false, &self, &index))
463 vfunc = VMOps::GetField(self, index, frame.Sandboxed, m_DebugInfo);
465 ExpressionResult vfuncres = m_FName->Evaluate(frame);
466 CHECK_RESULT(vfuncres);
468 vfunc = vfuncres.GetValue();
471 if (vfunc.IsObjectType<Type>()) {
472 std::vector<Value> arguments;
473 arguments.reserve(m_Args.size());
474 for (const auto& arg : m_Args) {
475 ExpressionResult argres = arg->Evaluate(frame);
476 CHECK_RESULT(argres);
478 arguments.push_back(argres.GetValue());
481 return VMOps::ConstructorCall(vfunc, arguments, m_DebugInfo);
484 if (!vfunc.IsObjectType<Function>())
485 BOOST_THROW_EXCEPTION(ScriptError("Argument is not a callable object.", m_DebugInfo));
487 Function::Ptr func = vfunc;
489 if (!func->IsSideEffectFree() && frame.Sandboxed)
490 BOOST_THROW_EXCEPTION(ScriptError("Function is not marked as safe for sandbox mode.", m_DebugInfo));
492 std::vector<Value> arguments;
493 arguments.reserve(m_Args.size());
494 for (const auto& arg : m_Args) {
495 ExpressionResult argres = arg->Evaluate(frame);
496 CHECK_RESULT(argres);
498 arguments.push_back(argres.GetValue());
501 return VMOps::FunctionCall(frame, self, func, arguments);
504 ExpressionResult ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
507 result.reserve(m_Expressions.size());
509 for (const auto& aexpr : m_Expressions) {
510 ExpressionResult element = aexpr->Evaluate(frame);
511 CHECK_RESULT(element);
513 result.push_back(element.GetValue());
516 return new Array(std::move(result));
519 ExpressionResult DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
525 frame.Self = new Dictionary();
531 for (const auto& aexpr : m_Expressions) {
532 ExpressionResult element = aexpr->Evaluate(frame, m_Inline ? dhint : nullptr);
533 CHECK_RESULT(element);
534 result = element.GetValue();
538 std::swap(self, frame.Self);
545 std::swap(self, frame.Self);
550 ExpressionResult GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
552 if (m_ScopeSpec == ScopeLocal)
554 else if (m_ScopeSpec == ScopeThis)
556 else if (m_ScopeSpec == ScopeGlobal)
557 return ScriptGlobal::GetGlobals();
559 VERIFY(!"Invalid scope.");
562 ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
565 BOOST_THROW_EXCEPTION(ScriptError("Assignments are not allowed in sandbox mode.", m_DebugInfo));
567 DebugHint *psdhint = dhint;
572 if (!m_Operand1->GetReference(frame, true, &parent, &index, &psdhint))
573 BOOST_THROW_EXCEPTION(ScriptError("Expression cannot be assigned to.", m_DebugInfo));
575 ExpressionResult operand2 = m_Operand2->Evaluate(frame, dhint);
576 CHECK_RESULT(operand2);
578 if (m_Op != OpSetLiteral) {
579 Value object = VMOps::GetField(parent, index, frame.Sandboxed, m_DebugInfo);
583 operand2 = object + operand2;
586 operand2 = object - operand2;
589 operand2 = object * operand2;
592 operand2 = object / operand2;
595 operand2 = object % operand2;
598 operand2 = object ^ operand2;
601 operand2 = object & operand2;
604 operand2 = object | operand2;
607 VERIFY(!"Invalid opcode.");
611 VMOps::SetField(parent, index, operand2.GetValue(), m_DebugInfo);
614 psdhint->AddMessage("=", m_DebugInfo);
616 if (psdhint != dhint)
623 ExpressionResult ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
625 ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
626 CHECK_RESULT(condition);
628 if (condition.GetValue().ToBool())
629 return m_TrueBranch->Evaluate(frame, dhint);
630 else if (m_FalseBranch)
631 return m_FalseBranch->Evaluate(frame, dhint);
636 ExpressionResult WhileExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
639 BOOST_THROW_EXCEPTION(ScriptError("While loops are not allowed in sandbox mode.", m_DebugInfo));
642 ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
643 CHECK_RESULT(condition);
645 if (!condition.GetValue().ToBool())
648 ExpressionResult loop_body = m_LoopBody->Evaluate(frame, dhint);
649 CHECK_RESULT_LOOP(loop_body);
655 ExpressionResult ReturnExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
657 ExpressionResult operand = m_Operand->Evaluate(frame);
658 CHECK_RESULT(operand);
660 return ExpressionResult(operand.GetValue(), ResultReturn);
663 ExpressionResult BreakExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
665 return ExpressionResult(Empty, ResultBreak);
668 ExpressionResult ContinueExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
670 return ExpressionResult(Empty, ResultContinue);
673 ExpressionResult IndexerExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
675 ExpressionResult operand1 = m_Operand1->Evaluate(frame, dhint);
676 CHECK_RESULT(operand1);
678 ExpressionResult operand2 = m_Operand2->Evaluate(frame, dhint);
679 CHECK_RESULT(operand2);
681 return VMOps::GetField(operand1.GetValue(), operand2.GetValue(), frame.Sandboxed, m_DebugInfo);
684 bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
688 DebugHint *psdhint = nullptr;
689 bool free_psd = false;
697 if (m_Operand1->GetReference(frame, init_dict, &vparent, &vindex, &psdhint)) {
699 Value old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
701 if (old_value.IsEmpty() && !old_value.IsString())
702 VMOps::SetField(vparent, vindex, new Dictionary(), m_Operand1->GetDebugInfo());
705 *parent = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_DebugInfo);
708 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
709 *parent = operand1.GetValue();
712 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
713 *index = operand2.GetValue();
717 *dhint = new DebugHint(psdhint->GetChild(*index));
728 void icinga::BindToScope(std::unique_ptr<Expression>& expr, ScopeSpecifier scopeSpec)
730 auto *dexpr = dynamic_cast<DictExpression *>(expr.get());
733 for (auto& expr : dexpr->m_Expressions)
734 BindToScope(expr, scopeSpec);
739 auto *aexpr = dynamic_cast<SetExpression *>(expr.get());
742 BindToScope(aexpr->m_Operand1, scopeSpec);
747 auto *iexpr = dynamic_cast<IndexerExpression *>(expr.get());
750 BindToScope(iexpr->m_Operand1, scopeSpec);
754 auto *lexpr = dynamic_cast<LiteralExpression *>(expr.get());
756 if (lexpr && lexpr->GetValue().IsString()) {
757 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
758 expr.reset(new IndexerExpression(std::move(scope), std::move(expr), lexpr->GetDebugInfo()));
761 auto *vexpr = dynamic_cast<VariableExpression *>(expr.get());
764 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
765 expr.reset(new IndexerExpression(std::move(scope), MakeLiteral(vexpr->GetVariable()), vexpr->GetDebugInfo()));
769 ExpressionResult ThrowExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
771 ExpressionResult messageres = m_Message->Evaluate(frame);
772 CHECK_RESULT(messageres);
773 Value message = messageres.GetValue();
774 BOOST_THROW_EXCEPTION(ScriptError(message, m_DebugInfo, m_IncompleteExpr));
777 ExpressionResult ImportExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
780 BOOST_THROW_EXCEPTION(ScriptError("Imports are not allowed in sandbox mode.", m_DebugInfo));
782 String type = VMOps::GetField(frame.Self, "type", frame.Sandboxed, m_DebugInfo);
783 ExpressionResult nameres = m_Name->Evaluate(frame);
784 CHECK_RESULT(nameres);
785 Value name = nameres.GetValue();
787 if (!name.IsString())
788 BOOST_THROW_EXCEPTION(ScriptError("Template/object name must be a string", m_DebugInfo));
790 ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(Type::GetByName(type), name);
793 BOOST_THROW_EXCEPTION(ScriptError("Import references unknown template: '" + name + "'", m_DebugInfo));
795 Dictionary::Ptr scope = item->GetScope();
798 scope->CopyTo(frame.Locals);
800 ExpressionResult result = item->GetExpression()->Evaluate(frame, dhint);
801 CHECK_RESULT(result);
806 ExpressionResult ImportDefaultTemplatesExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
809 BOOST_THROW_EXCEPTION(ScriptError("Imports are not allowed in sandbox mode.", m_DebugInfo));
811 String type = VMOps::GetField(frame.Self, "type", frame.Sandboxed, m_DebugInfo);
812 Type::Ptr ptype = Type::GetByName(type);
814 for (const ConfigItem::Ptr& item : ConfigItem::GetDefaultTemplates(ptype)) {
815 Dictionary::Ptr scope = item->GetScope();
818 scope->CopyTo(frame.Locals);
820 ExpressionResult result = item->GetExpression()->Evaluate(frame, dhint);
821 CHECK_RESULT(result);
827 ExpressionResult FunctionExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
829 return VMOps::NewFunction(frame, m_Name, m_Args, m_ClosedVars, m_Expression);
832 ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
835 BOOST_THROW_EXCEPTION(ScriptError("Apply rules are not allowed in sandbox mode.", m_DebugInfo));
837 ExpressionResult nameres = m_Name->Evaluate(frame);
838 CHECK_RESULT(nameres);
840 return VMOps::NewApply(frame, m_Type, m_Target, nameres.GetValue(), m_Filter,
841 m_Package, m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_IgnoreOnError, m_Expression, m_DebugInfo);
844 ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
847 BOOST_THROW_EXCEPTION(ScriptError("Object definitions are not allowed in sandbox mode.", m_DebugInfo));
849 ExpressionResult typeres = m_Type->Evaluate(frame, dhint);
850 CHECK_RESULT(typeres);
851 Type::Ptr type = typeres.GetValue();
856 ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
857 CHECK_RESULT(nameres);
859 name = nameres.GetValue();
862 return VMOps::NewObject(frame, m_Abstract, type, name, m_Filter, m_Zone,
863 m_Package, m_DefaultTmpl, m_IgnoreOnError, m_ClosedVars, m_Expression, m_DebugInfo);
866 ExpressionResult ForExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
869 BOOST_THROW_EXCEPTION(ScriptError("For loops are not allowed in sandbox mode.", m_DebugInfo));
871 ExpressionResult valueres = m_Value->Evaluate(frame, dhint);
872 CHECK_RESULT(valueres);
874 return VMOps::For(frame, m_FKVar, m_FVVar, valueres.GetValue(), m_Expression, m_DebugInfo);
877 ExpressionResult LibraryExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
880 BOOST_THROW_EXCEPTION(ScriptError("Loading libraries is not allowed in sandbox mode.", m_DebugInfo));
882 ExpressionResult libres = m_Operand->Evaluate(frame, dhint);
883 CHECK_RESULT(libres);
885 Log(LogNotice, "config")
886 << "Ignoring explicit load request for library \"" << libres << "\".";
891 ExpressionResult IncludeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
894 BOOST_THROW_EXCEPTION(ScriptError("Includes are not allowed in sandbox mode.", m_DebugInfo));
896 std::unique_ptr<Expression> expr;
897 String name, path, pattern;
902 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
903 CHECK_RESULT(pathres);
904 path = pathres.GetValue();
907 expr = ConfigCompiler::HandleInclude(m_RelativeBase, path, m_SearchIncludes, m_Zone, m_Package, m_DebugInfo);
910 case IncludeRecursive:
912 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
913 CHECK_RESULT(pathres);
914 path = pathres.GetValue();
918 ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
919 CHECK_RESULT(patternres);
920 pattern = patternres.GetValue();
923 expr = ConfigCompiler::HandleIncludeRecursive(m_RelativeBase, path, pattern, m_Zone, m_Package, m_DebugInfo);
928 ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
929 CHECK_RESULT(nameres);
930 name = nameres.GetValue();
934 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
935 CHECK_RESULT(pathres);
936 path = pathres.GetValue();
940 ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
941 CHECK_RESULT(patternres);
942 pattern = patternres.GetValue();
945 expr = ConfigCompiler::HandleIncludeZones(m_RelativeBase, name, path, pattern, m_Package, m_DebugInfo);
949 ExpressionResult res(Empty);
952 res = expr->Evaluate(frame, dhint);
953 } catch (const std::exception&) {
960 ExpressionResult BreakpointExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
962 ScriptBreakpoint(frame, nullptr, GetDebugInfo());
967 ExpressionResult UsingExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
970 BOOST_THROW_EXCEPTION(ScriptError("Using directives are not allowed in sandbox mode.", m_DebugInfo));
972 ExpressionResult importres = m_Name->Evaluate(frame);
973 CHECK_RESULT(importres);
974 Value import = importres.GetValue();
976 if (!import.IsObjectType<Dictionary>())
977 BOOST_THROW_EXCEPTION(ScriptError("The parameter must resolve to an object of type 'Dictionary'", m_DebugInfo));
979 ScriptFrame::AddImport(import);
984 ExpressionResult TryExceptExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
987 ExpressionResult tryResult = m_TryBody->Evaluate(frame, dhint);
988 CHECK_RESULT(tryResult);
989 } catch (const std::exception&) {
990 ExpressionResult exceptResult = m_ExceptBody->Evaluate(frame, dhint);
991 CHECK_RESULT(exceptResult);