mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-12 10:26:32 +00:00
Add JSON escape strategy
This commit is contained in:
committed by
Fabien Potencier
parent
c35ad8c4e3
commit
5c7b080b31
@@ -1,6 +1,6 @@
|
||||
* 1.35.4 (2018-XX-XX)
|
||||
|
||||
* n/a
|
||||
* "js" filter now produces valid JSON
|
||||
|
||||
* 1.35.3 (2018-03-20)
|
||||
|
||||
|
||||
@@ -1040,7 +1040,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
||||
|
||||
case 'js':
|
||||
// escape all non-alphanumeric characters
|
||||
// into their \xHH or \uHHHH representations
|
||||
// into their \x or \uHHHH representations
|
||||
if ('UTF-8' !== $charset) {
|
||||
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
||||
}
|
||||
@@ -1152,9 +1152,23 @@ function _twig_escape_js_callback($matches)
|
||||
{
|
||||
$char = $matches[0];
|
||||
|
||||
// \xHH
|
||||
if (!isset($char[1])) {
|
||||
return '\\x'.strtoupper(substr('00'.bin2hex($char), -2));
|
||||
/*
|
||||
* 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 = array(
|
||||
'\\' => '\\\\',
|
||||
'/' => '\\/',
|
||||
"\x08" => '\b',
|
||||
"\x0C" => '\f',
|
||||
"\x0A" => '\n',
|
||||
"\x0D" => '\r',
|
||||
"\x09" => '\t',
|
||||
);
|
||||
|
||||
if (isset($shortMap[$char])) {
|
||||
return $shortMap[$char];
|
||||
}
|
||||
|
||||
// \uHHHH
|
||||
|
||||
@@ -61,7 +61,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
||||
));
|
||||
|
||||
$this->assertEquals('foo<br/ > foo<br/ >', $twig->render('html', array('foo' => 'foo<br/ >')));
|
||||
$this->assertEquals('foo\x3Cbr\x2F\x20\x3E foo\x3Cbr\x2F\x20\x3E', $twig->render('js', array('bar' => 'foo<br/ >')));
|
||||
$this->assertEquals('foo\u003Cbr\/\u0020\u003E foo\u003Cbr\/\u0020\u003E', $twig->render('js', array('bar' => 'foo<br/ >')));
|
||||
}
|
||||
|
||||
public function escapingStrategyCallback($name)
|
||||
|
||||
@@ -17,6 +17,6 @@ return array('br' => '<br />')
|
||||
return array('autoescape' => 'name')
|
||||
--EXPECT--
|
||||
<br />
|
||||
\x3Cbr\x20\x2F\x3E
|
||||
\u003Cbr\u0020\/\u003E
|
||||
<br />
|
||||
<br />
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
--DATA--
|
||||
return array()
|
||||
--EXPECT--
|
||||
\u00E9\x20\u265C\x20\uD834\uDF06
|
||||
\u00E9\u0020\u265C\u0020\uD834\uDF06
|
||||
|
||||
@@ -14,5 +14,5 @@
|
||||
return array()
|
||||
--EXPECT--
|
||||
foo<br />
|
||||
\x20\x20\x20\x20foo\x3Cbr\x20\x2F\x3E\x0A
|
||||
\u0020\u0020\u0020\u0020foo\u003Cbr\u0020\/\u003E\n
|
||||
foo<br />
|
||||
|
||||
@@ -80,4 +80,4 @@ unsafe_br()|escape
|
||||
autoescape js
|
||||
|
||||
safe_br
|
||||
\x3Cbr\x20\x2F\x3E
|
||||
\u003Cbr\u0020\/\u003E
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
--DATA--
|
||||
return array('var' => '<br />"')
|
||||
--EXPECT--
|
||||
\x3Cbr\x20\x2F\x3E\x22
|
||||
\u003Cbr\u0020\/\u003E\u0022
|
||||
<br />"
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
--DATA--
|
||||
return array('var' => '<br />"')
|
||||
--EXPECT--
|
||||
\x3Cbr\x20\x2F\x3E\x22
|
||||
\u003Cbr\u0020\/\u003E\u0022
|
||||
<br />"
|
||||
|
||||
@@ -44,15 +44,15 @@ return array('msg' => "<>\n'\"")
|
||||
|
||||
1. autoescape 'html' |escape('js')
|
||||
|
||||
<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a>
|
||||
<a onclick="alert("\u003C\u003E\n\u0027\u0022")"></a>
|
||||
|
||||
2. autoescape 'html' |escape('js')
|
||||
|
||||
<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a>
|
||||
<a onclick="alert("\u003C\u003E\n\u0027\u0022")"></a>
|
||||
|
||||
3. autoescape 'js' |escape('js')
|
||||
|
||||
<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a>
|
||||
<a onclick="alert("\u003C\u003E\n\u0027\u0022")"></a>
|
||||
|
||||
4. no escape
|
||||
|
||||
@@ -61,9 +61,9 @@ return array('msg' => "<>\n'\"")
|
||||
|
||||
5. |escape('js')|escape('html')
|
||||
|
||||
<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a>
|
||||
<a onclick="alert("\u003C\u003E\n\u0027\u0022")"></a>
|
||||
|
||||
6. autoescape 'html' |escape('js')|escape('html')
|
||||
|
||||
<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a>
|
||||
<a onclick="alert("\u003C\u003E\n\u0027\u0022")"></a>
|
||||
|
||||
|
||||
@@ -51,13 +51,15 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase
|
||||
|
||||
protected $jsSpecialChars = array(
|
||||
/* HTML special chars - escape without exception to hex */
|
||||
'<' => '\\x3C',
|
||||
'>' => '\\x3E',
|
||||
'\'' => '\\x27',
|
||||
'"' => '\\x22',
|
||||
'&' => '\\x26',
|
||||
'<' => '\\u003C',
|
||||
'>' => '\\u003E',
|
||||
'\'' => '\\u0027',
|
||||
'"' => '\\u0022',
|
||||
'&' => '\\u0026',
|
||||
'/' => '\\/',
|
||||
/* Characters beyond ASCII value 255 to unicode escape */
|
||||
'Ā' => '\\u0100',
|
||||
'😀' => '\\uD83D\\uDE00',
|
||||
/* Immune chars excluded */
|
||||
',' => ',',
|
||||
'.' => '.',
|
||||
@@ -70,12 +72,14 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase
|
||||
'0' => '0',
|
||||
'9' => '9',
|
||||
/* Basic control characters and null */
|
||||
"\r" => '\\x0D',
|
||||
"\n" => '\\x0A',
|
||||
"\t" => '\\x09',
|
||||
"\0" => '\\x00',
|
||||
"\r" => '\r',
|
||||
"\n" => '\n',
|
||||
"\x08" => '\b',
|
||||
"\t" => '\t',
|
||||
"\x0C" => '\f',
|
||||
"\0" => '\\u0000',
|
||||
/* Encode spaces for quoteless attribute protection */
|
||||
' ' => '\\x20',
|
||||
' ' => '\\u0020',
|
||||
);
|
||||
|
||||
protected $urlSpecialChars = array(
|
||||
|
||||
Reference in New Issue
Block a user