ZEND_DECLARE_MODULE_GLOBALS(json_post);
PHP_INI_BEGIN()
- STD_PHP_INI_ENTRY("json_post.flags", "1", PHP_INI_PERDIR, OnUpdateLong, flags, zend_json_post_globals, json_post_globals)
+ STD_PHP_INI_ENTRY("json_post.flags", "1", PHP_INI_PERDIR, OnUpdateLong, flags, zend_json_post_globals, json_post_globals)
+ STD_PHP_INI_ENTRY("json_post.onerror.response", "0", PHP_INI_PERDIR, OnUpdateLong, onerror.response, zend_json_post_globals, json_post_globals)
+ STD_PHP_INI_ENTRY("json_post.onerror.exit", "0", PHP_INI_PERDIR, OnUpdateBool, onerror.exit, zend_json_post_globals, json_post_globals)
+ STD_PHP_INI_ENTRY("json_post.onerror.warning", "0", PHP_INI_PERDIR, OnUpdateBool, onerror.warning, zend_json_post_globals, json_post_globals)
PHP_INI_END()
static void php_json_post_init_globals(zend_json_post_globals *json_post_globals)
{
+ memset(json_post_globals, 0, sizeof(*json_post_globals));
#if PHP_VERSION_ID >= 50400
json_post_globals->flags = PHP_JSON_OBJECT_AS_ARRAY;
#else
#endif
}
+#if PHP_VERSION_ID < 70000
+ZEND_EXTERN_MODULE_GLOBALS(json);
+#endif
+
+#ifndef TSRMLS_CC
+# define TSRMLS_C
+# define TSRMLS_CC
+#endif
+
+
PHP_MINFO_FUNCTION(json_post)
{
php_info_print_table_start();
static SAPI_POST_HANDLER_FUNC(php_json_post_handler)
{
- zval *zarg = arg;
- char *json_str = NULL;
- size_t json_len = 0;
+ int module_number = 0;
+
+#if PHP_VERSION_ID >= 70000
+ zend_string *json = NULL;
-#if PHP_VERSION_ID >= 50600
if (SG(request_info).request_body) {
/* FG(stream_wrappers) not initialized yet, so we cannot use php://input */
php_stream_rewind(SG(request_info).request_body);
- json_len = php_stream_copy_to_mem(SG(request_info).request_body, &json_str, PHP_STREAM_COPY_ALL, 0);
+ json = php_stream_copy_to_mem(SG(request_info).request_body, PHP_STREAM_COPY_ALL, 0);
}
+
+ if (json) {
+ if (json->len) {
+ zval tmp;
+ long flags = JSON_POST_G(flags);
+
+#ifdef PHP_JSON_THROW_ON_ERROR
+ /* there's no execute data, so we must ensure json_decode() is not throwing */
+ flags &= ~PHP_JSON_THROW_ON_ERROR;
+#endif
+
+ ZVAL_NULL(&tmp);
+ php_json_decode_ex(&tmp, json->val, json->len, flags, PG(max_input_nesting_level));
+
+ switch (Z_TYPE(tmp)) {
+ case IS_OBJECT:
+ case IS_ARRAY:
+ if (zend_hash_num_elements(HASH_OF(&tmp))) {
+ zval_dtor(arg);
+ ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_POST], &tmp);
+ } else {
+ /* PHP-7.4 optimizes empty array */
+ zval_ptr_dtor(&tmp);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ zend_string_release(json);
+ }
+
#else
+
+ zval *zarg = arg;
+ char *json_str = NULL;
+ size_t json_len = 0;
+
+# if PHP_VERSION_ID >= 50600
+ if (!SG(request_info).request_body) {
+ return;
+ }
+
+ /* FG(stream_wrappers) not initialized yet, so we cannot use php://input */
+ php_stream_rewind(SG(request_info).request_body);
+ json_len = php_stream_copy_to_mem(SG(request_info).request_body, &json_str, PHP_STREAM_COPY_ALL, 0);
+# else
json_str = SG(request_info).raw_post_data;
json_len = SG(request_info).raw_post_data_length;
-#endif
+# endif
if (json_len) {
zval zjson;
INIT_ZVAL(zjson);
-#if PHP_VERSION_ID >= 50400
+
+# if PHP_VERSION_ID >= 50400
php_json_decode_ex(&zjson, json_str, json_len, JSON_POST_G(flags), PG(max_input_nesting_level) TSRMLS_CC);
if (Z_TYPE(zjson) != IS_NULL) {
zval_dtor(zarg);
ZVAL_COPY_VALUE(zarg, (&zjson));
-#else
+# else
php_json_decode(&zjson, json_str, json_len, (zend_bool)(JSON_POST_G(flags)&1), PG(max_input_nesting_level) TSRMLS_CC);
if (Z_TYPE(zjson) != IS_NULL) {
zval_dtor(zarg);
zarg->value = zjson.value;
Z_TYPE_P(zarg) = Z_TYPE(zjson);
-#endif
+# endif
}
}
-#if PHP_VERSION_ID >= 50600
+# if PHP_VERSION_ID >= 50600
if (json_str) {
efree(json_str);
}
+# endif
#endif
+
+ REGISTER_LONG_CONSTANT("JSON_POST_ERROR", JSON_G(error_code), CONST_CS);
+
+ if (JSON_G(error_code)) {
+ if (JSON_POST_G(onerror.response)) {
+ sapi_header_op(SAPI_HEADER_SET_STATUS, (void *) (zend_long) JSON_POST_G(onerror.response) TSRMLS_CC);
+ }
+ if (JSON_POST_G(onerror.warning)) {
+ zend_error(E_WARNING, "json_post: json_decode failed with error code: %d", JSON_G(error_code));
+ }
+ if (JSON_POST_G(onerror.exit)) {
+ sapi_send_headers(TSRMLS_C);
+ zend_bailout();
+ }
+ /* ext/json in PHP-7 fails to reset error_code in RINIT */
+ JSON_G(error_code) = 0;
+ }
}
PHP_MINIT_FUNCTION(json_post)
{
- sapi_post_entry entry = {NULL, 0, NULL, NULL};
-
- entry.post_reader = sapi_read_standard_form_data;
- entry.post_handler = php_json_post_handler;
+ sapi_post_entry json_post_entries[] = {
+ { "text/json", sizeof("text/json")-1, sapi_read_standard_form_data, php_json_post_handler },
+ { "application/json", sizeof("application/json")-1, sapi_read_standard_form_data, php_json_post_handler },
+ { NULL, 0, NULL, NULL }
+ };
- entry.content_type = "text/json";
- entry.content_type_len = sizeof("text/json")-1;
- sapi_register_post_entry(&entry TSRMLS_CC);
+ sapi_register_post_entries(json_post_entries TSRMLS_CC);
ZEND_INIT_MODULE_GLOBALS(json_post, php_json_post_init_globals, NULL);
REGISTER_INI_ENTRIES();