|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Provides a helper to properly encode HTML-safe JSON prior to PHP 5.3.0. |
|
6 */ |
|
7 |
|
8 /** |
|
9 * Encodes a PHP variable to HTML-safe JSON for PHP versions below 5.3.0. |
|
10 * |
|
11 * @see drupal_json_encode() |
|
12 */ |
|
13 function drupal_json_encode_helper($var) { |
|
14 switch (gettype($var)) { |
|
15 case 'boolean': |
|
16 return $var ? 'true' : 'false'; // Lowercase necessary! |
|
17 |
|
18 case 'integer': |
|
19 case 'double': |
|
20 return $var; |
|
21 |
|
22 case 'resource': |
|
23 case 'string': |
|
24 // Always use Unicode escape sequences (\u0022) over JSON escape |
|
25 // sequences (\") to prevent browsers interpreting these as |
|
26 // special characters. |
|
27 $replace_pairs = array( |
|
28 // ", \ and U+0000 - U+001F must be escaped according to RFC 4627. |
|
29 '\\' => '\u005C', |
|
30 '"' => '\u0022', |
|
31 "\x00" => '\u0000', |
|
32 "\x01" => '\u0001', |
|
33 "\x02" => '\u0002', |
|
34 "\x03" => '\u0003', |
|
35 "\x04" => '\u0004', |
|
36 "\x05" => '\u0005', |
|
37 "\x06" => '\u0006', |
|
38 "\x07" => '\u0007', |
|
39 "\x08" => '\u0008', |
|
40 "\x09" => '\u0009', |
|
41 "\x0a" => '\u000A', |
|
42 "\x0b" => '\u000B', |
|
43 "\x0c" => '\u000C', |
|
44 "\x0d" => '\u000D', |
|
45 "\x0e" => '\u000E', |
|
46 "\x0f" => '\u000F', |
|
47 "\x10" => '\u0010', |
|
48 "\x11" => '\u0011', |
|
49 "\x12" => '\u0012', |
|
50 "\x13" => '\u0013', |
|
51 "\x14" => '\u0014', |
|
52 "\x15" => '\u0015', |
|
53 "\x16" => '\u0016', |
|
54 "\x17" => '\u0017', |
|
55 "\x18" => '\u0018', |
|
56 "\x19" => '\u0019', |
|
57 "\x1a" => '\u001A', |
|
58 "\x1b" => '\u001B', |
|
59 "\x1c" => '\u001C', |
|
60 "\x1d" => '\u001D', |
|
61 "\x1e" => '\u001E', |
|
62 "\x1f" => '\u001F', |
|
63 // Prevent browsers from interpreting these as as special. |
|
64 "'" => '\u0027', |
|
65 '<' => '\u003C', |
|
66 '>' => '\u003E', |
|
67 '&' => '\u0026', |
|
68 // Prevent browsers from interpreting the solidus as special and |
|
69 // non-compliant JSON parsers from interpreting // as a comment. |
|
70 '/' => '\u002F', |
|
71 // While these are allowed unescaped according to ECMA-262, section |
|
72 // 15.12.2, they cause problems in some JSON parsers. |
|
73 "\xe2\x80\xa8" => '\u2028', // U+2028, Line Separator. |
|
74 "\xe2\x80\xa9" => '\u2029', // U+2029, Paragraph Separator. |
|
75 ); |
|
76 |
|
77 return '"' . strtr($var, $replace_pairs) . '"'; |
|
78 |
|
79 case 'array': |
|
80 // Arrays in JSON can't be associative. If the array is empty or if it |
|
81 // has sequential whole number keys starting with 0, it's not associative |
|
82 // so we can go ahead and convert it as an array. |
|
83 if (empty($var) || array_keys($var) === range(0, sizeof($var) - 1)) { |
|
84 $output = array(); |
|
85 foreach ($var as $v) { |
|
86 $output[] = drupal_json_encode_helper($v); |
|
87 } |
|
88 return '[ ' . implode(', ', $output) . ' ]'; |
|
89 } |
|
90 // Otherwise, fall through to convert the array as an object. |
|
91 |
|
92 case 'object': |
|
93 $output = array(); |
|
94 foreach ($var as $k => $v) { |
|
95 $output[] = drupal_json_encode_helper(strval($k)) . ':' . drupal_json_encode_helper($v); |
|
96 } |
|
97 return '{' . implode(', ', $output) . '}'; |
|
98 |
|
99 default: |
|
100 return 'null'; |
|
101 } |
|
102 } |