JSON_POST_ERROR, json_post.onerror.* INI, warning
[m6w6/ext-json_post] / php_json_post.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: json_post |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2015, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
17
18 #include "php.h"
19 #include "php_ini.h"
20 #include "ext/standard/info.h"
21 #include "ext/json/php_json.h"
22 #include "php_json_post.h"
23 #include "SAPI.h"
24
25 ZEND_DECLARE_MODULE_GLOBALS(json_post);
26
27 PHP_INI_BEGIN()
28 STD_PHP_INI_ENTRY("json_post.flags", "1", PHP_INI_PERDIR, OnUpdateLong, flags, zend_json_post_globals, json_post_globals)
29 STD_PHP_INI_ENTRY("json_post.onerror.response", "0", PHP_INI_PERDIR, OnUpdateLong, onerror.response, zend_json_post_globals, json_post_globals)
30 STD_PHP_INI_ENTRY("json_post.onerror.exit", "0", PHP_INI_PERDIR, OnUpdateBool, onerror.exit, zend_json_post_globals, json_post_globals)
31 STD_PHP_INI_ENTRY("json_post.onerror.warning", "0", PHP_INI_PERDIR, OnUpdateBool, onerror.warning, zend_json_post_globals, json_post_globals)
32 PHP_INI_END()
33
34 static void php_json_post_init_globals(zend_json_post_globals *json_post_globals)
35 {
36 memset(json_post_globals, 0, sizeof(*json_post_globals));
37 #if PHP_VERSION_ID >= 50400
38 json_post_globals->flags = PHP_JSON_OBJECT_AS_ARRAY;
39 #else
40 json_post_globals->flags = 1;
41 #endif
42 }
43
44 #if PHP_VERSION_ID < 70000
45 ZEND_EXTERN_MODULE_GLOBALS(json);
46 #endif
47
48 #ifndef TSRMLS_CC
49 # define TSRMLS_C
50 # define TSRMLS_CC
51 #endif
52
53
54 PHP_MINFO_FUNCTION(json_post)
55 {
56 php_info_print_table_start();
57 php_info_print_table_header(2, "json_post support", "enabled");
58 php_info_print_table_end();
59
60 DISPLAY_INI_ENTRIES();
61 }
62
63 static SAPI_POST_HANDLER_FUNC(php_json_post_handler)
64 {
65 int module_number = 0;
66
67 #if PHP_VERSION_ID >= 70000
68 zend_string *json = NULL;
69
70 if (SG(request_info).request_body) {
71 /* FG(stream_wrappers) not initialized yet, so we cannot use php://input */
72 php_stream_rewind(SG(request_info).request_body);
73 json = php_stream_copy_to_mem(SG(request_info).request_body, PHP_STREAM_COPY_ALL, 0);
74 }
75
76 if (json) {
77 if (json->len) {
78 zval tmp;
79 long flags = JSON_POST_G(flags);
80
81 #ifdef PHP_JSON_THROW_ON_ERROR
82 /* there's no execute data, so we must ensure json_decode() is not throwing */
83 flags &= ~PHP_JSON_THROW_ON_ERROR;
84 #endif
85
86 ZVAL_NULL(&tmp);
87 php_json_decode_ex(&tmp, json->val, json->len, flags, PG(max_input_nesting_level));
88
89 switch (Z_TYPE(tmp)) {
90 case IS_OBJECT:
91 case IS_ARRAY:
92 if (zend_hash_num_elements(HASH_OF(&tmp))) {
93 zval_dtor(arg);
94 ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_POST], &tmp);
95 } else {
96 /* PHP-7.4 optimizes empty array */
97 zval_ptr_dtor(&tmp);
98 }
99 break;
100 default:
101 break;
102 }
103 }
104 zend_string_release(json);
105 }
106
107 #else
108
109 zval *zarg = arg;
110 char *json_str = NULL;
111 size_t json_len = 0;
112
113 # if PHP_VERSION_ID >= 50600
114 if (!SG(request_info).request_body) {
115 return;
116 }
117
118 /* FG(stream_wrappers) not initialized yet, so we cannot use php://input */
119 php_stream_rewind(SG(request_info).request_body);
120 json_len = php_stream_copy_to_mem(SG(request_info).request_body, &json_str, PHP_STREAM_COPY_ALL, 0);
121 # else
122 json_str = SG(request_info).raw_post_data;
123 json_len = SG(request_info).raw_post_data_length;
124 # endif
125
126 if (json_len) {
127 zval zjson;
128
129 INIT_ZVAL(zjson);
130
131 # if PHP_VERSION_ID >= 50400
132 php_json_decode_ex(&zjson, json_str, json_len, JSON_POST_G(flags), PG(max_input_nesting_level) TSRMLS_CC);
133 if (Z_TYPE(zjson) != IS_NULL) {
134 zval_dtor(zarg);
135 ZVAL_COPY_VALUE(zarg, (&zjson));
136 # else
137 php_json_decode(&zjson, json_str, json_len, (zend_bool)(JSON_POST_G(flags)&1), PG(max_input_nesting_level) TSRMLS_CC);
138 if (Z_TYPE(zjson) != IS_NULL) {
139 zval_dtor(zarg);
140 zarg->value = zjson.value;
141 Z_TYPE_P(zarg) = Z_TYPE(zjson);
142 # endif
143 }
144 }
145 # if PHP_VERSION_ID >= 50600
146 if (json_str) {
147 efree(json_str);
148 }
149 # endif
150 #endif
151
152 REGISTER_LONG_CONSTANT("JSON_POST_ERROR", JSON_G(error_code), CONST_CS);
153
154 if (JSON_G(error_code)) {
155 if (JSON_POST_G(onerror.response)) {
156 sapi_header_op(SAPI_HEADER_SET_STATUS, (void *) (zend_long) JSON_POST_G(onerror.response) TSRMLS_CC);
157 }
158 if (JSON_POST_G(onerror.warning)) {
159 zend_error(E_WARNING, "json_post: json_decode failed with error code: %d", JSON_G(error_code));
160 }
161 if (JSON_POST_G(onerror.exit)) {
162 sapi_send_headers(TSRMLS_C);
163 zend_bailout();
164 }
165 /* ext/json in PHP-7 fails to reset error_code in RINIT */
166 JSON_G(error_code) = 0;
167 }
168 }
169
170 PHP_MINIT_FUNCTION(json_post)
171 {
172 sapi_post_entry json_post_entries[] = {
173 { "text/json", sizeof("text/json")-1, sapi_read_standard_form_data, php_json_post_handler },
174 { "application/json", sizeof("application/json")-1, sapi_read_standard_form_data, php_json_post_handler },
175 { NULL, 0, NULL, NULL }
176 };
177
178 sapi_register_post_entries(json_post_entries TSRMLS_CC);
179
180 ZEND_INIT_MODULE_GLOBALS(json_post, php_json_post_init_globals, NULL);
181 REGISTER_INI_ENTRIES();
182 return SUCCESS;
183 }
184
185 PHP_MSHUTDOWN_FUNCTION(json_post)
186 {
187 UNREGISTER_INI_ENTRIES();
188
189 return SUCCESS;
190 }
191
192 zend_function_entry json_post_functions[] = {
193 {0}
194 };
195
196 static zend_module_dep json_post_module_deps[] = {
197 ZEND_MOD_REQUIRED("json")
198 {NULL, NULL, NULL, 0}
199 };
200
201 zend_module_entry json_post_module_entry = {
202 STANDARD_MODULE_HEADER_EX,
203 NULL,
204 json_post_module_deps,
205 "json_post",
206 json_post_functions,
207 PHP_MINIT(json_post),
208 PHP_MSHUTDOWN(json_post),
209 NULL,
210 NULL,
211 PHP_MINFO(json_post),
212 PHP_JSON_POST_VERSION,
213 STANDARD_MODULE_PROPERTIES
214 };
215 /* }}} */
216
217 #ifdef COMPILE_DL_JSON_POST
218 ZEND_GET_MODULE(json_post)
219 #endif
220
221 /*
222 * Local variables:
223 * tab-width: 4
224 * c-basic-offset: 4
225 * End:
226 * vim600: noet sw=4 ts=4 fdm=marker
227 * vim<600: noet sw=4 ts=4
228 */