mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-01-31 09:06:17 +00:00
Updating JavascriptHelper::escapeString to properly encode utf8 characters as per the JSON spec.
Test cases added, with comparisons to json_encode() Fixes #6400 git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@8198 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
parent
88e0cfa2f8
commit
1ea5f94c29
2 changed files with 153 additions and 4 deletions
|
@ -319,8 +319,104 @@ class JavascriptHelper extends AppHelper {
|
|||
* @return string Escaped string.
|
||||
*/
|
||||
function escapeString($string) {
|
||||
$escape = array('\n' => '\\\n', "\r\n" => '\n', "\r" => '\n', "\n" => '\n', '"' => '\"', "'" => "\\'");
|
||||
return str_replace(array_keys($escape), array_values($escape), $string);
|
||||
App::import('Core', 'Multibyte');
|
||||
$escape = array("\r\n" => "\n", "\r" => "\n");
|
||||
$string = str_replace(array_keys($escape), array_values($escape), $string);
|
||||
return $this->_utf8ToHex($string);
|
||||
}
|
||||
/**
|
||||
* Encode a string into JSON. Converts and escapes necessary characters.
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function _utf8ToHex($string) {
|
||||
$length = strlen($string);
|
||||
$return = '';
|
||||
for ($i = 0; $i < $length; ++$i) {
|
||||
$ord = ord($string{$i});
|
||||
switch (true) {
|
||||
case $ord == 0x08:
|
||||
$return .= '\b';
|
||||
break;
|
||||
case $ord == 0x09:
|
||||
$return .= '\t';
|
||||
break;
|
||||
case $ord == 0x0A:
|
||||
$return .= '\n';
|
||||
break;
|
||||
case $ord == 0x0C:
|
||||
$return .= '\f';
|
||||
break;
|
||||
case $ord == 0x0D:
|
||||
$return .= '\r';
|
||||
break;
|
||||
case $ord == 0x22:
|
||||
case $ord == 0x2F:
|
||||
case $ord == 0x5C:
|
||||
case $ord == 0x27:
|
||||
$return .= '\\' . $string{$i};
|
||||
break;
|
||||
case (($ord >= 0x20) && ($ord <= 0x7F)):
|
||||
$return .= $string{$i};
|
||||
break;
|
||||
case (($ord & 0xE0) == 0xC0):
|
||||
if ($i + 1 >= $length) {
|
||||
$i += 1;
|
||||
$return .= '?';
|
||||
break;
|
||||
}
|
||||
$charbits = $string{$i} . $string{$i + 1};
|
||||
$char = Multibyte::utf8($charbits);
|
||||
$return .= sprintf('\u%04s', dechex($char[0]));
|
||||
$i += 1;
|
||||
break;
|
||||
case (($ord & 0xF0) == 0xE0):
|
||||
if ($i + 2 >= $length) {
|
||||
$i += 2;
|
||||
$return .= '?';
|
||||
break;
|
||||
}
|
||||
$charbits = $string{$i} . $string{$i + 1} . $string{$i + 2};
|
||||
$char = Multibyte::utf8($charbits);
|
||||
$return .= sprintf('\u%04s', dechex($char[0]));
|
||||
$i += 2;
|
||||
break;
|
||||
case (($ord & 0xF8) == 0xF0):
|
||||
if ($i + 3 >= $length) {
|
||||
$i += 3;
|
||||
$return .= '?';
|
||||
break;
|
||||
}
|
||||
$charbits = $string{$i} . $string{$i + 1} . $string{$i + 2} . $string{$i + 3};
|
||||
$char = Multibyte::utf8($charbits);
|
||||
$return .= sprintf('\u%04s', dechex($char[0]));
|
||||
$i += 3;
|
||||
break;
|
||||
case (($ord & 0xFC) == 0xF8):
|
||||
if ($i + 4 >= $length) {
|
||||
$i += 4;
|
||||
$return .= '?';
|
||||
break;
|
||||
}
|
||||
$charbits = $string{$i} . $string{$i + 1} . $string{$i + 2} . $string{$i + 3} . $string{$i + 4};
|
||||
$char = Multibyte::utf8($charbits);
|
||||
$return .= sprintf('\u%04s', dechex($char[0]));
|
||||
$i += 4;
|
||||
break;
|
||||
case (($ord & 0xFE) == 0xFC):
|
||||
if ($i + 5 >= $length) {
|
||||
$i += 5;
|
||||
$return .= '?';
|
||||
break;
|
||||
}
|
||||
$charbits = $string{$i} . $string{$i + 1} . $string{$i + 2} . $string{$i + 3} . $string{$i + 4} . $string{$i + 5};
|
||||
$char = Multibyte::utf8($charbits);
|
||||
$return .= sprintf('\u%04s', dechex($char[0]));
|
||||
$i += 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
/**
|
||||
* Attach an event to an element. Used with the Prototype library.
|
||||
|
|
|
@ -402,6 +402,7 @@ class JavascriptTest extends CakeTestCase {
|
|||
|
||||
$this->Javascript->useNative = $oldNative;
|
||||
}
|
||||
|
||||
/**
|
||||
* testScriptBlock method
|
||||
*
|
||||
|
@ -653,11 +654,11 @@ class JavascriptTest extends CakeTestCase {
|
|||
$this->assertEqual($result, $expected);
|
||||
|
||||
$result = $this->Javascript->escapeString('CakePHP: \'Rapid Development Framework\'');
|
||||
$expected = 'CakePHP: \\\'Rapid Development Framework\\\'';
|
||||
$expected = "CakePHP: \\'Rapid Development Framework\\'";
|
||||
$this->assertEqual($result, $expected);
|
||||
|
||||
$result = $this->Javascript->escapeString('my \\"string\\"');
|
||||
$expected = 'my \\\"string\\\"';
|
||||
$expected = 'my \\\\\\"string\\\\\\"';
|
||||
$this->assertEqual($result, $expected);
|
||||
|
||||
$result = $this->Javascript->escapeString('my string\nanother line');
|
||||
|
@ -672,6 +673,58 @@ class JavascriptTest extends CakeTestCase {
|
|||
$expected = 'String with \\\n string that looks like newline';
|
||||
$this->assertEqual($result, $expected);
|
||||
}
|
||||
/**
|
||||
* test string escaping and compare to json_encode()
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testStringJsonEncodeCompliance() {
|
||||
if (!function_exists('json_encode')) {
|
||||
return;
|
||||
}
|
||||
$this->Javascript->useNative = false;
|
||||
$data = array();
|
||||
$data['mystring'] = "simple string";
|
||||
$this->assertEqual(json_encode($data), $this->Javascript->object($data));
|
||||
|
||||
$data['mystring'] = "strïng with spécial chârs";
|
||||
$this->assertEqual(json_encode($data), $this->Javascript->object($data));
|
||||
|
||||
$data['mystring'] = "a two lines\nstring";
|
||||
$this->assertEqual(json_encode($data), $this->Javascript->object($data));
|
||||
|
||||
$data['mystring'] = "a \t tabbed \t string";
|
||||
$this->assertEqual(json_encode($data), $this->Javascript->object($data));
|
||||
|
||||
$data['mystring'] = "a \"double-quoted\" string";
|
||||
$this->assertEqual(json_encode($data), $this->Javascript->object($data));
|
||||
|
||||
$data['mystring'] = 'a \\"double-quoted\\" string';
|
||||
$this->assertEqual(json_encode($data), $this->Javascript->object($data));
|
||||
}
|
||||
/**
|
||||
* test that text encoded with Javascript::object decodes properly
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testObjectDecodeCompatibility() {
|
||||
if (!function_exists('json_decode')) {
|
||||
return;
|
||||
}
|
||||
$this->Javascript->useNative = false;
|
||||
|
||||
$data = array("simple string");
|
||||
$result = $this->Javascript->object($data);
|
||||
$this->assertEqual(json_decode($result), $data);
|
||||
|
||||
$data = array('my \"string\"');
|
||||
$result = $this->Javascript->object($data);
|
||||
$this->assertEqual(json_decode($result), $data);
|
||||
|
||||
$data = array('my \\"string\\"');
|
||||
$result = $this->Javascript->object($data);
|
||||
$this->assertEqual(json_decode($result), $data);
|
||||
}
|
||||
/**
|
||||
* testAfterRender method
|
||||
*
|
||||
|
|
Loading…
Add table
Reference in a new issue