This commit is contained in:
Fabien Potencier
2019-05-21 16:03:11 +02:00
parent b18733bce0
commit fe6503fe02
3 changed files with 278 additions and 285 deletions
+255 -261
View File
@@ -14,17 +14,17 @@ use Twig\FileExtensionEscapingStrategy;
use Twig\NodeVisitor\EscaperNodeVisitor;
use Twig\TokenParser\AutoEscapeTokenParser;
use Twig\TwigFilter;
use Twig\Environment;
use Twig\Error\RuntimeError;
use Twig\Extension\CoreExtension;
use Twig\Markup;
final class EscaperExtension extends AbstractExtension
{
private $defaultStrategy;
private $escapers = [];
private $safeClasses = [];
private $safeLookup = [];
/** @internal */
public $safeClasses = [];
/** @internal */
public $safeLookup = [];
/**
* @param string|false|callable $defaultStrategy An escaping strategy
@@ -49,8 +49,8 @@ final class EscaperExtension extends AbstractExtension
public function getFilters()
{
return [
new TwigFilter('escape', [$this, 'escape'], ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
new TwigFilter('e', [$this, 'escape'], ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
new TwigFilter('escape', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
new TwigFilter('e', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
new TwigFilter('raw', 'twig_raw_filter', ['is_safe' => ['all']]),
];
}
@@ -132,256 +132,6 @@ final class EscaperExtension extends AbstractExtension
$this->safeLookup[$strategy][$class] = true;
}
}
/**
* Escapes a string.
*
* @param mixed $string The value to be escaped
* @param string $strategy The escaping strategy
* @param string $charset The charset
* @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
*
* @return string
*/
function escape(Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
{
if ($autoescape && $string instanceof Markup) {
return $string;
}
if (!\is_string($string)) {
if (\is_object($string) && method_exists($string, '__toString')) {
if ($autoescape) {
$c = get_class($string);
if (!isset($this->safeClasses[$c])) {
$this->safeClasses[$c] = [];
foreach (class_parents($string) + class_implements($string) as $class) {
if (isset($this->safeClasses[$class])) {
$this->safeClasses[$c] = array_unique(array_merge($this->safeClasses[$c], $this->safeClasses[$class]));
foreach ($this->safeClasses[$class] as $s) {
$this->safeLookup[$s][$c] = true;
}
}
}
}
if (isset($this->safeLookup[$strategy][$c]) || isset($this->safeLookup['all'][$c])) {
return (string) $string;
}
}
$string = (string) $string;
} elseif (\in_array($strategy, ['html', 'js', 'css', 'html_attr', 'url'])) {
return $string;
}
}
if ('' === $string) {
return '';
}
if (null === $charset) {
$charset = $env->getCharset();
}
switch ($strategy) {
case 'html':
// see https://secure.php.net/htmlspecialchars
// Using a static variable to avoid initializing the array
// each time the function is called. Moving the declaration on the
// top of the function slow downs other escaping strategies.
static $htmlspecialcharsCharsets = [
'ISO-8859-1' => true, 'ISO8859-1' => true,
'ISO-8859-15' => true, 'ISO8859-15' => true,
'utf-8' => true, 'UTF-8' => true,
'CP866' => true, 'IBM866' => true, '866' => true,
'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true,
'1251' => true,
'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true,
'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true,
'BIG5' => true, '950' => true,
'GB2312' => true, '936' => true,
'BIG5-HKSCS' => true,
'SHIFT_JIS' => true, 'SJIS' => true, '932' => true,
'EUC-JP' => true, 'EUCJP' => true,
'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true,
];
if (isset($htmlspecialcharsCharsets[$charset])) {
return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
}
if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) {
// cache the lowercase variant for future iterations
$htmlspecialcharsCharsets[$charset] = true;
return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
}
$string = iconv($charset, 'UTF-8', $string);
$string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
return iconv('UTF-8', $charset, $string);
case 'js':
// escape all non-alphanumeric characters
// into their \x or \uHHHH representations
if ('UTF-8' !== $charset) {
$string = iconv($charset, 'UTF-8', $string);
}
if (!preg_match('//u', $string)) {
throw new RuntimeError('The string to escape is not a valid UTF-8 string.');
}
$string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', function ($matches) {
$char = $matches[0];
/*
* A few characters have short escape sequences in JSON and JavaScript.
* Escape sequences supported only by JavaScript, not JSON, are ommitted.
* \" is also supported but omitted, because the resulting string is not HTML safe.
*/
static $shortMap = [
'\\' => '\\\\',
'/' => '\\/',
"\x08" => '\b',
"\x0C" => '\f',
"\x0A" => '\n',
"\x0D" => '\r',
"\x09" => '\t',
];
if (isset($shortMap[$char])) {
return $shortMap[$char];
}
// \uHHHH
$char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
$char = strtoupper(bin2hex($char));
if (4 >= \strlen($char)) {
return sprintf('\u%04s', $char);
}
return sprintf('\u%04s\u%04s', substr($char, 0, -4), substr($char, -4));
}, $string);
if ('UTF-8' !== $charset) {
$string = iconv('UTF-8', $charset, $string);
}
return $string;
case 'css':
if ('UTF-8' !== $charset) {
$string = iconv($charset, 'UTF-8', $string);
}
if (!preg_match('//u', $string)) {
throw new RuntimeError('The string to escape is not a valid UTF-8 string.');
}
$string = preg_replace_callback('#[^a-zA-Z0-9]#Su', function ($matches) {
$char = $matches[0];
return sprintf('\\%X ', 1 === \strlen($char) ? \ord($char) : mb_ord($char, 'UTF-8'));
}, $string);
if ('UTF-8' !== $charset) {
$string = iconv('UTF-8', $charset, $string);
}
return $string;
case 'html_attr':
if ('UTF-8' !== $charset) {
$string = iconv($charset, 'UTF-8', $string);
}
if (!preg_match('//u', $string)) {
throw new RuntimeError('The string to escape is not a valid UTF-8 string.');
}
$string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', function ($matches) {
/**
* This function is adapted from code coming from Zend Framework.
*
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://framework.zend.com/license/new-bsd New BSD License
*/
$chr = $matches[0];
$ord = \ord($chr);
/*
* The following replaces characters undefined in HTML with the
* hex entity for the Unicode replacement character.
*/
if (($ord <= 0x1f && "\t" != $chr && "\n" != $chr && "\r" != $chr) || ($ord >= 0x7f && $ord <= 0x9f)) {
return '&#xFFFD;';
}
/*
* Check if the current character to escape has a name entity we should
* replace it with while grabbing the hex value of the character.
*/
if (1 === \strlen($chr)) {
/*
* While HTML supports far more named entities, the lowest common denominator
* has become HTML5's XML Serialisation which is restricted to the those named
* entities that XML supports. Using HTML entities would result in this error:
* XML Parsing Error: undefined entity
*/
static $entityMap = [
34 => '&quot;', /* quotation mark */
38 => '&amp;', /* ampersand */
60 => '&lt;', /* less-than sign */
62 => '&gt;', /* greater-than sign */
];
if (isset($entityMap[$ord])) {
return $entityMap[$ord];
}
return sprintf('&#x%02X;', $ord);
}
/*
* Per OWASP recommendations, we'll use hex entities for any other
* characters where a named entity does not exist.
*/
return sprintf('&#x%04X;', mb_ord($chr, 'UTF-8'));
}, $string);
if ('UTF-8' !== $charset) {
$string = iconv('UTF-8', $charset, $string);
}
return $string;
case 'url':
return rawurlencode($string);
default:
static $escapers;
if (null === $escapers) {
// merge the ones set on CoreExtension for BC (to be removed in 3.0)
$escapers = array_merge(
$env->getExtension(CoreExtension::class)->getEscapers(false),
$env->getExtension(EscaperExtension::class)->getEscapers()
);
}
if (isset($escapers[$strategy])) {
return $escapers[$strategy]($env, $string, $charset);
}
$validStrategies = implode(', ', array_merge(['html', 'js', 'url', 'css', 'html_attr'], array_keys($escapers)));
throw new RuntimeError(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies));
}
}
}
class_alias('Twig\Extension\EscaperExtension', 'Twig_Extension_Escaper');
@@ -389,7 +139,10 @@ class_alias('Twig\Extension\EscaperExtension', 'Twig_Extension_Escaper');
namespace {
use Twig\Environment;
use Twig\Error\RuntimeError;
use Twig\Extension\CoreExtension;
use Twig\Extension\EscaperExtension;
use Twig\Markup;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Node;
@@ -406,13 +159,254 @@ function twig_raw_filter($string)
}
/**
* @deprecated since Twig 2.11, to be removed in 3.0; use EscaperExtension::escape instead
* Escapes a string.
*
* @param mixed $string The value to be escaped
* @param string $strategy The escaping strategy
* @param string $charset The charset
* @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
*
* @return string
*/
function twig_escape_filter(Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
{
@trigger_error(sprintf('The "%s" method is deprecated since Twig 2.11; use "%s::escape" instead.', __METHOD__, EscaperExtension::class), E_USER_DEPRECATED);
if ($autoescape && $string instanceof Markup) {
return $string;
}
return $env->getExtension(EscaperExtension::class)->escape($env, $string, $strategy, $charset, $autoescape);
if (!\is_string($string)) {
if (\is_object($string) && method_exists($string, '__toString')) {
if ($autoescape) {
$c = \get_class($string);
$ext = $env->getExtension(EscaperExtension::class);
if (!isset($ext->safeClasses[$c])) {
$ext->safeClasses[$c] = [];
foreach (class_parents($string) + class_implements($string) as $class) {
if (isset($ext->safeClasses[$class])) {
$ext->safeClasses[$c] = array_unique(array_merge($ext->safeClasses[$c], $ext->safeClasses[$class]));
foreach ($ext->safeClasses[$class] as $s) {
$ext->safeLookup[$s][$c] = true;
}
}
}
}
if (isset($ext->safeLookup[$strategy][$c]) || isset($ext->safeLookup['all'][$c])) {
return (string) $string;
}
}
$string = (string) $string;
} elseif (\in_array($strategy, ['html', 'js', 'css', 'html_attr', 'url'])) {
return $string;
}
}
if ('' === $string) {
return '';
}
if (null === $charset) {
$charset = $env->getCharset();
}
switch ($strategy) {
case 'html':
// see https://secure.php.net/htmlspecialchars
// Using a static variable to avoid initializing the array
// each time the function is called. Moving the declaration on the
// top of the function slow downs other escaping strategies.
static $htmlspecialcharsCharsets = [
'ISO-8859-1' => true, 'ISO8859-1' => true,
'ISO-8859-15' => true, 'ISO8859-15' => true,
'utf-8' => true, 'UTF-8' => true,
'CP866' => true, 'IBM866' => true, '866' => true,
'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true,
'1251' => true,
'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true,
'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true,
'BIG5' => true, '950' => true,
'GB2312' => true, '936' => true,
'BIG5-HKSCS' => true,
'SHIFT_JIS' => true, 'SJIS' => true, '932' => true,
'EUC-JP' => true, 'EUCJP' => true,
'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true,
];
if (isset($htmlspecialcharsCharsets[$charset])) {
return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
}
if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) {
// cache the lowercase variant for future iterations
$htmlspecialcharsCharsets[$charset] = true;
return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
}
$string = iconv($charset, 'UTF-8', $string);
$string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
return iconv('UTF-8', $charset, $string);
case 'js':
// escape all non-alphanumeric characters
// into their \x or \uHHHH representations
if ('UTF-8' !== $charset) {
$string = iconv($charset, 'UTF-8', $string);
}
if (!preg_match('//u', $string)) {
throw new RuntimeError('The string to escape is not a valid UTF-8 string.');
}
$string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', function ($matches) {
$char = $matches[0];
/*
* A few characters have short escape sequences in JSON and JavaScript.
* Escape sequences supported only by JavaScript, not JSON, are ommitted.
* \" is also supported but omitted, because the resulting string is not HTML safe.
*/
static $shortMap = [
'\\' => '\\\\',
'/' => '\\/',
"\x08" => '\b',
"\x0C" => '\f',
"\x0A" => '\n',
"\x0D" => '\r',
"\x09" => '\t',
];
if (isset($shortMap[$char])) {
return $shortMap[$char];
}
// \uHHHH
$char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
$char = strtoupper(bin2hex($char));
if (4 >= \strlen($char)) {
return sprintf('\u%04s', $char);
}
return sprintf('\u%04s\u%04s', substr($char, 0, -4), substr($char, -4));
}, $string);
if ('UTF-8' !== $charset) {
$string = iconv('UTF-8', $charset, $string);
}
return $string;
case 'css':
if ('UTF-8' !== $charset) {
$string = iconv($charset, 'UTF-8', $string);
}
if (!preg_match('//u', $string)) {
throw new RuntimeError('The string to escape is not a valid UTF-8 string.');
}
$string = preg_replace_callback('#[^a-zA-Z0-9]#Su', function ($matches) {
$char = $matches[0];
return sprintf('\\%X ', 1 === \strlen($char) ? \ord($char) : mb_ord($char, 'UTF-8'));
}, $string);
if ('UTF-8' !== $charset) {
$string = iconv('UTF-8', $charset, $string);
}
return $string;
case 'html_attr':
if ('UTF-8' !== $charset) {
$string = iconv($charset, 'UTF-8', $string);
}
if (!preg_match('//u', $string)) {
throw new RuntimeError('The string to escape is not a valid UTF-8 string.');
}
$string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', function ($matches) {
/**
* This function is adapted from code coming from Zend Framework.
*
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://framework.zend.com/license/new-bsd New BSD License
*/
$chr = $matches[0];
$ord = \ord($chr);
/*
* The following replaces characters undefined in HTML with the
* hex entity for the Unicode replacement character.
*/
if (($ord <= 0x1f && "\t" != $chr && "\n" != $chr && "\r" != $chr) || ($ord >= 0x7f && $ord <= 0x9f)) {
return '&#xFFFD;';
}
/*
* Check if the current character to escape has a name entity we should
* replace it with while grabbing the hex value of the character.
*/
if (1 === \strlen($chr)) {
/*
* While HTML supports far more named entities, the lowest common denominator
* has become HTML5's XML Serialisation which is restricted to the those named
* entities that XML supports. Using HTML entities would result in this error:
* XML Parsing Error: undefined entity
*/
static $entityMap = [
34 => '&quot;', /* quotation mark */
38 => '&amp;', /* ampersand */
60 => '&lt;', /* less-than sign */
62 => '&gt;', /* greater-than sign */
];
if (isset($entityMap[$ord])) {
return $entityMap[$ord];
}
return sprintf('&#x%02X;', $ord);
}
/*
* Per OWASP recommendations, we'll use hex entities for any other
* characters where a named entity does not exist.
*/
return sprintf('&#x%04X;', mb_ord($chr, 'UTF-8'));
}, $string);
if ('UTF-8' !== $charset) {
$string = iconv('UTF-8', $charset, $string);
}
return $string;
case 'url':
return rawurlencode($string);
default:
static $escapers;
if (null === $escapers) {
// merge the ones set on CoreExtension for BC (to be removed in 3.0)
$escapers = array_merge(
$env->getExtension(CoreExtension::class)->getEscapers(false),
$env->getExtension(EscaperExtension::class)->getEscapers()
);
}
if (isset($escapers[$strategy])) {
return $escapers[$strategy]($env, $string, $charset);
}
$validStrategies = implode(', ', array_merge(['html', 'js', 'url', 'css', 'html_attr'], array_keys($escapers)));
throw new RuntimeError(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies));
}
}
/**
+22 -22
View File
@@ -158,7 +158,7 @@ class Twig_Tests_Extension_EscaperTest extends \PHPUnit\Framework\TestCase
{
$twig = new \Twig\Environment($this->getMockBuilder(\Twig\Loader\LoaderInterface::class)->getMock());
foreach ($this->htmlSpecialChars as $key => $value) {
$this->assertEquals($value, $twig->getExtension(EscaperExtension::class)->escape($twig, $key, 'html'), 'Failed to escape: '.$key);
$this->assertEquals($value, twig_escape_filter($twig, $key, 'html'), 'Failed to escape: '.$key);
}
}
@@ -166,7 +166,7 @@ class Twig_Tests_Extension_EscaperTest extends \PHPUnit\Framework\TestCase
{
$twig = new \Twig\Environment($this->getMockBuilder(\Twig\Loader\LoaderInterface::class)->getMock());
foreach ($this->htmlAttrSpecialChars as $key => $value) {
$this->assertEquals($value, $twig->getExtension(EscaperExtension::class)->escape($twig, $key, 'html_attr'), 'Failed to escape: '.$key);
$this->assertEquals($value, twig_escape_filter($twig, $key, 'html_attr'), 'Failed to escape: '.$key);
}
}
@@ -174,47 +174,47 @@ class Twig_Tests_Extension_EscaperTest extends \PHPUnit\Framework\TestCase
{
$twig = new \Twig\Environment($this->getMockBuilder(\Twig\Loader\LoaderInterface::class)->getMock());
foreach ($this->jsSpecialChars as $key => $value) {
$this->assertEquals($value, $twig->getExtension(EscaperExtension::class)->escape($twig, $key, 'js'), 'Failed to escape: '.$key);
$this->assertEquals($value, twig_escape_filter($twig, $key, 'js'), 'Failed to escape: '.$key);
}
}
public function testJavascriptEscapingReturnsStringIfZeroLength()
{
$twig = new \Twig\Environment($this->getMockBuilder(\Twig\Loader\LoaderInterface::class)->getMock());
$this->assertEquals('', $twig->getExtension(EscaperExtension::class)->escape($twig, '', 'js'));
$this->assertEquals('', twig_escape_filter($twig, '', 'js'));
}
public function testJavascriptEscapingReturnsStringIfContainsOnlyDigits()
{
$twig = new \Twig\Environment($this->getMockBuilder(\Twig\Loader\LoaderInterface::class)->getMock());
$this->assertEquals('123', $twig->getExtension(EscaperExtension::class)->escape($twig, '123', 'js'));
$this->assertEquals('123', twig_escape_filter($twig, '123', 'js'));
}
public function testCssEscapingConvertsSpecialChars()
{
$twig = new \Twig\Environment($this->getMockBuilder(\Twig\Loader\LoaderInterface::class)->getMock());
foreach ($this->cssSpecialChars as $key => $value) {
$this->assertEquals($value, $twig->getExtension(EscaperExtension::class)->escape($twig, $key, 'css'), 'Failed to escape: '.$key);
$this->assertEquals($value, twig_escape_filter($twig, $key, 'css'), 'Failed to escape: '.$key);
}
}
public function testCssEscapingReturnsStringIfZeroLength()
{
$twig = new \Twig\Environment($this->getMockBuilder(\Twig\Loader\LoaderInterface::class)->getMock());
$this->assertEquals('', $twig->getExtension(EscaperExtension::class)->escape($twig, '', 'css'));
$this->assertEquals('', twig_escape_filter($twig, '', 'css'));
}
public function testCssEscapingReturnsStringIfContainsOnlyDigits()
{
$twig = new \Twig\Environment($this->getMockBuilder(\Twig\Loader\LoaderInterface::class)->getMock());
$this->assertEquals('123', $twig->getExtension(EscaperExtension::class)->escape($twig, '123', 'css'));
$this->assertEquals('123', twig_escape_filter($twig, '123', 'css'));
}
public function testUrlEscapingConvertsSpecialChars()
{
$twig = new \Twig\Environment($this->getMockBuilder(\Twig\Loader\LoaderInterface::class)->getMock());
foreach ($this->urlSpecialChars as $key => $value) {
$this->assertEquals($value, $twig->getExtension(EscaperExtension::class)->escape($twig, $key, 'url'), 'Failed to escape: '.$key);
$this->assertEquals($value, twig_escape_filter($twig, $key, 'url'), 'Failed to escape: '.$key);
}
}
@@ -276,15 +276,15 @@ class Twig_Tests_Extension_EscaperTest extends \PHPUnit\Framework\TestCase
|| $chr >= 0x41 && $chr <= 0x5A
|| $chr >= 0x61 && $chr <= 0x7A) {
$literal = $this->codepointToUtf8($chr);
$this->assertEquals($literal, $twig->getExtension(EscaperExtension::class)->escape($twig, $literal, 'js'));
$this->assertEquals($literal, twig_escape_filter($twig, $literal, 'js'));
} else {
$literal = $this->codepointToUtf8($chr);
if (\in_array($literal, $immune)) {
$this->assertEquals($literal, $twig->getExtension(EscaperExtension::class)->escape($twig, $literal, 'js'));
$this->assertEquals($literal, twig_escape_filter($twig, $literal, 'js'));
} else {
$this->assertNotEquals(
$literal,
$twig->getExtension(EscaperExtension::class)->escape($twig, $literal, 'js'),
twig_escape_filter($twig, $literal, 'js'),
"$literal should be escaped!");
}
}
@@ -300,15 +300,15 @@ class Twig_Tests_Extension_EscaperTest extends \PHPUnit\Framework\TestCase
|| $chr >= 0x41 && $chr <= 0x5A
|| $chr >= 0x61 && $chr <= 0x7A) {
$literal = $this->codepointToUtf8($chr);
$this->assertEquals($literal, $twig->getExtension(EscaperExtension::class)->escape($twig, $literal, 'html_attr'));
$this->assertEquals($literal, twig_escape_filter($twig, $literal, 'html_attr'));
} else {
$literal = $this->codepointToUtf8($chr);
if (\in_array($literal, $immune)) {
$this->assertEquals($literal, $twig->getExtension(EscaperExtension::class)->escape($twig, $literal, 'html_attr'));
$this->assertEquals($literal, twig_escape_filter($twig, $literal, 'html_attr'));
} else {
$this->assertNotEquals(
$literal,
$twig->getExtension(EscaperExtension::class)->escape($twig, $literal, 'html_attr'),
twig_escape_filter($twig, $literal, 'html_attr'),
"$literal should be escaped!");
}
}
@@ -324,12 +324,12 @@ class Twig_Tests_Extension_EscaperTest extends \PHPUnit\Framework\TestCase
|| $chr >= 0x41 && $chr <= 0x5A
|| $chr >= 0x61 && $chr <= 0x7A) {
$literal = $this->codepointToUtf8($chr);
$this->assertEquals($literal, $twig->getExtension(EscaperExtension::class)->escape($twig, $literal, 'css'));
$this->assertEquals($literal, twig_escape_filter($twig, $literal, 'css'));
} else {
$literal = $this->codepointToUtf8($chr);
$this->assertNotEquals(
$literal,
$twig->getExtension(EscaperExtension::class)->escape($twig, $literal, 'css'),
twig_escape_filter($twig, $literal, 'css'),
"$literal should be escaped!");
}
}
@@ -343,7 +343,7 @@ class Twig_Tests_Extension_EscaperTest extends \PHPUnit\Framework\TestCase
$twig = new Environment($this->getMockBuilder(LoaderInterface::class)->getMock());
$twig->getExtension(EscaperExtension::class)->setEscaper('foo', 'foo_escaper_for_test');
$this->assertSame($expected, $twig->getExtension(EscaperExtension::class)->escape($twig, $string, $strategy));
$this->assertSame($expected, twig_escape_filter($twig, $string, $strategy));
}
public function provideCustomEscaperCases()
@@ -360,8 +360,7 @@ class Twig_Tests_Extension_EscaperTest extends \PHPUnit\Framework\TestCase
*/
public function testUnknownCustomEscaper()
{
$twig = new Environment($this->getMockBuilder(LoaderInterface::class)->getMock());
$twig->getExtension(EscaperExtension::class)->escape($twig, 'foo', 'bar');
twig_escape_filter(new Environment($this->getMockBuilder(LoaderInterface::class)->getMock()), 'foo', 'bar');
}
/**
@@ -372,9 +371,10 @@ class Twig_Tests_Extension_EscaperTest extends \PHPUnit\Framework\TestCase
$obj = new Twig_Tests_Extension_TestClass();
$twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock());
$twig->getExtension('\Twig\Extension\EscaperExtension')->setSafeClasses($safeClasses);
$this->assertSame($escapedHtml, $twig->getExtension(EscaperExtension::class)->escape($twig, $obj, 'html', null, true));
$this->assertSame($escapedJs, $twig->getExtension(EscaperExtension::class)->escape($twig, $obj, 'js', null, true));
$this->assertSame($escapedHtml, twig_escape_filter($twig, $obj, 'html', null, true));
$this->assertSame($escapedJs, twig_escape_filter($twig, $obj, 'js', null, true));
}
public function provideObjectsForEscaping()
{
return [
+1 -2
View File
@@ -22,7 +22,6 @@ use Twig\TokenParser\AbstractTokenParser;
use Twig\TwigFilter;
use Twig\TwigFunction;
use Twig\TwigTest;
use Twig\Extension\EscaperExtension;
// This function is defined to check that escaping strategies
// like html works even if a function with the same name is defined.
@@ -204,7 +203,7 @@ class TwigTestExtension extends AbstractExtension
*/
public function escape_and_nl2br($env, $value, $sep = '<br />')
{
return $this->nl2br($env->getExtension(EscaperExtension::class)->escape($env, $value, 'html'), $sep);
return $this->nl2br(twig_escape_filter($env, $value, 'html'), $sep);
}
/**