From a779eea202616dcd9d0de07d865c259c96d59e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Wed, 30 Jul 2014 15:17:57 +0200 Subject: [PATCH] Restored JSON reimplementation --- htdocs/core/lib/json.lib.php | 244 ++++++++++++++++++++++++++++++++++- 1 file changed, 240 insertions(+), 4 deletions(-) diff --git a/htdocs/core/lib/json.lib.php b/htdocs/core/lib/json.lib.php index dc87a04224a..69dbb4eba1a 100644 --- a/htdocs/core/lib/json.lib.php +++ b/htdocs/core/lib/json.lib.php @@ -23,16 +23,194 @@ * \ingroup core */ +if (! function_exists('json_encode')) +{ + /** + * Implement json_encode for PHP that does not support it + * + * @param mixed $elements PHP Object to json encode + * @return string Json encoded string + */ + function json_encode($elements) + { + return dol_json_encode($elements); + } +} + /** * Implement json_encode for PHP that does not support it * * @param mixed $elements PHP Object to json encode * @return string Json encoded string - * @deprecated Use json_encode native function */ function dol_json_encode($elements) { - return json_encode($elements); + $num=count($elements); + if (is_object($elements)) // Count number of properties for an object + { + $num=0; + foreach($elements as $key => $value) $num++; + } + //var_dump($num); + + // determine type + if (is_numeric(key($elements)) && key($elements) == 0) + { + // indexed (list) + $keysofelements=array_keys($elements); // Elements array mus have key that does not start with 0 and end with num-1, so we will use this later. + $output = '['; + for ($i = 0, $last = ($num - 1); $i < $num; $i++) + { + if (! isset($elements[$keysofelements[$i]])) continue; + if (is_array($elements[$keysofelements[$i]]) || is_object($elements[$keysofelements[$i]])) $output.= json_encode($elements[$keysofelements[$i]]); + else $output .= _val($elements[$keysofelements[$i]]); + if ($i !== $last) $output.= ','; + } + $output.= ']'; + } + else + { + // associative (object) + $output = '{'; + $last = $num - 1; + $i = 0; + $tmpelements=array(); + if (is_array($elements)) $tmpelements=$elements; + if (is_object($elements)) $tmpelements=get_object_vars($elements); + foreach($tmpelements as $key => $value) + { + $output .= '"'.$key.'":'; + if (is_array($value)) $output.= json_encode($value); + else $output .= _val($value); + if ($i !== $last) $output.= ','; + ++$i; + } + $output.= '}'; + } + + // return + return $output; +} + +/** + * Return text according to type + * + * @param mixed $val Value to show + * @return string Formated value + */ +function _val($val) +{ + if (is_string($val)) + { + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT + $ascii = ''; + $strlen_var = strlen($val); + + /* + * Iterate over every character in the string, + * escaping with a slash or encoding to UTF-8 where necessary + */ + for ($c = 0; $c < $strlen_var; ++$c) { + + $ord_var_c = ord($val{$c}); + + switch (true) { + case $ord_var_c == 0x08: + $ascii .= '\b'; + break; + case $ord_var_c == 0x09: + $ascii .= '\t'; + break; + case $ord_var_c == 0x0A: + $ascii .= '\n'; + break; + case $ord_var_c == 0x0C: + $ascii .= '\f'; + break; + case $ord_var_c == 0x0D: + $ascii .= '\r'; + break; + + case $ord_var_c == 0x22: + case $ord_var_c == 0x2F: + case $ord_var_c == 0x5C: + // double quote, slash, slosh + $ascii .= '\\'.$val{$c}; + break; + + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): + // characters U-00000000 - U-0000007F (same as ASCII) + $ascii .= $val{$c}; + break; + + case (($ord_var_c & 0xE0) == 0xC0): + // characters U-00000080 - U-000007FF, mask 110XXXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($val{$c + 1})); + $c += 1; + $utf16 = utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF0) == 0xE0): + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($val{$c + 1}), ord($val{$c + 2})); + $c += 2; + $utf16 = utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF8) == 0xF0): + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($val{$c + 1}), ord($val{$c + 2}), ord($val{$c + 3})); + $c += 3; + $utf16 = utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFC) == 0xF8): + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($val{$c + 1}), ord($val{$c + 2}), ord($val{$c + 3}), ord($val{$c + 4})); + $c += 4; + $utf16 = utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFE) == 0xFC): + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($val{$c + 1}), ord($val{$c + 2}), ord($val{$c + 3}), ord($val{$c + 4}), ord($val{$c + 5})); + $c += 5; + $utf16 = utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + } + } + + return '"'.$ascii.'"'; + } + elseif (is_int($val)) return sprintf('%d', $val); + elseif (is_float($val)) return sprintf('%F', $val); + elseif (is_bool($val)) return ($val ? 'true' : 'false'); + else return 'null'; +} + +if (! function_exists('json_decode')) +{ + /** + * Implement json_decode for PHP that does not support it + * + * @param string $json Json encoded to PHP Object or Array + * @param bool $assoc False return an object, true return an array + * @return mixed Object or Array + */ + function json_decode($json, $assoc=false) + { + return dol_json_decode($json, $assoc); + } } /** @@ -41,11 +219,69 @@ function dol_json_encode($elements) * @param string $json Json encoded to PHP Object or Array * @param bool $assoc False return an object, true return an array. Try to always use it with true ! * @return mixed Object or Array - * @deprecated Use json_decode native function */ function dol_json_decode($json, $assoc=false) { - return json_decode($json, $assoc); + $comment = false; + + $out=''; + $strLength = strlen($json); // Must stay strlen and not dol_strlen because we want technical length, not visible length + for ($i=0; $i<$strLength; $i++) + { + if (! $comment) + { + if (($json[$i] == '{') || ($json[$i] == '[')) $out.= 'array('; + else if (($json[$i] == '}') || ($json[$i] == ']')) $out.= ')'; + else if ($json[$i] == ':') $out.= ' => '; + else $out.=$json[$i]; + } + else $out.= $json[$i]; + if ($json[$i] == '"' && $json[($i-1)]!="\\") $comment = !$comment; + } + + $out=_unval($out); + + // Return an array + if ($out != '') eval('$array = '.$out.';'); + else $array=array(); + + // Return an object + if (! $assoc) + { + if (! empty($array)) + { + $object = false; + + foreach ($array as $key => $value) + { + $object->{$key} = $value; + } + + return $object; + } + + return false; + } + + return $array; +} + +/** + * Return text according to type + * + * @param mixed $val Value to decode + * @return string Formated value + */ +function _unval($val) +{ + while (preg_match('/\\\u([0-9A-F]{2})([0-9A-F]{2})/i', $val, $reg)) + { + // single, escaped unicode character + $utf16 = chr(hexdec($reg[1])) . chr(hexdec($reg[2])); + $utf8 = utf162utf8($utf16); + $val=preg_replace('/\\\u'.$reg[1].$reg[2].'/i',$utf8,$val); + } + return $val; } /**