This source file includes following definitions.
- PHP_MINIT_FUNCTION
- PHP_GINIT_FUNCTION
- ZEND_GET_MODULE
- json_determine_array_type
- json_pretty_print_char
- json_pretty_print_indent
- json_encode_array
- json_utf8_to_utf16
- json_escape_string
- json_encode_serializable_object
- php_json_encode
- php_json_decode_ex
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "ext/standard/html.h"
29 #include "ext/standard/php_smart_str.h"
30 #include "JSON_parser.h"
31 #include "php_json.h"
32 #include <zend_exceptions.h>
33
34 #include <float.h>
35 #if defined(DBL_MANT_DIG) && defined(DBL_MIN_EXP)
36 #define NUM_BUF_SIZE (3 + DBL_MANT_DIG - DBL_MIN_EXP)
37 #else
38 #define NUM_BUF_SIZE 1080
39 #endif
40
41
42 static PHP_MINFO_FUNCTION(json);
43 static PHP_FUNCTION(json_encode);
44 static PHP_FUNCTION(json_decode);
45 static PHP_FUNCTION(json_last_error);
46 static PHP_FUNCTION(json_last_error_msg);
47
48 static const char digits[] = "0123456789abcdef";
49
50 PHP_JSON_API zend_class_entry *php_json_serializable_ce;
51
52 ZEND_DECLARE_MODULE_GLOBALS(json)
53
54
55 ZEND_BEGIN_ARG_INFO_EX(arginfo_json_encode, 0, 0, 1)
56 ZEND_ARG_INFO(0, value)
57 ZEND_ARG_INFO(0, options)
58 ZEND_ARG_INFO(0, depth)
59 ZEND_END_ARG_INFO()
60
61 ZEND_BEGIN_ARG_INFO_EX(arginfo_json_decode, 0, 0, 1)
62 ZEND_ARG_INFO(0, json)
63 ZEND_ARG_INFO(0, assoc)
64 ZEND_ARG_INFO(0, depth)
65 ZEND_ARG_INFO(0, options)
66 ZEND_END_ARG_INFO()
67
68 ZEND_BEGIN_ARG_INFO(arginfo_json_last_error, 0)
69 ZEND_END_ARG_INFO()
70
71 ZEND_BEGIN_ARG_INFO(arginfo_json_last_error_msg, 0)
72 ZEND_END_ARG_INFO()
73
74
75
76 static const zend_function_entry json_functions[] = {
77 PHP_FE(json_encode, arginfo_json_encode)
78 PHP_FE(json_decode, arginfo_json_decode)
79 PHP_FE(json_last_error, arginfo_json_last_error)
80 PHP_FE(json_last_error_msg, arginfo_json_last_error_msg)
81 PHP_FE_END
82 };
83
84
85
86 ZEND_BEGIN_ARG_INFO(json_serialize_arginfo, 0)
87
88 ZEND_END_ARG_INFO();
89
90 static const zend_function_entry json_serializable_interface[] = {
91 PHP_ABSTRACT_ME(JsonSerializable, jsonSerialize, json_serialize_arginfo)
92 PHP_FE_END
93 };
94
95
96
97 static PHP_MINIT_FUNCTION(json)
98 {
99 zend_class_entry ce;
100
101 INIT_CLASS_ENTRY(ce, "JsonSerializable", json_serializable_interface);
102 php_json_serializable_ce = zend_register_internal_interface(&ce TSRMLS_CC);
103
104 REGISTER_LONG_CONSTANT("JSON_HEX_TAG", PHP_JSON_HEX_TAG, CONST_CS | CONST_PERSISTENT);
105 REGISTER_LONG_CONSTANT("JSON_HEX_AMP", PHP_JSON_HEX_AMP, CONST_CS | CONST_PERSISTENT);
106 REGISTER_LONG_CONSTANT("JSON_HEX_APOS", PHP_JSON_HEX_APOS, CONST_CS | CONST_PERSISTENT);
107 REGISTER_LONG_CONSTANT("JSON_HEX_QUOT", PHP_JSON_HEX_QUOT, CONST_CS | CONST_PERSISTENT);
108 REGISTER_LONG_CONSTANT("JSON_FORCE_OBJECT", PHP_JSON_FORCE_OBJECT, CONST_CS | CONST_PERSISTENT);
109 REGISTER_LONG_CONSTANT("JSON_NUMERIC_CHECK", PHP_JSON_NUMERIC_CHECK, CONST_CS | CONST_PERSISTENT);
110 REGISTER_LONG_CONSTANT("JSON_UNESCAPED_SLASHES", PHP_JSON_UNESCAPED_SLASHES, CONST_CS | CONST_PERSISTENT);
111 REGISTER_LONG_CONSTANT("JSON_PRETTY_PRINT", PHP_JSON_PRETTY_PRINT, CONST_CS | CONST_PERSISTENT);
112 REGISTER_LONG_CONSTANT("JSON_UNESCAPED_UNICODE", PHP_JSON_UNESCAPED_UNICODE, CONST_CS | CONST_PERSISTENT);
113 REGISTER_LONG_CONSTANT("JSON_PARTIAL_OUTPUT_ON_ERROR", PHP_JSON_PARTIAL_OUTPUT_ON_ERROR, CONST_CS | CONST_PERSISTENT);
114 REGISTER_LONG_CONSTANT("JSON_PRESERVE_ZERO_FRACTION", PHP_JSON_PRESERVE_ZERO_FRACTION, CONST_CS | CONST_PERSISTENT);
115
116 REGISTER_LONG_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE, CONST_CS | CONST_PERSISTENT);
117 REGISTER_LONG_CONSTANT("JSON_ERROR_DEPTH", PHP_JSON_ERROR_DEPTH, CONST_CS | CONST_PERSISTENT);
118 REGISTER_LONG_CONSTANT("JSON_ERROR_STATE_MISMATCH", PHP_JSON_ERROR_STATE_MISMATCH, CONST_CS | CONST_PERSISTENT);
119 REGISTER_LONG_CONSTANT("JSON_ERROR_CTRL_CHAR", PHP_JSON_ERROR_CTRL_CHAR, CONST_CS | CONST_PERSISTENT);
120 REGISTER_LONG_CONSTANT("JSON_ERROR_SYNTAX", PHP_JSON_ERROR_SYNTAX, CONST_CS | CONST_PERSISTENT);
121 REGISTER_LONG_CONSTANT("JSON_ERROR_UTF8", PHP_JSON_ERROR_UTF8, CONST_CS | CONST_PERSISTENT);
122 REGISTER_LONG_CONSTANT("JSON_ERROR_RECURSION", PHP_JSON_ERROR_RECURSION, CONST_CS | CONST_PERSISTENT);
123 REGISTER_LONG_CONSTANT("JSON_ERROR_INF_OR_NAN", PHP_JSON_ERROR_INF_OR_NAN, CONST_CS | CONST_PERSISTENT);
124 REGISTER_LONG_CONSTANT("JSON_ERROR_UNSUPPORTED_TYPE", PHP_JSON_ERROR_UNSUPPORTED_TYPE, CONST_CS | CONST_PERSISTENT);
125
126 REGISTER_LONG_CONSTANT("JSON_OBJECT_AS_ARRAY", PHP_JSON_OBJECT_AS_ARRAY, CONST_CS | CONST_PERSISTENT);
127 REGISTER_LONG_CONSTANT("JSON_BIGINT_AS_STRING", PHP_JSON_BIGINT_AS_STRING, CONST_CS | CONST_PERSISTENT);
128
129 return SUCCESS;
130 }
131
132
133
134
135 static PHP_GINIT_FUNCTION(json)
136 {
137 json_globals->encoder_depth = 0;
138 json_globals->error_code = 0;
139 json_globals->encode_max_depth = 0;
140 }
141
142
143
144
145
146 zend_module_entry json_module_entry = {
147 STANDARD_MODULE_HEADER,
148 "json",
149 json_functions,
150 PHP_MINIT(json),
151 NULL,
152 NULL,
153 NULL,
154 PHP_MINFO(json),
155 PHP_JSON_VERSION,
156 PHP_MODULE_GLOBALS(json),
157 PHP_GINIT(json),
158 NULL,
159 NULL,
160 STANDARD_MODULE_PROPERTIES_EX
161 };
162
163
164 #ifdef COMPILE_DL_JSON
165 ZEND_GET_MODULE(json)
166 #endif
167
168
169
170 static PHP_MINFO_FUNCTION(json)
171 {
172 php_info_print_table_start();
173 php_info_print_table_row(2, "json support", "enabled");
174 php_info_print_table_row(2, "json version", PHP_JSON_VERSION);
175 php_info_print_table_end();
176 }
177
178
179 static void json_escape_string(smart_str *buf, char *s, int len, int options TSRMLS_DC);
180
181 static int json_determine_array_type(zval **val TSRMLS_DC)
182 {
183 int i;
184 HashTable *myht = HASH_OF(*val);
185
186 i = myht ? zend_hash_num_elements(myht) : 0;
187 if (i > 0) {
188 char *key;
189 ulong index, idx;
190 uint key_len;
191 HashPosition pos;
192
193 zend_hash_internal_pointer_reset_ex(myht, &pos);
194 idx = 0;
195 for (;; zend_hash_move_forward_ex(myht, &pos)) {
196 i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
197 if (i == HASH_KEY_NON_EXISTENT) {
198 break;
199 }
200
201 if (i == HASH_KEY_IS_STRING) {
202 return 1;
203 } else {
204 if (index != idx) {
205 return 1;
206 }
207 }
208 idx++;
209 }
210 }
211
212 return PHP_JSON_OUTPUT_ARRAY;
213 }
214
215
216
217
218 static inline void json_pretty_print_char(smart_str *buf, int options, char c TSRMLS_DC)
219 {
220 if (options & PHP_JSON_PRETTY_PRINT) {
221 smart_str_appendc(buf, c);
222 }
223 }
224
225
226 static inline void json_pretty_print_indent(smart_str *buf, int options TSRMLS_DC)
227 {
228 int i;
229
230 if (options & PHP_JSON_PRETTY_PRINT) {
231 for (i = 0; i < JSON_G(encoder_depth); ++i) {
232 smart_str_appendl(buf, " ", 4);
233 }
234 }
235 }
236
237
238
239
240 static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
241 {
242 int i, r, need_comma = 0;
243 HashTable *myht;
244
245 if (Z_TYPE_PP(val) == IS_ARRAY) {
246 myht = HASH_OF(*val);
247 r = (options & PHP_JSON_FORCE_OBJECT) ? PHP_JSON_OUTPUT_OBJECT : json_determine_array_type(val TSRMLS_CC);
248 } else {
249 myht = Z_OBJPROP_PP(val);
250 r = PHP_JSON_OUTPUT_OBJECT;
251 }
252
253 if (myht && myht->nApplyCount > 1) {
254 JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
255 smart_str_appendl(buf, "null", 4);
256 return;
257 }
258
259 if (r == PHP_JSON_OUTPUT_ARRAY) {
260 smart_str_appendc(buf, '[');
261 } else {
262 smart_str_appendc(buf, '{');
263 }
264
265 ++JSON_G(encoder_depth);
266
267 i = myht ? zend_hash_num_elements(myht) : 0;
268
269 if (i > 0)
270 {
271 char *key;
272 zval **data;
273 ulong index;
274 uint key_len;
275 HashPosition pos;
276 HashTable *tmp_ht;
277
278 zend_hash_internal_pointer_reset_ex(myht, &pos);
279 for (;; zend_hash_move_forward_ex(myht, &pos)) {
280 i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
281 if (i == HASH_KEY_NON_EXISTENT)
282 break;
283
284 if (zend_hash_get_current_data_ex(myht, (void **) &data, &pos) == SUCCESS) {
285 tmp_ht = HASH_OF(*data);
286 if (tmp_ht) {
287 tmp_ht->nApplyCount++;
288 }
289
290 if (r == PHP_JSON_OUTPUT_ARRAY) {
291 if (need_comma) {
292 smart_str_appendc(buf, ',');
293 } else {
294 need_comma = 1;
295 }
296
297 json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
298 json_pretty_print_indent(buf, options TSRMLS_CC);
299 php_json_encode(buf, *data, options TSRMLS_CC);
300 } else if (r == PHP_JSON_OUTPUT_OBJECT) {
301 if (i == HASH_KEY_IS_STRING) {
302 if (key[0] == '\0' && Z_TYPE_PP(val) == IS_OBJECT) {
303
304 if (tmp_ht) {
305 tmp_ht->nApplyCount--;
306 }
307 continue;
308 }
309
310 if (need_comma) {
311 smart_str_appendc(buf, ',');
312 } else {
313 need_comma = 1;
314 }
315
316 json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
317 json_pretty_print_indent(buf, options TSRMLS_CC);
318
319 json_escape_string(buf, key, key_len - 1, options & ~PHP_JSON_NUMERIC_CHECK TSRMLS_CC);
320 smart_str_appendc(buf, ':');
321
322 json_pretty_print_char(buf, options, ' ' TSRMLS_CC);
323
324 php_json_encode(buf, *data, options TSRMLS_CC);
325 } else {
326 if (need_comma) {
327 smart_str_appendc(buf, ',');
328 } else {
329 need_comma = 1;
330 }
331
332 json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
333 json_pretty_print_indent(buf, options TSRMLS_CC);
334
335 smart_str_appendc(buf, '"');
336 smart_str_append_long(buf, (long) index);
337 smart_str_appendc(buf, '"');
338 smart_str_appendc(buf, ':');
339
340 json_pretty_print_char(buf, options, ' ' TSRMLS_CC);
341
342 php_json_encode(buf, *data, options TSRMLS_CC);
343 }
344 }
345
346 if (tmp_ht) {
347 tmp_ht->nApplyCount--;
348 }
349 }
350 }
351 }
352
353 if (JSON_G(encoder_depth) > JSON_G(encode_max_depth)) {
354 JSON_G(error_code) = PHP_JSON_ERROR_DEPTH;
355 }
356 --JSON_G(encoder_depth);
357
358
359 if (need_comma) {
360 json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
361 json_pretty_print_indent(buf, options TSRMLS_CC);
362 }
363
364 if (r == PHP_JSON_OUTPUT_ARRAY) {
365 smart_str_appendc(buf, ']');
366 } else {
367 smart_str_appendc(buf, '}');
368 }
369 }
370
371
372 static int json_utf8_to_utf16(unsigned short *utf16, char utf8[], int len)
373 {
374 size_t pos = 0, us;
375 int j, status;
376
377 if (utf16) {
378
379 for (j=0 ; pos < len ; j++) {
380 us = php_next_utf8_char((const unsigned char *)utf8, len, &pos, &status);
381 if (status != SUCCESS) {
382 return -1;
383 }
384
385 if (us >= 0x10000) {
386 us -= 0x10000;
387 utf16[j++] = (unsigned short)((us >> 10) | 0xd800);
388 utf16[j] = (unsigned short)((us & 0x3ff) | 0xdc00);
389 } else {
390 utf16[j] = (unsigned short)us;
391 }
392 }
393 } else {
394
395 for (j=0 ; pos < len ; j++) {
396 us = php_next_utf8_char((const unsigned char *)utf8, len, &pos, &status);
397 if (status != SUCCESS) {
398 return -1;
399 }
400 if (us >= 0x10000) {
401 j++;
402 }
403 }
404 }
405 return j;
406 }
407
408
409
410 static void json_escape_string(smart_str *buf, char *s, int len, int options TSRMLS_DC)
411 {
412 int pos = 0, ulen = 0;
413 unsigned short us;
414 unsigned short *utf16;
415 size_t newlen;
416
417 if (len == 0) {
418 smart_str_appendl(buf, "\"\"", 2);
419 return;
420 }
421
422 if (options & PHP_JSON_NUMERIC_CHECK) {
423 double d;
424 int type;
425 long p;
426
427 if ((type = is_numeric_string(s, len, &p, &d, 0)) != 0) {
428 if (type == IS_LONG) {
429 smart_str_append_long(buf, p);
430 return;
431 } else if (type == IS_DOUBLE && !zend_isinf(d) && !zend_isnan(d)) {
432 char num[NUM_BUF_SIZE];
433 int l;
434
435 php_gcvt(d, EG(precision), '.', 'e', (char *)num);
436 l = strlen(num);
437 if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && l < NUM_BUF_SIZE - 2) {
438 num[l++] = '.';
439 num[l++] = '0';
440 num[l] = '\0';
441 }
442 smart_str_appendl(buf, num, l);
443 return;
444 }
445 }
446
447 }
448
449 utf16 = (options & PHP_JSON_UNESCAPED_UNICODE) ? NULL : (unsigned short *) safe_emalloc(len, sizeof(unsigned short), 0);
450 ulen = json_utf8_to_utf16(utf16, s, len);
451 if (ulen <= 0) {
452 if (utf16) {
453 efree(utf16);
454 }
455 if (ulen < 0) {
456 JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
457 smart_str_appendl(buf, "null", 4);
458 } else {
459 smart_str_appendl(buf, "\"\"", 2);
460 }
461 return;
462 }
463 if (!(options & PHP_JSON_UNESCAPED_UNICODE)) {
464 len = ulen;
465 }
466
467
468 smart_str_alloc(buf, len+2, 0);
469 smart_str_appendc(buf, '"');
470
471 while (pos < len)
472 {
473 us = (options & PHP_JSON_UNESCAPED_UNICODE) ? s[pos++] : utf16[pos++];
474
475 switch (us)
476 {
477 case '"':
478 if (options & PHP_JSON_HEX_QUOT) {
479 smart_str_appendl(buf, "\\u0022", 6);
480 } else {
481 smart_str_appendl(buf, "\\\"", 2);
482 }
483 break;
484
485 case '\\':
486 smart_str_appendl(buf, "\\\\", 2);
487 break;
488
489 case '/':
490 if (options & PHP_JSON_UNESCAPED_SLASHES) {
491 smart_str_appendc(buf, '/');
492 } else {
493 smart_str_appendl(buf, "\\/", 2);
494 }
495 break;
496
497 case '\b':
498 smart_str_appendl(buf, "\\b", 2);
499 break;
500
501 case '\f':
502 smart_str_appendl(buf, "\\f", 2);
503 break;
504
505 case '\n':
506 smart_str_appendl(buf, "\\n", 2);
507 break;
508
509 case '\r':
510 smart_str_appendl(buf, "\\r", 2);
511 break;
512
513 case '\t':
514 smart_str_appendl(buf, "\\t", 2);
515 break;
516
517 case '<':
518 if (options & PHP_JSON_HEX_TAG) {
519 smart_str_appendl(buf, "\\u003C", 6);
520 } else {
521 smart_str_appendc(buf, '<');
522 }
523 break;
524
525 case '>':
526 if (options & PHP_JSON_HEX_TAG) {
527 smart_str_appendl(buf, "\\u003E", 6);
528 } else {
529 smart_str_appendc(buf, '>');
530 }
531 break;
532
533 case '&':
534 if (options & PHP_JSON_HEX_AMP) {
535 smart_str_appendl(buf, "\\u0026", 6);
536 } else {
537 smart_str_appendc(buf, '&');
538 }
539 break;
540
541 case '\'':
542 if (options & PHP_JSON_HEX_APOS) {
543 smart_str_appendl(buf, "\\u0027", 6);
544 } else {
545 smart_str_appendc(buf, '\'');
546 }
547 break;
548
549 default:
550 if (us >= ' ' && ((options & PHP_JSON_UNESCAPED_UNICODE) || (us & 127) == us)) {
551 smart_str_appendc(buf, (unsigned char) us);
552 } else {
553 smart_str_appendl(buf, "\\u", 2);
554 smart_str_appendc(buf, digits[(us & 0xf000) >> 12]);
555 smart_str_appendc(buf, digits[(us & 0xf00) >> 8]);
556 smart_str_appendc(buf, digits[(us & 0xf0) >> 4]);
557 smart_str_appendc(buf, digits[(us & 0xf)]);
558 }
559 break;
560 }
561 }
562
563 smart_str_appendc(buf, '"');
564 if (utf16) {
565 efree(utf16);
566 }
567 }
568
569
570
571 static void json_encode_serializable_object(smart_str *buf, zval *val, int options TSRMLS_DC)
572 {
573 zend_class_entry *ce = Z_OBJCE_P(val);
574 zval *retval = NULL, fname;
575 HashTable* myht;
576
577 if (Z_TYPE_P(val) == IS_ARRAY) {
578 myht = HASH_OF(val);
579 } else {
580 myht = Z_OBJPROP_P(val);
581 }
582
583 if (myht && myht->nApplyCount > 1) {
584 JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
585 smart_str_appendl(buf, "null", 4);
586 return;
587 }
588
589 ZVAL_STRING(&fname, "jsonSerialize", 0);
590
591 if (FAILURE == call_user_function_ex(EG(function_table), &val, &fname, &retval, 0, NULL, 1, NULL TSRMLS_CC) || !retval) {
592 zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Failed calling %s::jsonSerialize()", ce->name);
593 smart_str_appendl(buf, "null", sizeof("null") - 1);
594 return;
595 }
596
597 if (EG(exception)) {
598
599 zval_ptr_dtor(&retval);
600 smart_str_appendl(buf, "null", sizeof("null") - 1);
601 return;
602 }
603
604 if ((Z_TYPE_P(retval) == IS_OBJECT) &&
605 (Z_OBJ_HANDLE_P(retval) == Z_OBJ_HANDLE_P(val))) {
606
607 json_encode_array(buf, &retval, options TSRMLS_CC);
608 } else {
609
610 php_json_encode(buf, retval, options TSRMLS_CC);
611 }
612
613 zval_ptr_dtor(&retval);
614 }
615
616
617 PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_DC)
618 {
619 switch (Z_TYPE_P(val))
620 {
621 case IS_NULL:
622 smart_str_appendl(buf, "null", 4);
623 break;
624
625 case IS_BOOL:
626 if (Z_BVAL_P(val)) {
627 smart_str_appendl(buf, "true", 4);
628 } else {
629 smart_str_appendl(buf, "false", 5);
630 }
631 break;
632
633 case IS_LONG:
634 smart_str_append_long(buf, Z_LVAL_P(val));
635 break;
636
637 case IS_DOUBLE:
638 {
639 char num[NUM_BUF_SIZE];
640 int len;
641 double dbl = Z_DVAL_P(val);
642
643 if (!zend_isinf(dbl) && !zend_isnan(dbl)) {
644 php_gcvt(dbl, EG(precision), '.', 'e', (char *)num);
645 len = strlen(num);
646 if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < NUM_BUF_SIZE - 2) {
647 num[len++] = '.';
648 num[len++] = '0';
649 num[len] = '\0';
650 }
651 smart_str_appendl(buf, num, len);
652 } else {
653 JSON_G(error_code) = PHP_JSON_ERROR_INF_OR_NAN;
654 smart_str_appendc(buf, '0');
655 }
656 }
657 break;
658
659 case IS_STRING:
660 json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val), options TSRMLS_CC);
661 break;
662
663 case IS_OBJECT:
664 if (instanceof_function(Z_OBJCE_P(val), php_json_serializable_ce TSRMLS_CC)) {
665 json_encode_serializable_object(buf, val, options TSRMLS_CC);
666 break;
667 }
668
669 case IS_ARRAY:
670 json_encode_array(buf, &val, options TSRMLS_CC);
671 break;
672
673 default:
674 JSON_G(error_code) = PHP_JSON_ERROR_UNSUPPORTED_TYPE;
675 smart_str_appendl(buf, "null", 4);
676 break;
677 }
678
679 return;
680 }
681
682
683 PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len, int options, long depth TSRMLS_DC)
684 {
685 int utf16_len;
686 zval *z;
687 unsigned short *utf16;
688 JSON_parser jp;
689
690 utf16 = (unsigned short *) safe_emalloc((str_len+1), sizeof(unsigned short), 1);
691
692 utf16_len = json_utf8_to_utf16(utf16, str, str_len);
693 if (utf16_len <= 0) {
694 if (utf16) {
695 efree(utf16);
696 }
697 JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
698 RETURN_NULL();
699 }
700
701 if (depth <= 0) {
702 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Depth must be greater than zero");
703 efree(utf16);
704 RETURN_NULL();
705 }
706
707 ALLOC_INIT_ZVAL(z);
708 jp = new_JSON_parser(depth);
709 if (parse_JSON_ex(jp, z, utf16, utf16_len, options TSRMLS_CC)) {
710 *return_value = *z;
711 }
712 else
713 {
714 double d;
715 int type, overflow_info;
716 long p;
717 char *trim = str;
718 int trim_len = str_len;
719
720
721
722 while (trim_len && (*trim == ' ' || *trim == '\t' || *trim == '\n' || *trim == '\r')) {
723 trim++;
724 trim_len--;
725 }
726
727
728 while (trim_len && (trim[trim_len - 1] == ' ' || trim[trim_len - 1] == '\t' || trim[trim_len - 1] == '\n' || trim[trim_len - 1] == '\r')) {
729 trim_len--;
730 }
731
732 RETVAL_NULL();
733 if (trim_len == 4) {
734 if (!strncmp(trim, "null", trim_len)) {
735
736 jp->error_code = PHP_JSON_ERROR_NONE;
737 RETVAL_NULL();
738 } else if (!strncmp(trim, "true", trim_len)) {
739 RETVAL_BOOL(1);
740 }
741 } else if (trim_len == 5 && !strncmp(trim, "false", trim_len)) {
742 RETVAL_BOOL(0);
743 }
744
745 if ((type = is_numeric_string_ex(trim, trim_len, &p, &d, 0, &overflow_info)) != 0) {
746 if (type == IS_LONG) {
747 RETVAL_LONG(p);
748 } else if (type == IS_DOUBLE) {
749 if (options & PHP_JSON_BIGINT_AS_STRING && overflow_info) {
750
751
752
753
754
755 int i;
756 zend_bool is_float = 0;
757
758 for (i = (trim[0] == '-' ? 1 : 0); i < trim_len; i++) {
759
760
761 if (trim[i] < '0' || trim[i] > '9') {
762 is_float = 1;
763 break;
764 }
765 }
766
767 if (is_float) {
768 RETVAL_DOUBLE(d);
769 } else {
770 RETVAL_STRINGL(trim, trim_len, 1);
771 }
772 } else {
773 RETVAL_DOUBLE(d);
774 }
775 }
776 }
777
778 if (Z_TYPE_P(return_value) != IS_NULL) {
779 jp->error_code = PHP_JSON_ERROR_NONE;
780 }
781
782 zval_dtor(z);
783 }
784 FREE_ZVAL(z);
785 efree(utf16);
786 JSON_G(error_code) = jp->error_code;
787 free_JSON_parser(jp);
788 }
789
790
791
792
793
794 static PHP_FUNCTION(json_encode)
795 {
796 zval *parameter;
797 smart_str buf = {0};
798 long options = 0;
799 long depth = JSON_PARSER_DEFAULT_DEPTH;
800
801 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ll", ¶meter, &options, &depth) == FAILURE) {
802 return;
803 }
804
805 JSON_G(error_code) = PHP_JSON_ERROR_NONE;
806
807 JSON_G(encode_max_depth) = depth;
808
809 php_json_encode(&buf, parameter, options TSRMLS_CC);
810
811 if (JSON_G(error_code) != PHP_JSON_ERROR_NONE && !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
812 ZVAL_FALSE(return_value);
813 } else {
814 ZVAL_STRINGL(return_value, buf.c, buf.len, 1);
815 }
816
817 smart_str_free(&buf);
818 }
819
820
821
822
823 static PHP_FUNCTION(json_decode)
824 {
825 char *str;
826 int str_len;
827 zend_bool assoc = 0;
828 long depth = JSON_PARSER_DEFAULT_DEPTH;
829 long options = 0;
830
831 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bll", &str, &str_len, &assoc, &depth, &options) == FAILURE) {
832 return;
833 }
834
835 JSON_G(error_code) = 0;
836
837 if (!str_len) {
838 RETURN_NULL();
839 }
840
841
842 if (assoc) {
843 options |= PHP_JSON_OBJECT_AS_ARRAY;
844 } else {
845 options &= ~PHP_JSON_OBJECT_AS_ARRAY;
846 }
847
848 php_json_decode_ex(return_value, str, str_len, options, depth TSRMLS_CC);
849 }
850
851
852
853
854 static PHP_FUNCTION(json_last_error)
855 {
856 if (zend_parse_parameters_none() == FAILURE) {
857 return;
858 }
859
860 RETURN_LONG(JSON_G(error_code));
861 }
862
863
864
865
866 static PHP_FUNCTION(json_last_error_msg)
867 {
868 if (zend_parse_parameters_none() == FAILURE) {
869 return;
870 }
871
872 switch(JSON_G(error_code)) {
873 case PHP_JSON_ERROR_NONE:
874 RETURN_STRING("No error", 1);
875 case PHP_JSON_ERROR_DEPTH:
876 RETURN_STRING("Maximum stack depth exceeded", 1);
877 case PHP_JSON_ERROR_STATE_MISMATCH:
878 RETURN_STRING("State mismatch (invalid or malformed JSON)", 1);
879 case PHP_JSON_ERROR_CTRL_CHAR:
880 RETURN_STRING("Control character error, possibly incorrectly encoded", 1);
881 case PHP_JSON_ERROR_SYNTAX:
882 RETURN_STRING("Syntax error", 1);
883 case PHP_JSON_ERROR_UTF8:
884 RETURN_STRING("Malformed UTF-8 characters, possibly incorrectly encoded", 1);
885 case PHP_JSON_ERROR_RECURSION:
886 RETURN_STRING("Recursion detected", 1);
887 case PHP_JSON_ERROR_INF_OR_NAN:
888 RETURN_STRING("Inf and NaN cannot be JSON encoded", 1);
889 case PHP_JSON_ERROR_UNSUPPORTED_TYPE:
890 RETURN_STRING("Type is not supported", 1);
891 default:
892 RETURN_STRING("Unknown error", 1);
893 }
894
895 }
896
897
898
899
900
901
902
903
904
905