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
12namespace Twig\Extension;
13
14use Twig\NodeVisitor\SandboxNodeVisitor;
15use Twig\Sandbox\SecurityNotAllowedMethodError;
16use Twig\Sandbox\SecurityNotAllowedPropertyError;
17use Twig\Sandbox\SecurityPolicyInterface;
18use Twig\Source;
19use Twig\TokenParser\SandboxTokenParser;
20
21final class SandboxExtension extends AbstractExtension
22{
23    private $sandboxedGlobally;
24    private $sandboxed;
25    private $policy;
26
27    public function __construct(SecurityPolicyInterface $policy, $sandboxed = false)
28    {
29        $this->policy = $policy;
30        $this->sandboxedGlobally = $sandboxed;
31    }
32
33    public function getTokenParsers()
34    {
35        return [new SandboxTokenParser()];
36    }
37
38    public function getNodeVisitors()
39    {
40        return [new SandboxNodeVisitor()];
41    }
42
43    public function enableSandbox()
44    {
45        $this->sandboxed = true;
46    }
47
48    public function disableSandbox()
49    {
50        $this->sandboxed = false;
51    }
52
53    public function isSandboxed()
54    {
55        return $this->sandboxedGlobally || $this->sandboxed;
56    }
57
58    public function isSandboxedGlobally()
59    {
60        return $this->sandboxedGlobally;
61    }
62
63    public function setSecurityPolicy(SecurityPolicyInterface $policy)
64    {
65        $this->policy = $policy;
66    }
67
68    public function getSecurityPolicy()
69    {
70        return $this->policy;
71    }
72
73    public function checkSecurity($tags, $filters, $functions)
74    {
75        if ($this->isSandboxed()) {
76            $this->policy->checkSecurity($tags, $filters, $functions);
77        }
78    }
79
80    public function checkMethodAllowed($obj, $method, int $lineno = -1, Source $source = null)
81    {
82        if ($this->isSandboxed()) {
83            try {
84                $this->policy->checkMethodAllowed($obj, $method);
85            } catch (SecurityNotAllowedMethodError $e) {
86                $e->setSourceContext($source);
87                $e->setTemplateLine($lineno);
88
89                throw $e;
90            }
91        }
92    }
93
94    public function checkPropertyAllowed($obj, $property, int $lineno = -1, Source $source = null)
95    {
96        if ($this->isSandboxed()) {
97            try {
98                $this->policy->checkPropertyAllowed($obj, $property);
99            } catch (SecurityNotAllowedPropertyError $e) {
100                $e->setSourceContext($source);
101                $e->setTemplateLine($lineno);
102
103                throw $e;
104            }
105        }
106    }
107
108    public function ensureToStringAllowed($obj, int $lineno = -1, Source $source = null)
109    {
110        if ($this->isSandboxed() && \is_object($obj) && method_exists($obj, '__toString')) {
111            try {
112                $this->policy->checkMethodAllowed($obj, '__toString');
113            } catch (SecurityNotAllowedMethodError $e) {
114                $e->setSourceContext($source);
115                $e->setTemplateLine($lineno);
116
117                throw $e;
118            }
119        }
120
121        return $obj;
122    }
123}
124
125class_alias('Twig\Extension\SandboxExtension', 'Twig_Extension_Sandbox');
126