dolibarr 19.0.3
json.lib.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2011-2012 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2011-2012 Regis Houssin <regis.houssin@inodbox.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 * or see https://www.gnu.org/
18 */
19
26if (!function_exists('json_encode')) {
33 function json_encode($elements)
34 {
35 return dol_json_encode($elements);
36 }
37}
38
39
50function dol_json_encode($elements)
51{
52 dol_syslog("For better performance, enable the native json in your PHP", LOG_WARNING);
53
54 $num = 0;
55 if (is_object($elements)) { // Count number of properties for an object
56 foreach ($elements as $key => $value) {
57 $num++;
58 }
59 } else {
60 $num = count($elements);
61 }
62 //var_dump($num);
63
64 // determine type
65 if (is_numeric(key($elements)) && key($elements) == 0) {
66 // indexed (list)
67 $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.
68 $output = '[';
69 for ($i = 0, $last = ($num - 1); $i < $num; $i++) {
70 if (!isset($elements[$keysofelements[$i]])) {
71 continue;
72 }
73 if (is_array($elements[$keysofelements[$i]]) || is_object($elements[$keysofelements[$i]])) {
74 $output .= json_encode($elements[$keysofelements[$i]]);
75 } else {
76 $output .= _val($elements[$keysofelements[$i]]);
77 }
78 if ($i !== $last) {
79 $output .= ',';
80 }
81 }
82 $output .= ']';
83 } else {
84 // associative (object)
85 $output = '{';
86 $last = $num - 1;
87 $i = 0;
88 $tmpelements = array();
89 if (is_array($elements)) {
90 $tmpelements = $elements;
91 }
92 if (is_object($elements)) {
93 $tmpelements = get_object_vars($elements);
94 }
95 foreach ($tmpelements as $key => $value) {
96 $output .= '"'.$key.'":';
97 if (is_array($value)) {
98 $output .= json_encode($value);
99 } else {
100 $output .= _val($value);
101 }
102 if ($i !== $last) {
103 $output .= ',';
104 }
105 ++$i;
106 }
107 $output .= '}';
108 }
109
110 // return
111 return $output;
112}
113
120function _val($val)
121{
122 if (is_string($val)) {
123 // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
124 $ascii = '';
125 $strlen_var = strlen($val);
126
127 /*
128 * Iterate over every character in the string,
129 * escaping with a slash or encoding to UTF-8 where necessary
130 */
131 for ($c = 0; $c < $strlen_var; ++$c) {
132 $ord_var_c = ord($val[$c]);
133
134 switch (true) {
135 case $ord_var_c == 0x08:
136 $ascii .= '\b';
137 break;
138 case $ord_var_c == 0x09:
139 $ascii .= '\t';
140 break;
141 case $ord_var_c == 0x0A:
142 $ascii .= '\n';
143 break;
144 case $ord_var_c == 0x0C:
145 $ascii .= '\f';
146 break;
147 case $ord_var_c == 0x0D:
148 $ascii .= '\r';
149 break;
150
151 case $ord_var_c == 0x22:
152 case $ord_var_c == 0x2F:
153 case $ord_var_c == 0x5C:
154 // double quote, slash, slosh
155 $ascii .= '\\'.$val[$c];
156 break;
157
158 case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
159 // characters U-00000000 - U-0000007F (same as ASCII)
160 $ascii .= $val[$c];
161 break;
162
163 case (($ord_var_c & 0xE0) == 0xC0):
164 // characters U-00000080 - U-000007FF, mask 110XXXXX
165 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
166 $char = pack('C*', $ord_var_c, ord($val[$c + 1]));
167 $c += 1;
168 $utf16 = utf82utf16($char);
169 $ascii .= sprintf('\u%04s', bin2hex($utf16));
170 break;
171
172 case (($ord_var_c & 0xF0) == 0xE0):
173 // characters U-00000800 - U-0000FFFF, mask 1110XXXX
174 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
175 $char = pack('C*', $ord_var_c, ord($val[$c + 1]), ord($val[$c + 2]));
176 $c += 2;
177 $utf16 = utf82utf16($char);
178 $ascii .= sprintf('\u%04s', bin2hex($utf16));
179 break;
180
181 case (($ord_var_c & 0xF8) == 0xF0):
182 // characters U-00010000 - U-001FFFFF, mask 11110XXX
183 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
184 $char = pack('C*', $ord_var_c, ord($val[$c + 1]), ord($val[$c + 2]), ord($val[$c + 3]));
185 $c += 3;
186 $utf16 = utf82utf16($char);
187 $ascii .= sprintf('\u%04s', bin2hex($utf16));
188 break;
189
190 case (($ord_var_c & 0xFC) == 0xF8):
191 // characters U-00200000 - U-03FFFFFF, mask 111110XX
192 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
193 $char = pack('C*', $ord_var_c, ord($val[$c + 1]), ord($val[$c + 2]), ord($val[$c + 3]), ord($val[$c + 4]));
194 $c += 4;
195 $utf16 = utf82utf16($char);
196 $ascii .= sprintf('\u%04s', bin2hex($utf16));
197 break;
198
199 case (($ord_var_c & 0xFE) == 0xFC):
200 // characters U-04000000 - U-7FFFFFFF, mask 1111110X
201 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
202 $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]));
203 $c += 5;
204 $utf16 = utf82utf16($char);
205 $ascii .= sprintf('\u%04s', bin2hex($utf16));
206 break;
207 }
208 }
209
210 return '"'.$ascii.'"';
211 } elseif (is_int($val)) {
212 return sprintf('%d', $val);
213 } elseif (is_float($val)) {
214 return sprintf('%F', $val);
215 } elseif (is_bool($val)) {
216 return ($val ? 'true' : 'false');
217 } else {
218 return 'null';
219 }
220}
221
222if (!function_exists('json_decode')) {
230 function json_decode($json, $assoc = false)
231 {
232 return dol_json_decode($json, $assoc);
233 }
234}
235
245function dol_json_decode($json, $assoc = false)
246{
247 dol_syslog("For better performance, enable the native json in your PHP", LOG_WARNING);
248
249 $comment = false;
250
251 $out = '';
252 $strLength = strlen($json); // Must stay strlen and not dol_strlen because we want technical length, not visible length
253 for ($i = 0; $i < $strLength; $i++) {
254 if (!$comment) {
255 if (($json[$i] == '{') || ($json[$i] == '[')) {
256 $out .= 'array(';
257 } elseif (($json[$i] == '}') || ($json[$i] == ']')) {
258 $out .= ')';
259 } elseif ($json[$i] == ':') {
260 $out .= ' => ';
261 } else {
262 $out .= $json[$i];
263 }
264 } else {
265 $out .= $json[$i];
266 }
267 if ($json[$i] == '"' && $json[($i - 1)] != "\\") {
268 $comment = !$comment;
269 }
270 }
271
272 $out = _unval($out);
273
274 $array = array();
275
276 // Return an array
277 if ($out != '') {
278 try {
279 eval('$array = '.$out.';');
280 } catch (Exception $e) {
281 $array = array();
282 }
283 }
284
285 // Return an object
286 if (!$assoc) {
287 if (!empty($array)) {
288 $object = false;
289 if (count($array) > 0) {
290 $object = (object) array();
291 }
292 foreach ($array as $key => $value) {
293 if ($key) {
294 $object->{$key} = $value;
295 }
296 }
297
298 return $object;
299 }
300
301 return false;
302 }
303
304 return $array;
305}
306
313function _unval($val)
314{
315 $reg = array();
316 while (preg_match('/\\\u([0-9A-F]{2})([0-9A-F]{2})/i', $val, $reg)) {
317 // single, escaped unicode character
318 $utf16 = chr(hexdec($reg[1])).chr(hexdec($reg[2]));
319 $utf8 = utf162utf8($utf16);
320 $val = preg_replace('/\\\u'.$reg[1].$reg[2].'/i', $utf8, $val);
321 }
322 return $val;
323}
324
335function utf162utf8($utf16)
336{
337 // oh please oh please oh please oh please oh please
338 if (function_exists('mb_convert_encoding')) {
339 return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
340 }
341
342 $bytes = (ord($utf16[0]) << 8) | ord($utf16[1]);
343
344 switch (true) {
345 case ((0x7F & $bytes) == $bytes):
346 // this case should never be reached, because we are in ASCII range
347 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
348 return chr($bytes);
349
350 case (0x07FF & $bytes) == $bytes:
351 // return a 2-byte UTF-8 character
352 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
353 return chr(0xC0 | (($bytes >> 6) & 0x1F))
354 . chr(0x80 | ($bytes & 0x3F));
355
356 case (0xFFFF & $bytes) == $bytes:
357 // return a 3-byte UTF-8 character
358 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
359 return chr(0xE0 | (($bytes >> 12) & 0x0F))
360 . chr(0x80 | (($bytes >> 6) & 0x3F))
361 . chr(0x80 | ($bytes & 0x3F));
362 }
363
364 // ignoring UTF-32 for now, sorry
365 return '';
366}
367
378function utf82utf16($utf8)
379{
380 // oh please oh please oh please oh please oh please
381 if (function_exists('mb_convert_encoding')) {
382 return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
383 }
384
385 switch (strlen($utf8)) {
386 case 1:
387 // this case should never be reached, because we are in ASCII range
388 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
389 return $utf8;
390
391 case 2:
392 // return a UTF-16 character from a 2-byte UTF-8 char
393 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
394 return chr(0x07 & (ord($utf8[0]) >> 2)).chr((0xC0 & (ord($utf8[0]) << 6)) | (0x3F & ord($utf8[1])));
395
396 case 3:
397 // return a UTF-16 character from a 3-byte UTF-8 char
398 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
399 return chr((0xF0 & (ord($utf8[0]) << 4)) | (0x0F & (ord($utf8[1]) >> 2))).chr((0xC0 & (ord($utf8[1]) << 6)) | (0x7F & ord($utf8[2])));
400 }
401
402 // ignoring UTF-32 for now, sorry
403 return '';
404}
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
_val($val)
Return text according to type.
Definition json.lib.php:120
if(!function_exists( 'json_decode')) dol_json_decode($json, $assoc=false)
Implement json_decode for PHP that does not support it Use json_encode and json_decode in your code !
Definition json.lib.php:245
utf162utf8($utf16)
Convert a string from one UTF-16 char to one UTF-8 char.
Definition json.lib.php:335
_unval($val)
Return text according to type.
Definition json.lib.php:313
if(!function_exists( 'json_encode')) dol_json_encode($elements)
Implement json_encode for PHP that does not support it.
Definition json.lib.php:50
utf82utf16($utf8)
Convert a string from one UTF-8 char to one UTF-16 char.
Definition json.lib.php:378