1/*
2  +----------------------------------------------------------------------+
3  | PHP Version 7                                                        |
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  |         Jakub Zelenka <bukka@php.net>                                |
17  +----------------------------------------------------------------------+
18*/
19
20/* $Id$ */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include "php.h"
27#include "php_ini.h"
28#include "ext/standard/info.h"
29#include "ext/standard/html.h"
30#include "zend_smart_str.h"
31#include "php_json.h"
32#include "php_json_encoder.h"
33#include "php_json_parser.h"
34#include <zend_exceptions.h>
35
36#include <float.h>
37#if defined(DBL_MANT_DIG) && defined(DBL_MIN_EXP)
38#define NUM_BUF_SIZE (3 + DBL_MANT_DIG - DBL_MIN_EXP)
39#else
40#define NUM_BUF_SIZE 1080
41#endif
42
43
44static PHP_MINFO_FUNCTION(json);
45static PHP_FUNCTION(json_encode);
46static PHP_FUNCTION(json_decode);
47static PHP_FUNCTION(json_last_error);
48static PHP_FUNCTION(json_last_error_msg);
49
50PHP_JSON_API zend_class_entry *php_json_serializable_ce;
51
52PHP_JSON_API ZEND_DECLARE_MODULE_GLOBALS(json)
53
54/* {{{ arginfo */
55ZEND_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)
59ZEND_END_ARG_INFO()
60
61ZEND_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)
66ZEND_END_ARG_INFO()
67
68ZEND_BEGIN_ARG_INFO(arginfo_json_last_error, 0)
69ZEND_END_ARG_INFO()
70
71ZEND_BEGIN_ARG_INFO(arginfo_json_last_error_msg, 0)
72ZEND_END_ARG_INFO()
73/* }}} */
74
75/* {{{ json_functions[] */
76static 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/* {{{ JsonSerializable methods */
86ZEND_BEGIN_ARG_INFO(json_serialize_arginfo, 0)
87	/* No arguments */
88ZEND_END_ARG_INFO();
89
90static const zend_function_entry json_serializable_interface[] = {
91	PHP_ABSTRACT_ME(JsonSerializable, jsonSerialize, json_serialize_arginfo)
92	PHP_FE_END
93};
94/* }}} */
95
96/* Register constant for options and errors */
97#define PHP_JSON_REGISTER_CONSTANT(_name, _value) \
98	REGISTER_LONG_CONSTANT(_name,  _value, CONST_CS | CONST_PERSISTENT);
99
100/* {{{ MINIT */
101static PHP_MINIT_FUNCTION(json)
102{
103	zend_class_entry ce;
104
105	INIT_CLASS_ENTRY(ce, "JsonSerializable", json_serializable_interface);
106	php_json_serializable_ce = zend_register_internal_interface(&ce);
107
108	/* options for json_encode */
109	PHP_JSON_REGISTER_CONSTANT("JSON_HEX_TAG",  PHP_JSON_HEX_TAG);
110	PHP_JSON_REGISTER_CONSTANT("JSON_HEX_AMP",  PHP_JSON_HEX_AMP);
111	PHP_JSON_REGISTER_CONSTANT("JSON_HEX_APOS", PHP_JSON_HEX_APOS);
112	PHP_JSON_REGISTER_CONSTANT("JSON_HEX_QUOT", PHP_JSON_HEX_QUOT);
113	PHP_JSON_REGISTER_CONSTANT("JSON_FORCE_OBJECT", PHP_JSON_FORCE_OBJECT);
114	PHP_JSON_REGISTER_CONSTANT("JSON_NUMERIC_CHECK", PHP_JSON_NUMERIC_CHECK);
115	PHP_JSON_REGISTER_CONSTANT("JSON_UNESCAPED_SLASHES", PHP_JSON_UNESCAPED_SLASHES);
116	PHP_JSON_REGISTER_CONSTANT("JSON_PRETTY_PRINT", PHP_JSON_PRETTY_PRINT);
117	PHP_JSON_REGISTER_CONSTANT("JSON_UNESCAPED_UNICODE", PHP_JSON_UNESCAPED_UNICODE);
118	PHP_JSON_REGISTER_CONSTANT("JSON_PARTIAL_OUTPUT_ON_ERROR", PHP_JSON_PARTIAL_OUTPUT_ON_ERROR);
119	PHP_JSON_REGISTER_CONSTANT("JSON_PRESERVE_ZERO_FRACTION", PHP_JSON_PRESERVE_ZERO_FRACTION);
120	PHP_JSON_REGISTER_CONSTANT("JSON_UNESCAPED_LINE_TERMINATORS", PHP_JSON_UNESCAPED_LINE_TERMINATORS);
121
122	/* options for json_decode */
123	PHP_JSON_REGISTER_CONSTANT("JSON_OBJECT_AS_ARRAY", PHP_JSON_OBJECT_AS_ARRAY);
124	PHP_JSON_REGISTER_CONSTANT("JSON_BIGINT_AS_STRING", PHP_JSON_BIGINT_AS_STRING);
125
126	/* json error constants */
127	PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE);
128	PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_DEPTH", PHP_JSON_ERROR_DEPTH);
129	PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_STATE_MISMATCH", PHP_JSON_ERROR_STATE_MISMATCH);
130	PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_CTRL_CHAR", PHP_JSON_ERROR_CTRL_CHAR);
131	PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_SYNTAX", PHP_JSON_ERROR_SYNTAX);
132	PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_UTF8", PHP_JSON_ERROR_UTF8);
133	PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_RECURSION", PHP_JSON_ERROR_RECURSION);
134	PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_INF_OR_NAN", PHP_JSON_ERROR_INF_OR_NAN);
135	PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_UNSUPPORTED_TYPE", PHP_JSON_ERROR_UNSUPPORTED_TYPE);
136	PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_INVALID_PROPERTY_NAME", PHP_JSON_ERROR_INVALID_PROPERTY_NAME);
137	PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_UTF16", PHP_JSON_ERROR_UTF16);
138
139	return SUCCESS;
140}
141/* }}} */
142
143/* {{{ PHP_GINIT_FUNCTION
144*/
145static PHP_GINIT_FUNCTION(json)
146{
147#if defined(COMPILE_DL_JSON) && defined(ZTS)
148	ZEND_TSRMLS_CACHE_UPDATE();
149#endif
150	json_globals->encoder_depth = 0;
151	json_globals->error_code = 0;
152	json_globals->encode_max_depth = 0;
153}
154/* }}} */
155
156
157/* {{{ json_module_entry
158 */
159zend_module_entry json_module_entry = {
160	STANDARD_MODULE_HEADER,
161	"json",
162	json_functions,
163	PHP_MINIT(json),
164	NULL,
165	NULL,
166	NULL,
167	PHP_MINFO(json),
168	PHP_JSON_VERSION,
169	PHP_MODULE_GLOBALS(json),
170	PHP_GINIT(json),
171	NULL,
172	NULL,
173	STANDARD_MODULE_PROPERTIES_EX
174};
175/* }}} */
176
177#ifdef COMPILE_DL_JSON
178#ifdef ZTS
179ZEND_TSRMLS_CACHE_DEFINE()
180#endif
181ZEND_GET_MODULE(json)
182#endif
183
184/* {{{ PHP_MINFO_FUNCTION
185 */
186static PHP_MINFO_FUNCTION(json)
187{
188	php_info_print_table_start();
189	php_info_print_table_row(2, "json support", "enabled");
190	php_info_print_table_row(2, "json version", PHP_JSON_VERSION);
191	php_info_print_table_end();
192}
193/* }}} */
194
195PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options) /* {{{ */
196{
197	php_json_encode_zval(buf, val, options);
198}
199/* }}} */
200
201PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, size_t str_len, zend_long options, zend_long depth) /* {{{ */
202{
203	php_json_parser parser;
204
205	php_json_parser_init(&parser, return_value, str, str_len, (int)options, (int)depth);
206
207	if (php_json_yyparse(&parser)) {
208		JSON_G(error_code) = php_json_parser_error_code(&parser);
209		RETURN_NULL();
210	}
211}
212/* }}} */
213
214/* {{{ proto string json_encode(mixed data [, int options[, int depth]])
215   Returns the JSON representation of a value */
216static PHP_FUNCTION(json_encode)
217{
218	zval *parameter;
219	smart_str buf = {0};
220	zend_long options = 0;
221	zend_long depth = PHP_JSON_PARSER_DEFAULT_DEPTH;
222
223	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|ll", &parameter, &options, &depth) == FAILURE) {
224		return;
225	}
226
227	JSON_G(error_code) = PHP_JSON_ERROR_NONE;
228
229	JSON_G(encode_max_depth) = (int)depth;
230
231	php_json_encode(&buf, parameter, (int)options);
232
233	if (JSON_G(error_code) != PHP_JSON_ERROR_NONE && !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
234		smart_str_free(&buf);
235		ZVAL_FALSE(return_value);
236	} else {
237		smart_str_0(&buf); /* copy? */
238		ZVAL_NEW_STR(return_value, buf.s);
239	}
240}
241/* }}} */
242
243/* {{{ proto mixed json_decode(string json [, bool assoc [, long depth]])
244   Decodes the JSON representation into a PHP value */
245static PHP_FUNCTION(json_decode)
246{
247	char *str;
248	size_t str_len;
249	zend_bool assoc = 0; /* return JS objects as PHP objects by default */
250	zend_long depth = PHP_JSON_PARSER_DEFAULT_DEPTH;
251	zend_long options = 0;
252
253	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|bll", &str, &str_len, &assoc, &depth, &options) == FAILURE) {
254		return;
255	}
256
257	JSON_G(error_code) = PHP_JSON_ERROR_NONE;
258
259	if (!str_len) {
260		JSON_G(error_code) = PHP_JSON_ERROR_SYNTAX;
261		RETURN_NULL();
262	}
263
264	/* For BC reasons, the bool $assoc overrides the long $options bit for PHP_JSON_OBJECT_AS_ARRAY */
265	if (assoc) {
266		options |=  PHP_JSON_OBJECT_AS_ARRAY;
267	} else {
268		options &= ~PHP_JSON_OBJECT_AS_ARRAY;
269	}
270
271	php_json_decode_ex(return_value, str, str_len, options, depth);
272}
273/* }}} */
274
275/* {{{ proto int json_last_error()
276   Returns the error code of the last json_encode() or json_decode() call. */
277static PHP_FUNCTION(json_last_error)
278{
279	if (zend_parse_parameters_none() == FAILURE) {
280		return;
281	}
282
283	RETURN_LONG(JSON_G(error_code));
284}
285/* }}} */
286
287/* {{{ proto string json_last_error_msg()
288   Returns the error string of the last json_encode() or json_decode() call. */
289static PHP_FUNCTION(json_last_error_msg)
290{
291	if (zend_parse_parameters_none() == FAILURE) {
292		return;
293	}
294
295	switch(JSON_G(error_code)) {
296		case PHP_JSON_ERROR_NONE:
297			RETURN_STRING("No error");
298		case PHP_JSON_ERROR_DEPTH:
299			RETURN_STRING("Maximum stack depth exceeded");
300		case PHP_JSON_ERROR_STATE_MISMATCH:
301			RETURN_STRING("State mismatch (invalid or malformed JSON)");
302		case PHP_JSON_ERROR_CTRL_CHAR:
303			RETURN_STRING("Control character error, possibly incorrectly encoded");
304		case PHP_JSON_ERROR_SYNTAX:
305			RETURN_STRING("Syntax error");
306		case PHP_JSON_ERROR_UTF8:
307			RETURN_STRING("Malformed UTF-8 characters, possibly incorrectly encoded");
308		case PHP_JSON_ERROR_RECURSION:
309			RETURN_STRING("Recursion detected");
310		case PHP_JSON_ERROR_INF_OR_NAN:
311			RETURN_STRING("Inf and NaN cannot be JSON encoded");
312		case PHP_JSON_ERROR_UNSUPPORTED_TYPE:
313			RETURN_STRING("Type is not supported");
314		case PHP_JSON_ERROR_INVALID_PROPERTY_NAME:
315			RETURN_STRING("The decoded property name is invalid");
316		case PHP_JSON_ERROR_UTF16:
317			RETURN_STRING("Single unpaired UTF-16 surrogate in unicode escape");
318		default:
319			RETURN_STRING("Unknown error");
320	}
321
322}
323/* }}} */
324
325/*
326 * Local variables:
327 * tab-width: 4
328 * c-basic-offset: 4
329 * End:
330 * vim600: noet sw=4 ts=4 fdm=marker
331 * vim<600: noet sw=4 ts=4
332 */
333