[ Index ]

PHP Cross Reference of phpBB-3.3.2-deutsch

title

Body

[close]

/vendor/twig/twig/src/NodeVisitor/ -> EscaperNodeVisitor.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of Twig.
   5   *
   6   * (c) Fabien Potencier
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Twig\NodeVisitor;
  13  
  14  use Twig\Environment;
  15  use Twig\Extension\EscaperExtension;
  16  use Twig\Node\AutoEscapeNode;
  17  use Twig\Node\BlockNode;
  18  use Twig\Node\BlockReferenceNode;
  19  use Twig\Node\DoNode;
  20  use Twig\Node\Expression\ConditionalExpression;
  21  use Twig\Node\Expression\ConstantExpression;
  22  use Twig\Node\Expression\FilterExpression;
  23  use Twig\Node\Expression\InlinePrint;
  24  use Twig\Node\ImportNode;
  25  use Twig\Node\ModuleNode;
  26  use Twig\Node\Node;
  27  use Twig\Node\PrintNode;
  28  use Twig\NodeTraverser;
  29  
  30  /**
  31   * @author Fabien Potencier <fabien@symfony.com>
  32   */
  33  final class EscaperNodeVisitor extends AbstractNodeVisitor
  34  {
  35      private $statusStack = [];
  36      private $blocks = [];
  37      private $safeAnalysis;
  38      private $traverser;
  39      private $defaultStrategy = false;
  40      private $safeVars = [];
  41  
  42      public function __construct()
  43      {
  44          $this->safeAnalysis = new SafeAnalysisNodeVisitor();
  45      }
  46  
  47      protected function doEnterNode(Node $node, Environment $env)
  48      {
  49          if ($node instanceof ModuleNode) {
  50              if ($env->hasExtension(EscaperExtension::class) && $defaultStrategy = $env->getExtension(EscaperExtension::class)->getDefaultStrategy($node->getTemplateName())) {
  51                  $this->defaultStrategy = $defaultStrategy;
  52              }
  53              $this->safeVars = [];
  54              $this->blocks = [];
  55          } elseif ($node instanceof AutoEscapeNode) {
  56              $this->statusStack[] = $node->getAttribute('value');
  57          } elseif ($node instanceof BlockNode) {
  58              $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env);
  59          } elseif ($node instanceof ImportNode) {
  60              $this->safeVars[] = $node->getNode('var')->getAttribute('name');
  61          }
  62  
  63          return $node;
  64      }
  65  
  66      protected function doLeaveNode(Node $node, Environment $env)
  67      {
  68          if ($node instanceof ModuleNode) {
  69              $this->defaultStrategy = false;
  70              $this->safeVars = [];
  71              $this->blocks = [];
  72          } elseif ($node instanceof FilterExpression) {
  73              return $this->preEscapeFilterNode($node, $env);
  74          } elseif ($node instanceof PrintNode && false !== $type = $this->needEscaping($env)) {
  75              $expression = $node->getNode('expr');
  76              if ($expression instanceof ConditionalExpression && $this->shouldUnwrapConditional($expression, $env, $type)) {
  77                  return new DoNode($this->unwrapConditional($expression, $env, $type), $expression->getTemplateLine());
  78              }
  79  
  80              return $this->escapePrintNode($node, $env, $type);
  81          }
  82  
  83          if ($node instanceof AutoEscapeNode || $node instanceof BlockNode) {
  84              array_pop($this->statusStack);
  85          } elseif ($node instanceof BlockReferenceNode) {
  86              $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env);
  87          }
  88  
  89          return $node;
  90      }
  91  
  92      private function shouldUnwrapConditional(ConditionalExpression $expression, Environment $env, $type)
  93      {
  94          $expr2Safe = $this->isSafeFor($type, $expression->getNode('expr2'), $env);
  95          $expr3Safe = $this->isSafeFor($type, $expression->getNode('expr3'), $env);
  96  
  97          return $expr2Safe !== $expr3Safe;
  98      }
  99  
 100      private function unwrapConditional(ConditionalExpression $expression, Environment $env, $type)
 101      {
 102          // convert "echo a ? b : c" to "a ? echo b : echo c" recursively
 103          $expr2 = $expression->getNode('expr2');
 104          if ($expr2 instanceof ConditionalExpression && $this->shouldUnwrapConditional($expr2, $env, $type)) {
 105              $expr2 = $this->unwrapConditional($expr2, $env, $type);
 106          } else {
 107              $expr2 = $this->escapeInlinePrintNode(new InlinePrint($expr2, $expr2->getTemplateLine()), $env, $type);
 108          }
 109          $expr3 = $expression->getNode('expr3');
 110          if ($expr3 instanceof ConditionalExpression && $this->shouldUnwrapConditional($expr3, $env, $type)) {
 111              $expr3 = $this->unwrapConditional($expr3, $env, $type);
 112          } else {
 113              $expr3 = $this->escapeInlinePrintNode(new InlinePrint($expr3, $expr3->getTemplateLine()), $env, $type);
 114          }
 115  
 116          return new ConditionalExpression($expression->getNode('expr1'), $expr2, $expr3, $expression->getTemplateLine());
 117      }
 118  
 119      private function escapeInlinePrintNode(InlinePrint $node, Environment $env, $type)
 120      {
 121          $expression = $node->getNode('node');
 122  
 123          if ($this->isSafeFor($type, $expression, $env)) {
 124              return $node;
 125          }
 126  
 127          return new InlinePrint($this->getEscaperFilter($type, $expression), $node->getTemplateLine());
 128      }
 129  
 130      private function escapePrintNode(PrintNode $node, Environment $env, $type)
 131      {
 132          if (false === $type) {
 133              return $node;
 134          }
 135  
 136          $expression = $node->getNode('expr');
 137  
 138          if ($this->isSafeFor($type, $expression, $env)) {
 139              return $node;
 140          }
 141  
 142          $class = \get_class($node);
 143  
 144          return new $class($this->getEscaperFilter($type, $expression), $node->getTemplateLine());
 145      }
 146  
 147      private function preEscapeFilterNode(FilterExpression $filter, Environment $env)
 148      {
 149          $name = $filter->getNode('filter')->getAttribute('value');
 150  
 151          $type = $env->getFilter($name)->getPreEscape();
 152          if (null === $type) {
 153              return $filter;
 154          }
 155  
 156          $node = $filter->getNode('node');
 157          if ($this->isSafeFor($type, $node, $env)) {
 158              return $filter;
 159          }
 160  
 161          $filter->setNode('node', $this->getEscaperFilter($type, $node));
 162  
 163          return $filter;
 164      }
 165  
 166      private function isSafeFor($type, Node $expression, $env)
 167      {
 168          $safe = $this->safeAnalysis->getSafe($expression);
 169  
 170          if (null === $safe) {
 171              if (null === $this->traverser) {
 172                  $this->traverser = new NodeTraverser($env, [$this->safeAnalysis]);
 173              }
 174  
 175              $this->safeAnalysis->setSafeVars($this->safeVars);
 176  
 177              $this->traverser->traverse($expression);
 178              $safe = $this->safeAnalysis->getSafe($expression);
 179          }
 180  
 181          return \in_array($type, $safe) || \in_array('all', $safe);
 182      }
 183  
 184      private function needEscaping(Environment $env)
 185      {
 186          if (\count($this->statusStack)) {
 187              return $this->statusStack[\count($this->statusStack) - 1];
 188          }
 189  
 190          return $this->defaultStrategy ? $this->defaultStrategy : false;
 191      }
 192  
 193      private function getEscaperFilter(string $type, Node $node): FilterExpression
 194      {
 195          $line = $node->getTemplateLine();
 196          $name = new ConstantExpression('escape', $line);
 197          $args = new Node([new ConstantExpression((string) $type, $line), new ConstantExpression(null, $line), new ConstantExpression(true, $line)]);
 198  
 199          return new FilterExpression($node, $name, $args, $line);
 200      }
 201  
 202      public function getPriority()
 203      {
 204          return 0;
 205      }
 206  }
 207  
 208  class_alias('Twig\NodeVisitor\EscaperNodeVisitor', 'Twig_NodeVisitor_Escaper');


Generated: Wed Nov 11 20:28:18 2020 Cross-referenced by PHPXref 0.7.1