release 1.1.0
[m6w6/ext-json_post] / php_json_post.c
index 4a0fcd30387a1d9346461aa53343e017a2e6e76b..643b1738f57467322c6fb4de87b367560939f7f6 100644 (file)
 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
@@ -37,6 +41,12 @@ static void php_json_post_init_globals(zend_json_post_globals *json_post_globals
 #endif
 }
 
+#ifndef TSRMLS_CC
+#      define TSRMLS_D
+#      define TSRMLS_C
+#      define TSRMLS_CC
+#endif
+
 PHP_MINFO_FUNCTION(json_post)
 {
        php_info_print_table_start();
@@ -46,9 +56,20 @@ PHP_MINFO_FUNCTION(json_post)
        DISPLAY_INI_ENTRIES();
 }
 
-#if PHP_VERSION_ID >= 70000
+#if PHP_VERSION_ID < 70000
+#      undef JSON_G
+#      ifdef ZTS
+#              define JSON_G(v) TSRMG(*JSON_POST_G(json_module)->globals_id_ptr, zend_json_globals *, v)
+#      else
+#              define JSON_G(v) ((zend_json_globals *) JSON_POST_G(json_module)->globals_ptr)->v
+#      endif
+#endif
+
 static SAPI_POST_HANDLER_FUNC(php_json_post_handler)
 {
+       int module_number = 0;
+
+#if PHP_VERSION_ID >= 70000
        zend_string *json = NULL;
 
        if (SG(request_info).request_body) {
@@ -60,16 +81,26 @@ static SAPI_POST_HANDLER_FUNC(php_json_post_handler)
        if (json) {
                if (json->len) {
                        zval tmp;
+                       long flags = JSON_POST_G(flags);
 
-                       ZVAL_NULL(&tmp);
+#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
 
-                       php_json_decode_ex(&tmp, json->val, json->len, JSON_POST_G(flags), PG(max_input_nesting_level));
+                       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:
-                               zval_dtor(arg);
-                               ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_POST], &tmp);
+                               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;
@@ -77,12 +108,9 @@ static SAPI_POST_HANDLER_FUNC(php_json_post_handler)
                }
                zend_string_release(json);
        }
-}
 
 #else
 
-static SAPI_POST_HANDLER_FUNC(php_json_post_handler)
-{
        zval *zarg = arg;
        char *json_str = NULL;
        size_t json_len = 0;
@@ -124,9 +152,27 @@ static SAPI_POST_HANDLER_FUNC(php_json_post_handler)
                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();
+               }
+#if PHP_VERSION_ID >= 70000 && PHP_VERSION_ID < 80000
+               /* ext/json in PHP-7 fails to reset error_code in RINIT */
+               JSON_G(error_code) = 0;
 #endif
+       }
+}
 
 PHP_MINIT_FUNCTION(json_post)
 {
@@ -139,6 +185,11 @@ PHP_MINIT_FUNCTION(json_post)
        sapi_register_post_entries(json_post_entries TSRMLS_CC);
 
        ZEND_INIT_MODULE_GLOBALS(json_post, php_json_post_init_globals, NULL);
+
+#if PHP_VERSION_ID < 70000
+       zend_hash_find(&module_registry, ZEND_STRS("json"), (void **) &JSON_POST_G(json_module));
+#endif
+
        REGISTER_INI_ENTRIES();
        return SUCCESS;
 }