mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-17 06:53:15 +00:00
initial import
This commit is contained in:
123
lib/classes/Twig/NodeVisitor/Escaper.php
Executable file
123
lib/classes/Twig/NodeVisitor/Escaper.php
Executable file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Twig_NodeVisitor_Escaper implements output escaping.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
|
||||
{
|
||||
protected $statusStack = array();
|
||||
protected $blocks = array();
|
||||
|
||||
protected $safeAnalysis;
|
||||
protected $traverser;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->safeAnalysis = new Twig_NodeVisitor_SafeAnalysis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before child nodes are visited.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to visit
|
||||
* @param Twig_Environment $env The Twig environment instance
|
||||
*
|
||||
* @param Twig_NodeInterface The modified node
|
||||
*/
|
||||
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof Twig_Node_AutoEscape) {
|
||||
$this->statusStack[] = $node->getAttribute('value');
|
||||
} elseif ($node instanceof Twig_Node_Print) {
|
||||
return $this->escapeNode($node, $env, $this->needEscaping($env));
|
||||
} elseif ($node instanceof Twig_Node_Block) {
|
||||
$this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after child nodes are visited.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to visit
|
||||
* @param Twig_Environment $env The Twig environment instance
|
||||
*
|
||||
* @param Twig_NodeInterface The modified node
|
||||
*/
|
||||
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof Twig_Node_AutoEscape || $node instanceof Twig_Node_Block) {
|
||||
array_pop($this->statusStack);
|
||||
} elseif ($node instanceof Twig_Node_BlockReference) {
|
||||
$this->blocks[$node->getAttribute('name')] = $this->needEscaping($env);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
protected function escapeNode(Twig_NodeInterface $node, Twig_Environment $env, $type)
|
||||
{
|
||||
if (false === $type) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
$expression = $node instanceof Twig_Node_Print ? $node->getNode('expr') : $node;
|
||||
|
||||
$safe = $this->safeAnalysis->getSafe($expression);
|
||||
|
||||
if (null === $safe) {
|
||||
if (null === $this->traverser) {
|
||||
$this->traverser = new Twig_NodeTraverser($env, array($this->safeAnalysis));
|
||||
}
|
||||
$this->traverser->traverse($expression);
|
||||
$safe = $this->safeAnalysis->getSafe($expression);
|
||||
}
|
||||
|
||||
if (false !== in_array($type, $safe) || false !== in_array('all', $safe)) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if ($node instanceof Twig_Node_Print) {
|
||||
return new Twig_Node_Print(
|
||||
$this->getEscaperFilter($type, $expression),
|
||||
$node->getLine()
|
||||
);
|
||||
}
|
||||
|
||||
return $this->getEscaperFilter($type, $node);
|
||||
}
|
||||
|
||||
protected function needEscaping(Twig_Environment $env)
|
||||
{
|
||||
if (count($this->statusStack)) {
|
||||
return $this->statusStack[count($this->statusStack) - 1];
|
||||
}
|
||||
|
||||
if ($env->hasExtension('escaper') && $env->getExtension('escaper')->isGlobal()) {
|
||||
return 'html';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getEscaperFilter($type, Twig_NodeInterface $node)
|
||||
{
|
||||
$line = $node->getLine();
|
||||
$name = new Twig_Node_Expression_Constant('escape', $line);
|
||||
$args = new Twig_Node(array(new Twig_Node_Expression_Constant((string) $type, $line)));
|
||||
return new Twig_Node_Expression_Filter($node, $name, $args, $line);
|
||||
}
|
||||
}
|
84
lib/classes/Twig/NodeVisitor/SafeAnalysis.php
Normal file
84
lib/classes/Twig/NodeVisitor/SafeAnalysis.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
|
||||
{
|
||||
protected $data = array();
|
||||
|
||||
public function getSafe(Twig_NodeInterface $node)
|
||||
{
|
||||
$hash = spl_object_hash($node);
|
||||
if (isset($this->data[$hash])) {
|
||||
foreach($this->data[$hash] as $bucket) {
|
||||
if ($bucket['key'] === $node) {
|
||||
return $bucket['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function setSafe(Twig_NodeInterface $node, array $safe)
|
||||
{
|
||||
$hash = spl_object_hash($node);
|
||||
if (isset($this->data[$hash])) {
|
||||
foreach($this->data[$hash] as &$bucket) {
|
||||
if ($bucket['key'] === $node) {
|
||||
$bucket['value'] = $safe;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->data[$hash][] = array(
|
||||
'key' => $node,
|
||||
'value' => $safe,
|
||||
);
|
||||
}
|
||||
|
||||
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof Twig_Node_Expression_Constant) {
|
||||
// constants are marked safe for all
|
||||
$this->setSafe($node, array('all'));
|
||||
} elseif ($node instanceof Twig_Node_Expression_Conditional) {
|
||||
// instersect safeness of both operands
|
||||
$safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3')));
|
||||
$this->setSafe($node, $safe);
|
||||
} elseif ($node instanceof Twig_Node_Expression_Filter) {
|
||||
// filter expression is safe when the filter is safe
|
||||
$filterMap = $env->getFilters();
|
||||
$name = $node->getNode('filter')->getAttribute('value');
|
||||
$args = $node->getNode('arguments');
|
||||
if (isset($filterMap[$name])) {
|
||||
$this->setSafe($node, $filterMap[$name]->getSafe($args));
|
||||
} else {
|
||||
$this->setSafe($node, array());
|
||||
}
|
||||
} else {
|
||||
$this->setSafe($node, array());
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
protected function intersectSafe(array $a = null, array $b = null)
|
||||
{
|
||||
if (null === $a || null === $b) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (in_array('all', $a)) {
|
||||
return $b;
|
||||
}
|
||||
|
||||
if (in_array('all', $b)) {
|
||||
return $a;
|
||||
}
|
||||
|
||||
return array_intersect($a, $b);
|
||||
}
|
||||
}
|
78
lib/classes/Twig/NodeVisitor/Sandbox.php
Executable file
78
lib/classes/Twig/NodeVisitor/Sandbox.php
Executable file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Twig_NodeVisitor_Sandbox implements sandboxing.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
|
||||
{
|
||||
protected $inAModule = false;
|
||||
protected $tags;
|
||||
protected $filters;
|
||||
|
||||
/**
|
||||
* Called before child nodes are visited.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to visit
|
||||
* @param Twig_Environment $env The Twig environment instance
|
||||
*
|
||||
* @param Twig_NodeInterface The modified node
|
||||
*/
|
||||
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof Twig_Node_Module) {
|
||||
$this->inAModule = true;
|
||||
$this->tags = array();
|
||||
$this->filters = array();
|
||||
|
||||
return $node;
|
||||
} elseif ($this->inAModule) {
|
||||
// look for tags
|
||||
if ($node->getNodeTag()) {
|
||||
$this->tags[] = $node->getNodeTag();
|
||||
}
|
||||
|
||||
// look for filters
|
||||
if ($node instanceof Twig_Node_Expression_Filter) {
|
||||
$this->filters[] = $node->getNode('filter')->getAttribute('value');
|
||||
}
|
||||
|
||||
// look for simple print statements ({{ article }})
|
||||
if ($node instanceof Twig_Node_Print && $node->getNode('expr') instanceof Twig_Node_Expression_Name) {
|
||||
return new Twig_Node_SandboxedPrint($node);
|
||||
}
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after child nodes are visited.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to visit
|
||||
* @param Twig_Environment $env The Twig environment instance
|
||||
*
|
||||
* @param Twig_NodeInterface The modified node
|
||||
*/
|
||||
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof Twig_Node_Module) {
|
||||
$this->inAModule = false;
|
||||
|
||||
return new Twig_Node_SandboxedModule($node, array_unique($this->filters), array_unique($this->tags));
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user