json.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2016 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Omar Kilani <omar@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id$ */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include "php.h"
  23. #include "php_ini.h"
  24. #include "ext/standard/info.h"
  25. #include "ext/standard/html.h"
  26. #include "ext/standard/php_smart_str.h"
  27. #include "JSON_parser.h"
  28. #include "php_json.h"
  29. #include <zend_exceptions.h>
  30. #include <float.h>
  31. #if defined(DBL_MANT_DIG) && defined(DBL_MIN_EXP)
  32. #define NUM_BUF_SIZE (3 + DBL_MANT_DIG - DBL_MIN_EXP)
  33. #else
  34. #define NUM_BUF_SIZE 1080
  35. #endif
  36. static PHP_MINFO_FUNCTION(json);
  37. static PHP_FUNCTION(json_encode);
  38. static PHP_FUNCTION(json_decode);
  39. static PHP_FUNCTION(json_last_error);
  40. static PHP_FUNCTION(json_last_error_msg);
  41. static const char digits[] = "0123456789abcdef";
  42. PHP_JSON_API zend_class_entry *php_json_serializable_ce;
  43. ZEND_DECLARE_MODULE_GLOBALS(json)
  44. /* {{{ arginfo */
  45. ZEND_BEGIN_ARG_INFO_EX(arginfo_json_encode, 0, 0, 1)
  46. ZEND_ARG_INFO(0, value)
  47. ZEND_ARG_INFO(0, options)
  48. ZEND_ARG_INFO(0, depth)
  49. ZEND_END_ARG_INFO()
  50. ZEND_BEGIN_ARG_INFO_EX(arginfo_json_decode, 0, 0, 1)
  51. ZEND_ARG_INFO(0, json)
  52. ZEND_ARG_INFO(0, assoc)
  53. ZEND_ARG_INFO(0, depth)
  54. ZEND_ARG_INFO(0, options)
  55. ZEND_END_ARG_INFO()
  56. ZEND_BEGIN_ARG_INFO(arginfo_json_last_error, 0)
  57. ZEND_END_ARG_INFO()
  58. ZEND_BEGIN_ARG_INFO(arginfo_json_last_error_msg, 0)
  59. ZEND_END_ARG_INFO()
  60. /* }}} */
  61. /* {{{ json_functions[] */
  62. static const zend_function_entry json_functions[] = {
  63. PHP_FE(json_encode, arginfo_json_encode)
  64. PHP_FE(json_decode, arginfo_json_decode)
  65. PHP_FE(json_last_error, arginfo_json_last_error)
  66. PHP_FE(json_last_error_msg, arginfo_json_last_error_msg)
  67. PHP_FE_END
  68. };
  69. /* }}} */
  70. /* {{{ JsonSerializable methods */
  71. ZEND_BEGIN_ARG_INFO(json_serialize_arginfo, 0)
  72. /* No arguments */
  73. ZEND_END_ARG_INFO();
  74. static const zend_function_entry json_serializable_interface[] = {
  75. PHP_ABSTRACT_ME(JsonSerializable, jsonSerialize, json_serialize_arginfo)
  76. PHP_FE_END
  77. };
  78. /* }}} */
  79. /* {{{ MINIT */
  80. static PHP_MINIT_FUNCTION(json)
  81. {
  82. zend_class_entry ce;
  83. INIT_CLASS_ENTRY(ce, "JsonSerializable", json_serializable_interface);
  84. php_json_serializable_ce = zend_register_internal_interface(&ce TSRMLS_CC);
  85. REGISTER_LONG_CONSTANT("JSON_HEX_TAG", PHP_JSON_HEX_TAG, CONST_CS | CONST_PERSISTENT);
  86. REGISTER_LONG_CONSTANT("JSON_HEX_AMP", PHP_JSON_HEX_AMP, CONST_CS | CONST_PERSISTENT);
  87. REGISTER_LONG_CONSTANT("JSON_HEX_APOS", PHP_JSON_HEX_APOS, CONST_CS | CONST_PERSISTENT);
  88. REGISTER_LONG_CONSTANT("JSON_HEX_QUOT", PHP_JSON_HEX_QUOT, CONST_CS | CONST_PERSISTENT);
  89. REGISTER_LONG_CONSTANT("JSON_FORCE_OBJECT", PHP_JSON_FORCE_OBJECT, CONST_CS | CONST_PERSISTENT);
  90. REGISTER_LONG_CONSTANT("JSON_NUMERIC_CHECK", PHP_JSON_NUMERIC_CHECK, CONST_CS | CONST_PERSISTENT);
  91. REGISTER_LONG_CONSTANT("JSON_UNESCAPED_SLASHES", PHP_JSON_UNESCAPED_SLASHES, CONST_CS | CONST_PERSISTENT);
  92. REGISTER_LONG_CONSTANT("JSON_PRETTY_PRINT", PHP_JSON_PRETTY_PRINT, CONST_CS | CONST_PERSISTENT);
  93. REGISTER_LONG_CONSTANT("JSON_UNESCAPED_UNICODE", PHP_JSON_UNESCAPED_UNICODE, CONST_CS | CONST_PERSISTENT);
  94. REGISTER_LONG_CONSTANT("JSON_PARTIAL_OUTPUT_ON_ERROR", PHP_JSON_PARTIAL_OUTPUT_ON_ERROR, CONST_CS | CONST_PERSISTENT);
  95. REGISTER_LONG_CONSTANT("JSON_PRESERVE_ZERO_FRACTION", PHP_JSON_PRESERVE_ZERO_FRACTION, CONST_CS | CONST_PERSISTENT);
  96. REGISTER_LONG_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE, CONST_CS | CONST_PERSISTENT);
  97. REGISTER_LONG_CONSTANT("JSON_ERROR_DEPTH", PHP_JSON_ERROR_DEPTH, CONST_CS | CONST_PERSISTENT);
  98. REGISTER_LONG_CONSTANT("JSON_ERROR_STATE_MISMATCH", PHP_JSON_ERROR_STATE_MISMATCH, CONST_CS | CONST_PERSISTENT);
  99. REGISTER_LONG_CONSTANT("JSON_ERROR_CTRL_CHAR", PHP_JSON_ERROR_CTRL_CHAR, CONST_CS | CONST_PERSISTENT);
  100. REGISTER_LONG_CONSTANT("JSON_ERROR_SYNTAX", PHP_JSON_ERROR_SYNTAX, CONST_CS | CONST_PERSISTENT);
  101. REGISTER_LONG_CONSTANT("JSON_ERROR_UTF8", PHP_JSON_ERROR_UTF8, CONST_CS | CONST_PERSISTENT);
  102. REGISTER_LONG_CONSTANT("JSON_ERROR_RECURSION", PHP_JSON_ERROR_RECURSION, CONST_CS | CONST_PERSISTENT);
  103. REGISTER_LONG_CONSTANT("JSON_ERROR_INF_OR_NAN", PHP_JSON_ERROR_INF_OR_NAN, CONST_CS | CONST_PERSISTENT);
  104. REGISTER_LONG_CONSTANT("JSON_ERROR_UNSUPPORTED_TYPE", PHP_JSON_ERROR_UNSUPPORTED_TYPE, CONST_CS | CONST_PERSISTENT);
  105. REGISTER_LONG_CONSTANT("JSON_OBJECT_AS_ARRAY", PHP_JSON_OBJECT_AS_ARRAY, CONST_CS | CONST_PERSISTENT);
  106. REGISTER_LONG_CONSTANT("JSON_BIGINT_AS_STRING", PHP_JSON_BIGINT_AS_STRING, CONST_CS | CONST_PERSISTENT);
  107. return SUCCESS;
  108. }
  109. /* }}} */
  110. /* {{{ PHP_GINIT_FUNCTION
  111. */
  112. static PHP_GINIT_FUNCTION(json)
  113. {
  114. json_globals->encoder_depth = 0;
  115. json_globals->error_code = 0;
  116. json_globals->encode_max_depth = 0;
  117. }
  118. /* }}} */
  119. /* {{{ json_module_entry
  120. */
  121. zend_module_entry json_module_entry = {
  122. STANDARD_MODULE_HEADER,
  123. "json",
  124. json_functions,
  125. PHP_MINIT(json),
  126. NULL,
  127. NULL,
  128. NULL,
  129. PHP_MINFO(json),
  130. PHP_JSON_VERSION,
  131. PHP_MODULE_GLOBALS(json),
  132. PHP_GINIT(json),
  133. NULL,
  134. NULL,
  135. STANDARD_MODULE_PROPERTIES_EX
  136. };
  137. /* }}} */
  138. #ifdef COMPILE_DL_JSON
  139. ZEND_GET_MODULE(json)
  140. #endif
  141. /* {{{ PHP_MINFO_FUNCTION
  142. */
  143. static PHP_MINFO_FUNCTION(json)
  144. {
  145. php_info_print_table_start();
  146. php_info_print_table_row(2, "json support", "enabled");
  147. php_info_print_table_row(2, "json version", PHP_JSON_VERSION);
  148. php_info_print_table_end();
  149. }
  150. /* }}} */
  151. static void json_escape_string(smart_str *buf, char *s, int len, int options TSRMLS_DC);
  152. static int json_determine_array_type(zval **val TSRMLS_DC) /* {{{ */
  153. {
  154. int i;
  155. HashTable *myht = HASH_OF(*val);
  156. i = myht ? zend_hash_num_elements(myht) : 0;
  157. if (i > 0) {
  158. char *key;
  159. ulong index, idx;
  160. uint key_len;
  161. HashPosition pos;
  162. zend_hash_internal_pointer_reset_ex(myht, &pos);
  163. idx = 0;
  164. for (;; zend_hash_move_forward_ex(myht, &pos)) {
  165. i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
  166. if (i == HASH_KEY_NON_EXISTENT) {
  167. break;
  168. }
  169. if (i == HASH_KEY_IS_STRING) {
  170. return 1;
  171. } else {
  172. if (index != idx) {
  173. return 1;
  174. }
  175. }
  176. idx++;
  177. }
  178. }
  179. return PHP_JSON_OUTPUT_ARRAY;
  180. }
  181. /* }}} */
  182. /* {{{ Pretty printing support functions */
  183. static inline void json_pretty_print_char(smart_str *buf, int options, char c TSRMLS_DC) /* {{{ */
  184. {
  185. if (options & PHP_JSON_PRETTY_PRINT) {
  186. smart_str_appendc(buf, c);
  187. }
  188. }
  189. /* }}} */
  190. static inline void json_pretty_print_indent(smart_str *buf, int options TSRMLS_DC) /* {{{ */
  191. {
  192. int i;
  193. if (options & PHP_JSON_PRETTY_PRINT) {
  194. for (i = 0; i < JSON_G(encoder_depth); ++i) {
  195. smart_str_appendl(buf, " ", 4);
  196. }
  197. }
  198. }
  199. /* }}} */
  200. /* }}} */
  201. static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC) /* {{{ */
  202. {
  203. int i, r, need_comma = 0;
  204. HashTable *myht;
  205. if (Z_TYPE_PP(val) == IS_ARRAY) {
  206. myht = HASH_OF(*val);
  207. r = (options & PHP_JSON_FORCE_OBJECT) ? PHP_JSON_OUTPUT_OBJECT : json_determine_array_type(val TSRMLS_CC);
  208. } else {
  209. myht = Z_OBJPROP_PP(val);
  210. r = PHP_JSON_OUTPUT_OBJECT;
  211. }
  212. if (myht && myht->nApplyCount > 1) {
  213. JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
  214. smart_str_appendl(buf, "null", 4);
  215. return;
  216. }
  217. if (r == PHP_JSON_OUTPUT_ARRAY) {
  218. smart_str_appendc(buf, '[');
  219. } else {
  220. smart_str_appendc(buf, '{');
  221. }
  222. ++JSON_G(encoder_depth);
  223. i = myht ? zend_hash_num_elements(myht) : 0;
  224. if (i > 0)
  225. {
  226. char *key;
  227. zval **data;
  228. ulong index;
  229. uint key_len;
  230. HashPosition pos;
  231. HashTable *tmp_ht;
  232. zend_hash_internal_pointer_reset_ex(myht, &pos);
  233. for (;; zend_hash_move_forward_ex(myht, &pos)) {
  234. i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
  235. if (i == HASH_KEY_NON_EXISTENT)
  236. break;
  237. if (zend_hash_get_current_data_ex(myht, (void **) &data, &pos) == SUCCESS) {
  238. tmp_ht = HASH_OF(*data);
  239. if (tmp_ht) {
  240. tmp_ht->nApplyCount++;
  241. }
  242. if (r == PHP_JSON_OUTPUT_ARRAY) {
  243. if (need_comma) {
  244. smart_str_appendc(buf, ',');
  245. } else {
  246. need_comma = 1;
  247. }
  248. json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
  249. json_pretty_print_indent(buf, options TSRMLS_CC);
  250. php_json_encode(buf, *data, options TSRMLS_CC);
  251. } else if (r == PHP_JSON_OUTPUT_OBJECT) {
  252. if (i == HASH_KEY_IS_STRING) {
  253. if (key[0] == '\0' && Z_TYPE_PP(val) == IS_OBJECT) {
  254. /* Skip protected and private members. */
  255. if (tmp_ht) {
  256. tmp_ht->nApplyCount--;
  257. }
  258. continue;
  259. }
  260. if (need_comma) {
  261. smart_str_appendc(buf, ',');
  262. } else {
  263. need_comma = 1;
  264. }
  265. json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
  266. json_pretty_print_indent(buf, options TSRMLS_CC);
  267. json_escape_string(buf, key, key_len - 1, options & ~PHP_JSON_NUMERIC_CHECK TSRMLS_CC);
  268. smart_str_appendc(buf, ':');
  269. json_pretty_print_char(buf, options, ' ' TSRMLS_CC);
  270. php_json_encode(buf, *data, options TSRMLS_CC);
  271. } else {
  272. if (need_comma) {
  273. smart_str_appendc(buf, ',');
  274. } else {
  275. need_comma = 1;
  276. }
  277. json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
  278. json_pretty_print_indent(buf, options TSRMLS_CC);
  279. smart_str_appendc(buf, '"');
  280. smart_str_append_long(buf, (long) index);
  281. smart_str_appendc(buf, '"');
  282. smart_str_appendc(buf, ':');
  283. json_pretty_print_char(buf, options, ' ' TSRMLS_CC);
  284. php_json_encode(buf, *data, options TSRMLS_CC);
  285. }
  286. }
  287. if (tmp_ht) {
  288. tmp_ht->nApplyCount--;
  289. }
  290. }
  291. }
  292. }
  293. if (JSON_G(encoder_depth) > JSON_G(encode_max_depth)) {
  294. JSON_G(error_code) = PHP_JSON_ERROR_DEPTH;
  295. }
  296. --JSON_G(encoder_depth);
  297. /* Only keep closing bracket on same line for empty arrays/objects */
  298. if (need_comma) {
  299. json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
  300. json_pretty_print_indent(buf, options TSRMLS_CC);
  301. }
  302. if (r == PHP_JSON_OUTPUT_ARRAY) {
  303. smart_str_appendc(buf, ']');
  304. } else {
  305. smart_str_appendc(buf, '}');
  306. }
  307. }
  308. /* }}} */
  309. static int json_utf8_to_utf16(unsigned short *utf16, char utf8[], int len) /* {{{ */
  310. {
  311. size_t pos = 0, us;
  312. int j, status;
  313. if (utf16) {
  314. /* really convert the utf8 string */
  315. for (j=0 ; pos < len ; j++) {
  316. us = php_next_utf8_char((const unsigned char *)utf8, len, &pos, &status);
  317. if (status != SUCCESS) {
  318. return -1;
  319. }
  320. /* From http://en.wikipedia.org/wiki/UTF16 */
  321. if (us >= 0x10000) {
  322. us -= 0x10000;
  323. utf16[j++] = (unsigned short)((us >> 10) | 0xd800);
  324. utf16[j] = (unsigned short)((us & 0x3ff) | 0xdc00);
  325. } else {
  326. utf16[j] = (unsigned short)us;
  327. }
  328. }
  329. } else {
  330. /* Only check if utf8 string is valid, and compute utf16 length */
  331. for (j=0 ; pos < len ; j++) {
  332. us = php_next_utf8_char((const unsigned char *)utf8, len, &pos, &status);
  333. if (status != SUCCESS) {
  334. return -1;
  335. }
  336. if (us >= 0x10000) {
  337. j++;
  338. }
  339. }
  340. }
  341. return j;
  342. }
  343. /* }}} */
  344. static void json_escape_string(smart_str *buf, char *s, int len, int options TSRMLS_DC) /* {{{ */
  345. {
  346. int pos = 0, ulen = 0;
  347. unsigned short us;
  348. unsigned short *utf16;
  349. size_t newlen;
  350. if (len == 0) {
  351. smart_str_appendl(buf, "\"\"", 2);
  352. return;
  353. }
  354. if (options & PHP_JSON_NUMERIC_CHECK) {
  355. double d;
  356. int type;
  357. long p;
  358. if ((type = is_numeric_string(s, len, &p, &d, 0)) != 0) {
  359. if (type == IS_LONG) {
  360. smart_str_append_long(buf, p);
  361. return;
  362. } else if (type == IS_DOUBLE && !zend_isinf(d) && !zend_isnan(d)) {
  363. char num[NUM_BUF_SIZE];
  364. int l;
  365. php_gcvt(d, EG(precision), '.', 'e', (char *)num);
  366. l = strlen(num);
  367. if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && l < NUM_BUF_SIZE - 2) {
  368. num[l++] = '.';
  369. num[l++] = '0';
  370. num[l] = '\0';
  371. }
  372. smart_str_appendl(buf, num, l);
  373. return;
  374. }
  375. }
  376. }
  377. utf16 = (options & PHP_JSON_UNESCAPED_UNICODE) ? NULL : (unsigned short *) safe_emalloc(len, sizeof(unsigned short), 0);
  378. ulen = json_utf8_to_utf16(utf16, s, len);
  379. if (ulen <= 0) {
  380. if (utf16) {
  381. efree(utf16);
  382. }
  383. if (ulen < 0) {
  384. JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
  385. smart_str_appendl(buf, "null", 4);
  386. } else {
  387. smart_str_appendl(buf, "\"\"", 2);
  388. }
  389. return;
  390. }
  391. if (!(options & PHP_JSON_UNESCAPED_UNICODE)) {
  392. len = ulen;
  393. }
  394. /* pre-allocate for string length plus 2 quotes */
  395. smart_str_alloc(buf, len+2, 0);
  396. smart_str_appendc(buf, '"');
  397. while (pos < len)
  398. {
  399. us = (options & PHP_JSON_UNESCAPED_UNICODE) ? s[pos++] : utf16[pos++];
  400. switch (us)
  401. {
  402. case '"':
  403. if (options & PHP_JSON_HEX_QUOT) {
  404. smart_str_appendl(buf, "\\u0022", 6);
  405. } else {
  406. smart_str_appendl(buf, "\\\"", 2);
  407. }
  408. break;
  409. case '\\':
  410. smart_str_appendl(buf, "\\\\", 2);
  411. break;
  412. case '/':
  413. if (options & PHP_JSON_UNESCAPED_SLASHES) {
  414. smart_str_appendc(buf, '/');
  415. } else {
  416. smart_str_appendl(buf, "\\/", 2);
  417. }
  418. break;
  419. case '\b':
  420. smart_str_appendl(buf, "\\b", 2);
  421. break;
  422. case '\f':
  423. smart_str_appendl(buf, "\\f", 2);
  424. break;
  425. case '\n':
  426. smart_str_appendl(buf, "\\n", 2);
  427. break;
  428. case '\r':
  429. smart_str_appendl(buf, "\\r", 2);
  430. break;
  431. case '\t':
  432. smart_str_appendl(buf, "\\t", 2);
  433. break;
  434. case '<':
  435. if (options & PHP_JSON_HEX_TAG) {
  436. smart_str_appendl(buf, "\\u003C", 6);
  437. } else {
  438. smart_str_appendc(buf, '<');
  439. }
  440. break;
  441. case '>':
  442. if (options & PHP_JSON_HEX_TAG) {
  443. smart_str_appendl(buf, "\\u003E", 6);
  444. } else {
  445. smart_str_appendc(buf, '>');
  446. }
  447. break;
  448. case '&':
  449. if (options & PHP_JSON_HEX_AMP) {
  450. smart_str_appendl(buf, "\\u0026", 6);
  451. } else {
  452. smart_str_appendc(buf, '&');
  453. }
  454. break;
  455. case '\'':
  456. if (options & PHP_JSON_HEX_APOS) {
  457. smart_str_appendl(buf, "\\u0027", 6);
  458. } else {
  459. smart_str_appendc(buf, '\'');
  460. }
  461. break;
  462. default:
  463. if (us >= ' ' && ((options & PHP_JSON_UNESCAPED_UNICODE) || (us & 127) == us)) {
  464. smart_str_appendc(buf, (unsigned char) us);
  465. } else {
  466. smart_str_appendl(buf, "\\u", 2);
  467. smart_str_appendc(buf, digits[(us & 0xf000) >> 12]);
  468. smart_str_appendc(buf, digits[(us & 0xf00) >> 8]);
  469. smart_str_appendc(buf, digits[(us & 0xf0) >> 4]);
  470. smart_str_appendc(buf, digits[(us & 0xf)]);
  471. }
  472. break;
  473. }
  474. }
  475. smart_str_appendc(buf, '"');
  476. if (utf16) {
  477. efree(utf16);
  478. }
  479. }
  480. /* }}} */
  481. static void json_encode_serializable_object(smart_str *buf, zval *val, int options TSRMLS_DC) /* {{{ */
  482. {
  483. zend_class_entry *ce = Z_OBJCE_P(val);
  484. zval *retval = NULL, fname;
  485. HashTable* myht;
  486. if (Z_TYPE_P(val) == IS_ARRAY) {
  487. myht = HASH_OF(val);
  488. } else {
  489. myht = Z_OBJPROP_P(val);
  490. }
  491. if (myht && myht->nApplyCount > 1) {
  492. JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
  493. smart_str_appendl(buf, "null", 4);
  494. return;
  495. }
  496. ZVAL_STRING(&fname, "jsonSerialize", 0);
  497. if (FAILURE == call_user_function_ex(EG(function_table), &val, &fname, &retval, 0, NULL, 1, NULL TSRMLS_CC) || !retval) {
  498. if (!EG(exception)) {
  499. zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Failed calling %s::jsonSerialize()", ce->name);
  500. }
  501. smart_str_appendl(buf, "null", sizeof("null") - 1);
  502. return;
  503. }
  504. if (EG(exception)) {
  505. /* Error already raised */
  506. zval_ptr_dtor(&retval);
  507. smart_str_appendl(buf, "null", sizeof("null") - 1);
  508. return;
  509. }
  510. if ((Z_TYPE_P(retval) == IS_OBJECT) &&
  511. (Z_OBJ_HANDLE_P(retval) == Z_OBJ_HANDLE_P(val))) {
  512. /* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
  513. json_encode_array(buf, &retval, options TSRMLS_CC);
  514. } else {
  515. /* All other types, encode as normal */
  516. php_json_encode(buf, retval, options TSRMLS_CC);
  517. }
  518. zval_ptr_dtor(&retval);
  519. }
  520. /* }}} */
  521. PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_DC) /* {{{ */
  522. {
  523. switch (Z_TYPE_P(val))
  524. {
  525. case IS_NULL:
  526. smart_str_appendl(buf, "null", 4);
  527. break;
  528. case IS_BOOL:
  529. if (Z_BVAL_P(val)) {
  530. smart_str_appendl(buf, "true", 4);
  531. } else {
  532. smart_str_appendl(buf, "false", 5);
  533. }
  534. break;
  535. case IS_LONG:
  536. smart_str_append_long(buf, Z_LVAL_P(val));
  537. break;
  538. case IS_DOUBLE:
  539. {
  540. char num[NUM_BUF_SIZE];
  541. int len;
  542. double dbl = Z_DVAL_P(val);
  543. if (!zend_isinf(dbl) && !zend_isnan(dbl)) {
  544. php_gcvt(dbl, EG(precision), '.', 'e', (char *)num);
  545. len = strlen(num);
  546. if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < NUM_BUF_SIZE - 2) {
  547. num[len++] = '.';
  548. num[len++] = '0';
  549. num[len] = '\0';
  550. }
  551. smart_str_appendl(buf, num, len);
  552. } else {
  553. JSON_G(error_code) = PHP_JSON_ERROR_INF_OR_NAN;
  554. smart_str_appendc(buf, '0');
  555. }
  556. }
  557. break;
  558. case IS_STRING:
  559. json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val), options TSRMLS_CC);
  560. break;
  561. case IS_OBJECT:
  562. if (instanceof_function(Z_OBJCE_P(val), php_json_serializable_ce TSRMLS_CC)) {
  563. json_encode_serializable_object(buf, val, options TSRMLS_CC);
  564. break;
  565. }
  566. /* fallthrough -- Non-serializable object */
  567. case IS_ARRAY:
  568. json_encode_array(buf, &val, options TSRMLS_CC);
  569. break;
  570. default:
  571. JSON_G(error_code) = PHP_JSON_ERROR_UNSUPPORTED_TYPE;
  572. smart_str_appendl(buf, "null", 4);
  573. break;
  574. }
  575. return;
  576. }
  577. /* }}} */
  578. PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len, int options, long depth TSRMLS_DC) /* {{{ */
  579. {
  580. int utf16_len;
  581. zval *z;
  582. unsigned short *utf16;
  583. JSON_parser jp;
  584. utf16 = (unsigned short *) safe_emalloc((str_len+1), sizeof(unsigned short), 1);
  585. utf16_len = json_utf8_to_utf16(utf16, str, str_len);
  586. if (utf16_len <= 0) {
  587. if (utf16) {
  588. efree(utf16);
  589. }
  590. JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
  591. RETURN_NULL();
  592. }
  593. if (depth <= 0) {
  594. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Depth must be greater than zero");
  595. efree(utf16);
  596. RETURN_NULL();
  597. }
  598. if (depth > INT_MAX) {
  599. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Depth must be lower than %d", INT_MAX);
  600. efree(utf16);
  601. RETURN_NULL();
  602. }
  603. ALLOC_INIT_ZVAL(z);
  604. jp = new_JSON_parser(depth);
  605. if (parse_JSON_ex(jp, z, utf16, utf16_len, options TSRMLS_CC)) {
  606. *return_value = *z;
  607. }
  608. else
  609. {
  610. double d;
  611. int type, overflow_info;
  612. long p;
  613. char *trim = str;
  614. int trim_len = str_len;
  615. /* Increment trimmed string pointer to strip leading whitespace */
  616. /* JSON RFC says to consider as whitespace: space, tab, LF or CR */
  617. while (trim_len && (*trim == ' ' || *trim == '\t' || *trim == '\n' || *trim == '\r')) {
  618. trim++;
  619. trim_len--;
  620. }
  621. /* Decrement trimmed string length to strip trailing whitespace */
  622. while (trim_len && (trim[trim_len - 1] == ' ' || trim[trim_len - 1] == '\t' || trim[trim_len - 1] == '\n' || trim[trim_len - 1] == '\r')) {
  623. trim_len--;
  624. }
  625. RETVAL_NULL();
  626. if (trim_len == 4) {
  627. if (!strncmp(trim, "null", trim_len)) {
  628. /* We need to explicitly clear the error because its an actual NULL and not an error */
  629. jp->error_code = PHP_JSON_ERROR_NONE;
  630. RETVAL_NULL();
  631. } else if (!strncmp(trim, "true", trim_len)) {
  632. RETVAL_BOOL(1);
  633. }
  634. } else if (trim_len == 5 && !strncmp(trim, "false", trim_len)) {
  635. RETVAL_BOOL(0);
  636. }
  637. if ((type = is_numeric_string_ex(trim, trim_len, &p, &d, 0, &overflow_info)) != 0) {
  638. if (type == IS_LONG) {
  639. RETVAL_LONG(p);
  640. } else if (type == IS_DOUBLE) {
  641. if (options & PHP_JSON_BIGINT_AS_STRING && overflow_info) {
  642. /* Within an object or array, a numeric literal is assumed
  643. * to be an integer if and only if it's entirely made up of
  644. * digits (exponent notation will result in the number
  645. * being treated as a double). We'll match that behaviour
  646. * here. */
  647. int i;
  648. zend_bool is_float = 0;
  649. for (i = (trim[0] == '-' ? 1 : 0); i < trim_len; i++) {
  650. /* Not using isdigit() because it's locale specific,
  651. * but we expect JSON input to always be UTF-8. */
  652. if (trim[i] < '0' || trim[i] > '9') {
  653. is_float = 1;
  654. break;
  655. }
  656. }
  657. if (is_float) {
  658. RETVAL_DOUBLE(d);
  659. } else {
  660. RETVAL_STRINGL(trim, trim_len, 1);
  661. }
  662. } else {
  663. RETVAL_DOUBLE(d);
  664. }
  665. }
  666. }
  667. if (Z_TYPE_P(return_value) != IS_NULL) {
  668. jp->error_code = PHP_JSON_ERROR_NONE;
  669. }
  670. zval_dtor(z);
  671. }
  672. FREE_ZVAL(z);
  673. efree(utf16);
  674. JSON_G(error_code) = jp->error_code;
  675. free_JSON_parser(jp);
  676. }
  677. /* }}} */
  678. /* {{{ proto string json_encode(mixed data [, int options[, int depth]])
  679. Returns the JSON representation of a value */
  680. static PHP_FUNCTION(json_encode)
  681. {
  682. zval *parameter;
  683. smart_str buf = {0};
  684. long options = 0;
  685. long depth = JSON_PARSER_DEFAULT_DEPTH;
  686. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ll", &parameter, &options, &depth) == FAILURE) {
  687. return;
  688. }
  689. JSON_G(error_code) = PHP_JSON_ERROR_NONE;
  690. JSON_G(encode_max_depth) = depth;
  691. php_json_encode(&buf, parameter, options TSRMLS_CC);
  692. if (JSON_G(error_code) != PHP_JSON_ERROR_NONE && !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
  693. ZVAL_FALSE(return_value);
  694. } else {
  695. ZVAL_STRINGL(return_value, buf.c, buf.len, 1);
  696. }
  697. smart_str_free(&buf);
  698. }
  699. /* }}} */
  700. /* {{{ proto mixed json_decode(string json [, bool assoc [, long depth]])
  701. Decodes the JSON representation into a PHP value */
  702. static PHP_FUNCTION(json_decode)
  703. {
  704. char *str;
  705. int str_len;
  706. zend_bool assoc = 0; /* return JS objects as PHP objects by default */
  707. long depth = JSON_PARSER_DEFAULT_DEPTH;
  708. long options = 0;
  709. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bll", &str, &str_len, &assoc, &depth, &options) == FAILURE) {
  710. return;
  711. }
  712. JSON_G(error_code) = 0;
  713. if (!str_len) {
  714. RETURN_NULL();
  715. }
  716. /* For BC reasons, the bool $assoc overrides the long $options bit for PHP_JSON_OBJECT_AS_ARRAY */
  717. if (assoc) {
  718. options |= PHP_JSON_OBJECT_AS_ARRAY;
  719. } else {
  720. options &= ~PHP_JSON_OBJECT_AS_ARRAY;
  721. }
  722. php_json_decode_ex(return_value, str, str_len, options, depth TSRMLS_CC);
  723. }
  724. /* }}} */
  725. /* {{{ proto int json_last_error()
  726. Returns the error code of the last json_encode() or json_decode() call. */
  727. static PHP_FUNCTION(json_last_error)
  728. {
  729. if (zend_parse_parameters_none() == FAILURE) {
  730. return;
  731. }
  732. RETURN_LONG(JSON_G(error_code));
  733. }
  734. /* }}} */
  735. /* {{{ proto string json_last_error_msg()
  736. Returns the error string of the last json_encode() or json_decode() call. */
  737. static PHP_FUNCTION(json_last_error_msg)
  738. {
  739. if (zend_parse_parameters_none() == FAILURE) {
  740. return;
  741. }
  742. switch(JSON_G(error_code)) {
  743. case PHP_JSON_ERROR_NONE:
  744. RETURN_STRING("No error", 1);
  745. case PHP_JSON_ERROR_DEPTH:
  746. RETURN_STRING("Maximum stack depth exceeded", 1);
  747. case PHP_JSON_ERROR_STATE_MISMATCH:
  748. RETURN_STRING("State mismatch (invalid or malformed JSON)", 1);
  749. case PHP_JSON_ERROR_CTRL_CHAR:
  750. RETURN_STRING("Control character error, possibly incorrectly encoded", 1);
  751. case PHP_JSON_ERROR_SYNTAX:
  752. RETURN_STRING("Syntax error", 1);
  753. case PHP_JSON_ERROR_UTF8:
  754. RETURN_STRING("Malformed UTF-8 characters, possibly incorrectly encoded", 1);
  755. case PHP_JSON_ERROR_RECURSION:
  756. RETURN_STRING("Recursion detected", 1);
  757. case PHP_JSON_ERROR_INF_OR_NAN:
  758. RETURN_STRING("Inf and NaN cannot be JSON encoded", 1);
  759. case PHP_JSON_ERROR_UNSUPPORTED_TYPE:
  760. RETURN_STRING("Type is not supported", 1);
  761. default:
  762. RETURN_STRING("Unknown error", 1);
  763. }
  764. }
  765. /* }}} */
  766. /*
  767. * Local variables:
  768. * tab-width: 4
  769. * c-basic-offset: 4
  770. * End:
  771. * vim600: noet sw=4 ts=4 fdm=marker
  772. * vim<600: noet sw=4 ts=4
  773. */