git subrepo commit (merge) mailcow/src/mailcow-dockerized

subrepo: subdir:   "mailcow/src/mailcow-dockerized"
  merged:   "32243e56"
upstream: origin:   "https://github.com/mailcow/mailcow-dockerized.git"
  branch:   "master"
  commit:   "e2b4b6f6"
git-subrepo: version:  "0.4.3"
  origin:   "???"
  commit:   "???"
Change-Id: I51e2016ef5ab88a8b0bdc08551b18f48ceef0aa5
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php
new file mode 100644
index 0000000..1446cee
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php
@@ -0,0 +1,136 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Twig\NodeVisitor;
+
+use Twig\Environment;
+use Twig\Node\CheckSecurityCallNode;
+use Twig\Node\CheckSecurityNode;
+use Twig\Node\CheckToStringNode;
+use Twig\Node\Expression\Binary\ConcatBinary;
+use Twig\Node\Expression\Binary\RangeBinary;
+use Twig\Node\Expression\FilterExpression;
+use Twig\Node\Expression\FunctionExpression;
+use Twig\Node\Expression\GetAttrExpression;
+use Twig\Node\Expression\NameExpression;
+use Twig\Node\ModuleNode;
+use Twig\Node\Node;
+use Twig\Node\PrintNode;
+use Twig\Node\SetNode;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @internal
+ */
+final class SandboxNodeVisitor implements NodeVisitorInterface
+{
+    private $inAModule = false;
+    private $tags;
+    private $filters;
+    private $functions;
+    private $needsToStringWrap = false;
+
+    public function enterNode(Node $node, Environment $env): Node
+    {
+        if ($node instanceof ModuleNode) {
+            $this->inAModule = true;
+            $this->tags = [];
+            $this->filters = [];
+            $this->functions = [];
+
+            return $node;
+        } elseif ($this->inAModule) {
+            // look for tags
+            if ($node->getNodeTag() && !isset($this->tags[$node->getNodeTag()])) {
+                $this->tags[$node->getNodeTag()] = $node;
+            }
+
+            // look for filters
+            if ($node instanceof FilterExpression && !isset($this->filters[$node->getNode('filter')->getAttribute('value')])) {
+                $this->filters[$node->getNode('filter')->getAttribute('value')] = $node;
+            }
+
+            // look for functions
+            if ($node instanceof FunctionExpression && !isset($this->functions[$node->getAttribute('name')])) {
+                $this->functions[$node->getAttribute('name')] = $node;
+            }
+
+            // the .. operator is equivalent to the range() function
+            if ($node instanceof RangeBinary && !isset($this->functions['range'])) {
+                $this->functions['range'] = $node;
+            }
+
+            if ($node instanceof PrintNode) {
+                $this->needsToStringWrap = true;
+                $this->wrapNode($node, 'expr');
+            }
+
+            if ($node instanceof SetNode && !$node->getAttribute('capture')) {
+                $this->needsToStringWrap = true;
+            }
+
+            // wrap outer nodes that can implicitly call __toString()
+            if ($this->needsToStringWrap) {
+                if ($node instanceof ConcatBinary) {
+                    $this->wrapNode($node, 'left');
+                    $this->wrapNode($node, 'right');
+                }
+                if ($node instanceof FilterExpression) {
+                    $this->wrapNode($node, 'node');
+                    $this->wrapArrayNode($node, 'arguments');
+                }
+                if ($node instanceof FunctionExpression) {
+                    $this->wrapArrayNode($node, 'arguments');
+                }
+            }
+        }
+
+        return $node;
+    }
+
+    public function leaveNode(Node $node, Environment $env): ?Node
+    {
+        if ($node instanceof ModuleNode) {
+            $this->inAModule = false;
+
+            $node->setNode('constructor_end', new Node([new CheckSecurityCallNode(), $node->getNode('constructor_end')]));
+            $node->setNode('class_end', new Node([new CheckSecurityNode($this->filters, $this->tags, $this->functions), $node->getNode('class_end')]));
+        } elseif ($this->inAModule) {
+            if ($node instanceof PrintNode || $node instanceof SetNode) {
+                $this->needsToStringWrap = false;
+            }
+        }
+
+        return $node;
+    }
+
+    private function wrapNode(Node $node, string $name): void
+    {
+        $expr = $node->getNode($name);
+        if ($expr instanceof NameExpression || $expr instanceof GetAttrExpression) {
+            $node->setNode($name, new CheckToStringNode($expr));
+        }
+    }
+
+    private function wrapArrayNode(Node $node, string $name): void
+    {
+        $args = $node->getNode($name);
+        foreach ($args as $name => $_) {
+            $this->wrapNode($args, $name);
+        }
+    }
+
+    public function getPriority(): int
+    {
+        return 0;
+    }
+}