@@ -62,7 +62,7 @@ static void php_url_encode_scalar(zval *scalar, smart_str *form_str,
62
62
encoded_data = php_url_encode (Z_STRVAL_P (scalar ), Z_STRLEN_P (scalar ));
63
63
}
64
64
smart_str_append (form_str , encoded_data );
65
- zend_string_free (encoded_data );
65
+ zend_string_release_ex (encoded_data , false );
66
66
break ;
67
67
}
68
68
case IS_LONG :
@@ -77,8 +77,8 @@ static void php_url_encode_scalar(zval *scalar, smart_str *form_str,
77
77
encoded_data = php_url_encode (ZSTR_VAL (tmp ), ZSTR_LEN (tmp ));
78
78
}
79
79
smart_str_append (form_str , encoded_data );
80
- zend_string_free (tmp );
81
- zend_string_free (encoded_data );
80
+ zend_string_release_ex (tmp , false );
81
+ zend_string_release_ex (encoded_data , false );
82
82
break ;
83
83
}
84
84
case IS_FALSE :
@@ -92,11 +92,137 @@ static void php_url_encode_scalar(zval *scalar, smart_str *form_str,
92
92
}
93
93
}
94
94
95
+ static HashTable * php_object_get_visible_properties (/* const */ zend_object * object )
96
+ {
97
+ /* const */ //HashTable *properties = zend_array_dup(object->handlers->get_properties(object));
98
+ /* const */ HashTable * properties = object -> handlers -> get_properties (object );
99
+ //HashTable *visible_properties = zend_new_array(zend_hash_num_elements(properties));
100
+ HashTable * visible_properties = zend_array_dup (object -> handlers -> get_properties (object ));
101
+ zend_string * property_name ;
102
+ zval * value ;
103
+
104
+ ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL (properties , property_name , value ) {
105
+ bool is_dynamic = true;
106
+ if (Z_TYPE_P (value ) == IS_INDIRECT ) {
107
+ value = Z_INDIRECT_P (value );
108
+ if (Z_ISUNDEF_P (value )) {
109
+ continue ;
110
+ }
111
+ is_dynamic = false;
112
+ }
113
+
114
+ if (zend_check_property_access (object , property_name , is_dynamic ) == FAILURE ) {
115
+ /* property not visible in this scope */
116
+ zend_hash_del (visible_properties , property_name );
117
+ continue ;
118
+ }
119
+
120
+ /* handling for private & protected object properties */
121
+ if (ZSTR_VAL (property_name )[0 ] == '\0' ) {
122
+ zend_hash_del (visible_properties , property_name );
123
+
124
+ const char * tmp ;
125
+ const char * unmangled_name ;
126
+ size_t unmangled_name_len ;
127
+ zend_unmangle_property_name_ex (property_name , & tmp , & unmangled_name , & unmangled_name_len );
128
+ zend_hash_str_add (visible_properties , unmangled_name , unmangled_name_len , value );
129
+ }
130
+ } ZEND_HASH_FOREACH_END ();
131
+ //zend_array_destroy(properties);
132
+ return visible_properties ;
133
+ }
134
+
135
+ static zend_string * php_url_encode_get_new_prefix (
136
+ int encoding_type , zend_ulong index_int ,
137
+ const char * index_string , size_t index_string_len ,
138
+ const char * num_prefix , size_t num_prefix_len ,
139
+ const zend_string * key_prefix
140
+ ) {
141
+ zend_string * new_prefix ;
142
+
143
+ if (index_string ) {
144
+ zend_string * encoded_key ;
145
+ if (encoding_type == PHP_QUERY_RFC3986 ) {
146
+ encoded_key = php_raw_url_encode (index_string , index_string_len );
147
+ } else {
148
+ encoded_key = php_url_encode (index_string , index_string_len );
149
+ }
150
+
151
+ if (key_prefix ) {
152
+ new_prefix = zend_string_concat3 (ZSTR_VAL (key_prefix ), ZSTR_LEN (key_prefix ), ZSTR_VAL (encoded_key ), ZSTR_LEN (encoded_key ), "%5D%5B" , strlen ("%5D%5B" ));
153
+ } else {
154
+ new_prefix = zend_string_concat2 (ZSTR_VAL (encoded_key ), ZSTR_LEN (encoded_key ), "%5B" , strlen ("%5B" ));
155
+ }
156
+ zend_string_release_ex (encoded_key , false);
157
+ } else { /* is integer index */
158
+ char * index_int_as_str ;
159
+ size_t index_int_as_str_len ;
160
+
161
+ index_int_as_str_len = spprintf (& index_int_as_str , 0 , ZEND_LONG_FMT , index_int );
162
+
163
+ if (key_prefix && num_prefix ) {
164
+ /* zend_string_concat4() */
165
+ size_t len = ZSTR_LEN (key_prefix ) + num_prefix_len + index_int_as_str_len + strlen ("%5D%5B" );
166
+ new_prefix = zend_string_alloc (len , 0 );
167
+
168
+ memcpy (ZSTR_VAL (new_prefix ), ZSTR_VAL (key_prefix ), ZSTR_LEN (key_prefix ));
169
+ memcpy (ZSTR_VAL (new_prefix ) + ZSTR_LEN (key_prefix ), num_prefix , num_prefix_len );
170
+ memcpy (ZSTR_VAL (new_prefix ) + ZSTR_LEN (key_prefix ) + num_prefix_len , index_int_as_str , index_int_as_str_len );
171
+ memcpy (ZSTR_VAL (new_prefix ) + ZSTR_LEN (key_prefix ) + num_prefix_len + index_int_as_str_len , "%5D%5B" , strlen ("%5D%5B" ));
172
+ ZSTR_VAL (new_prefix )[len ] = '\0' ;
173
+ } else if (key_prefix ) {
174
+ new_prefix = zend_string_concat3 (ZSTR_VAL (key_prefix ), ZSTR_LEN (key_prefix ), index_int_as_str , index_int_as_str_len , "%5D%5B" , strlen ("%5D%5B" ));
175
+ } else if (num_prefix ) {
176
+ new_prefix = zend_string_concat3 (num_prefix , num_prefix_len , index_int_as_str , index_int_as_str_len , "%5B" , strlen ("%5B" ));
177
+ } else {
178
+ new_prefix = zend_string_concat2 (index_int_as_str , index_int_as_str_len , "%5B" , strlen ("%5B" ));
179
+ }
180
+ efree (index_int_as_str );
181
+ }
182
+
183
+ return new_prefix ;
184
+ }
185
+
186
+ static void php_url_encode_object (zend_object * object , smart_str * form_str ,
187
+ int encoding_type , zend_ulong index_int ,
188
+ const char * index_string , size_t index_string_len ,
189
+ const char * num_prefix , size_t num_prefix_len ,
190
+ const zend_string * key_prefix ,
191
+ const zend_string * arg_sep )
192
+ {
193
+ if (GC_IS_RECURSIVE (object )) {
194
+ /* Prevent recursion */
195
+ return ;
196
+ }
197
+
198
+ HashTable * properties = php_object_get_visible_properties (object );
199
+ if (zend_hash_num_elements (properties ) == 0 ) {
200
+ zend_array_destroy (properties );
201
+
202
+ zval tmp ;
203
+ /* If the data object is stringable without visible properties handle it like a string instead of empty array */
204
+ if (object -> handlers -> cast_object (object , & tmp , IS_STRING ) == SUCCESS ) {
205
+ php_url_encode_scalar (& tmp , form_str ,
206
+ encoding_type , index_int ,
207
+ index_string , index_string_len ,
208
+ num_prefix , num_prefix_len ,
209
+ NULL ,
210
+ arg_sep );
211
+ }
212
+ return ;
213
+ }
214
+
215
+ GC_TRY_PROTECT_RECURSION (object );
216
+ php_url_encode_hash_ex (properties , form_str , num_prefix , num_prefix_len , key_prefix , NULL , arg_sep , encoding_type );
217
+ GC_TRY_UNPROTECT_RECURSION (object );
218
+ zend_array_destroy (properties );
219
+ }
220
+
95
221
/* {{{ php_url_encode_hash */
96
222
PHPAPI void php_url_encode_hash_ex (HashTable * ht , smart_str * formstr ,
97
223
const char * num_prefix , size_t num_prefix_len ,
98
224
const zend_string * key_prefix ,
99
- zval * type , const zend_string * arg_sep , int enc_type )
225
+ ZEND_ATTRIBUTE_UNUSED zval * type , const zend_string * arg_sep , int enc_type )
100
226
{
101
227
zend_string * key = NULL ;
102
228
const char * prop_name ;
@@ -118,97 +244,32 @@ PHPAPI void php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
118
244
}
119
245
120
246
ZEND_HASH_FOREACH_KEY_VAL (ht , idx , key , zdata ) {
121
- bool is_dynamic = 1 ;
122
- if (Z_TYPE_P (zdata ) == IS_INDIRECT ) {
123
- zdata = Z_INDIRECT_P (zdata );
124
- if (Z_ISUNDEF_P (zdata )) {
125
- continue ;
126
- }
127
-
128
- is_dynamic = 0 ;
129
- }
130
-
131
- /* handling for private & protected object properties */
132
247
if (key ) {
133
248
prop_name = ZSTR_VAL (key );
134
249
prop_len = ZSTR_LEN (key );
135
-
136
- if (type != NULL && zend_check_property_access (Z_OBJ_P (type ), key , is_dynamic ) != SUCCESS ) {
137
- /* property not visible in this scope */
138
- continue ;
139
- }
140
-
141
- if (ZSTR_VAL (key )[0 ] == '\0' && type != NULL ) {
142
- const char * tmp ;
143
- zend_unmangle_property_name_ex (key , & tmp , & prop_name , & prop_len );
144
- } else {
145
- prop_name = ZSTR_VAL (key );
146
- prop_len = ZSTR_LEN (key );
147
- }
148
250
} else {
149
251
prop_name = NULL ;
150
252
prop_len = 0 ;
151
253
}
152
254
153
255
ZVAL_DEREF (zdata );
154
- if (Z_TYPE_P (zdata ) == IS_ARRAY || Z_TYPE_P (zdata ) == IS_OBJECT ) {
155
- /* If the data object is stringable handle it like a string instead of recursively */
156
- zval tmp ;
157
- if (Z_TYPE_P (zdata ) == IS_OBJECT &&
158
- Z_OBJ_HT_P (zdata )-> cast_object (Z_OBJ_P (zdata ), & tmp , IS_STRING ) == SUCCESS ) {
159
- php_url_encode_scalar (& tmp , formstr ,
160
- enc_type , idx ,
161
- prop_name , prop_len ,
162
- num_prefix , num_prefix_len ,
163
- key_prefix ,
164
- arg_sep );
165
- continue ;
166
- }
167
-
168
- zend_string * new_prefix ;
169
- if (key ) {
170
- zend_string * encoded_key ;
171
- if (enc_type == PHP_QUERY_RFC3986 ) {
172
- encoded_key = php_raw_url_encode (prop_name , prop_len );
173
- } else {
174
- encoded_key = php_url_encode (prop_name , prop_len );
175
- }
176
-
177
- if (key_prefix ) {
178
- new_prefix = zend_string_concat3 (ZSTR_VAL (key_prefix ), ZSTR_LEN (key_prefix ), ZSTR_VAL (encoded_key ), ZSTR_LEN (encoded_key ), "%5D%5B" , strlen ("%5D%5B" ));
179
- } else {
180
- new_prefix = zend_string_concat2 (ZSTR_VAL (encoded_key ), ZSTR_LEN (encoded_key ), "%5B" , strlen ("%5B" ));
181
- }
182
- zend_string_release_ex (encoded_key , false);
183
- } else { /* is integer index */
184
- char * index_int_as_str ;
185
- size_t index_int_as_str_len ;
186
-
187
- index_int_as_str_len = spprintf (& index_int_as_str , 0 , ZEND_LONG_FMT , idx );
188
-
189
- if (key_prefix && num_prefix ) {
190
- /* zend_string_concat4() */
191
- size_t len = ZSTR_LEN (key_prefix ) + num_prefix_len + index_int_as_str_len + strlen ("%5D%5B" );
192
- new_prefix = zend_string_alloc (len , 0 );
193
-
194
- memcpy (ZSTR_VAL (new_prefix ), ZSTR_VAL (key_prefix ), ZSTR_LEN (key_prefix ));
195
- memcpy (ZSTR_VAL (new_prefix ) + ZSTR_LEN (key_prefix ), num_prefix , num_prefix_len );
196
- memcpy (ZSTR_VAL (new_prefix ) + ZSTR_LEN (key_prefix ) + num_prefix_len , index_int_as_str , index_int_as_str_len );
197
- memcpy (ZSTR_VAL (new_prefix ) + ZSTR_LEN (key_prefix ) + num_prefix_len + index_int_as_str_len , "%5D%5B" , strlen ("%5D%5B" ));
198
- ZSTR_VAL (new_prefix )[len ] = '\0' ;
199
- } else if (key_prefix ) {
200
- new_prefix = zend_string_concat3 (ZSTR_VAL (key_prefix ), ZSTR_LEN (key_prefix ), index_int_as_str , index_int_as_str_len , "%5D%5B" , strlen ("%5D%5B" ));
201
- } else if (num_prefix ) {
202
- new_prefix = zend_string_concat3 (num_prefix , num_prefix_len , index_int_as_str , index_int_as_str_len , "%5B" , strlen ("%5B" ));
203
- } else {
204
- new_prefix = zend_string_concat2 (index_int_as_str , index_int_as_str_len , "%5B" , strlen ("%5B" ));
205
- }
206
- efree (index_int_as_str );
207
- }
256
+ if (Z_TYPE_P (zdata ) == IS_ARRAY ) {
257
+ zend_string * new_prefix = php_url_encode_get_new_prefix (enc_type , idx , prop_name , prop_len ,
258
+ num_prefix , num_prefix_len , key_prefix );
208
259
GC_TRY_PROTECT_RECURSION (ht );
209
- php_url_encode_hash_ex (HASH_OF (zdata ), formstr , NULL , 0 , new_prefix , ( Z_TYPE_P ( zdata ) == IS_OBJECT ? zdata : NULL ) , arg_sep , enc_type );
260
+ php_url_encode_hash_ex (Z_ARRVAL_P (zdata ), formstr , NULL , 0 , new_prefix , NULL , arg_sep , enc_type );
210
261
GC_TRY_UNPROTECT_RECURSION (ht );
211
262
zend_string_release_ex (new_prefix , false);
263
+ } else if (Z_TYPE_P (zdata ) == IS_OBJECT ) {
264
+ zend_string * new_prefix = php_url_encode_get_new_prefix (enc_type , idx , prop_name , prop_len ,
265
+ num_prefix , num_prefix_len , key_prefix );
266
+ php_url_encode_object (Z_OBJ_P (zdata ), formstr ,
267
+ enc_type , idx ,
268
+ prop_name , prop_len ,
269
+ num_prefix , num_prefix_len ,
270
+ new_prefix ,
271
+ arg_sep );
272
+ zend_string_release_ex (new_prefix , false);
212
273
} else if (Z_TYPE_P (zdata ) == IS_NULL || Z_TYPE_P (zdata ) == IS_RESOURCE ) {
213
274
/* Skip these types */
214
275
continue ;
@@ -243,17 +304,15 @@ PHP_FUNCTION(http_build_query)
243
304
Z_PARAM_LONG (enc_type )
244
305
ZEND_PARSE_PARAMETERS_END ();
245
306
246
- /* If the data object is stringable handle it like a string instead of recursively */
247
- zval tmp ;
248
- if (Z_TYPE_P (formdata ) == IS_OBJECT && Z_OBJ_HT_P (formdata )-> cast_object (Z_OBJ_P (formdata ), & tmp , IS_STRING ) == SUCCESS ) {
249
- php_url_encode_scalar (& tmp , & formstr ,
250
- enc_type , 0 ,
251
- NULL , 0 ,
307
+ if (Z_TYPE_P (formdata ) == IS_OBJECT ) {
308
+ php_url_encode_object (Z_OBJ_P (formdata ), & formstr ,
309
+ (int ) enc_type , /* int_index */ 0 ,
310
+ /* string_index */ NULL , 0 ,
252
311
prefix , prefix_len ,
253
312
NULL ,
254
313
arg_sep );
255
314
} else {
256
- php_url_encode_hash_ex (HASH_OF (formdata ), & formstr , prefix , prefix_len , /* key_prefix */ NULL , ( Z_TYPE_P ( formdata ) == IS_OBJECT ? formdata : NULL ) , arg_sep , (int )enc_type );
315
+ php_url_encode_hash_ex (Z_ARRVAL_P (formdata ), & formstr , prefix , prefix_len , /* key_prefix */ NULL , NULL , arg_sep , (int )enc_type );
257
316
}
258
317
259
318
RETURN_STR (smart_str_extract (& formstr ));
0 commit comments