Fix gh-issue #6
[m6w6/ext-http] / php_http_querystring.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: http |
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) 2004-2014, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #include "php_http_api.h"
14
15 #include <php_variables.h>
16 #include <ext/spl/spl_array.h>
17
18 #ifdef PHP_HTTP_HAVE_ICONV
19 # ifndef HAVE_ICONV
20 # define HAVE_ICONV 1
21 # endif
22 # undef PHP_ATOM_INC
23 # include <ext/iconv/php_iconv.h>
24 #endif
25
26 #define QS_MERGE 1
27
28 static inline void php_http_querystring_set(zval *instance, zval *params, int flags TSRMLS_DC)
29 {
30 zval *qa;
31
32 if (flags & QS_MERGE) {
33 qa = php_http_zsep(1, IS_ARRAY, zend_read_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), 0 TSRMLS_CC));
34 } else {
35 MAKE_STD_ZVAL(qa);
36 array_init(qa);
37 }
38
39 php_http_querystring_update(qa, params, NULL TSRMLS_CC);
40 zend_update_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), qa TSRMLS_CC);
41 zval_ptr_dtor(&qa);
42 }
43
44 static inline void php_http_querystring_str(zval *instance, zval *return_value TSRMLS_DC)
45 {
46 zval *qa = zend_read_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), 0 TSRMLS_CC);
47
48 if (Z_TYPE_P(qa) == IS_ARRAY) {
49 php_http_querystring_update(qa, NULL, return_value TSRMLS_CC);
50 } else {
51 RETURN_EMPTY_STRING();
52 }
53 }
54
55 static inline void php_http_querystring_get(zval *this_ptr, int type, char *name, uint name_len, zval *defval, zend_bool del, zval *return_value TSRMLS_DC)
56 {
57 zval **arrval, *qarray = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
58
59 if ((Z_TYPE_P(qarray) == IS_ARRAY) && (SUCCESS == zend_symtable_find(Z_ARRVAL_P(qarray), name, name_len + 1, (void *) &arrval))) {
60 if (type) {
61 zval *value = php_http_ztyp(type, *arrval);
62 RETVAL_ZVAL(value, 1, 1);
63 } else {
64 RETVAL_ZVAL(*arrval, 1, 0);
65 }
66
67 if (del) {
68 zval *delarr;
69
70 MAKE_STD_ZVAL(delarr);
71 array_init(delarr);
72 add_assoc_null_ex(delarr, name, name_len + 1);
73 php_http_querystring_set(this_ptr, delarr, QS_MERGE TSRMLS_CC);
74 zval_ptr_dtor(&delarr);
75 }
76 } else if(defval) {
77 RETURN_ZVAL(defval, 1, 0);
78 }
79 }
80
81 #ifdef PHP_HTTP_HAVE_ICONV
82 ZEND_RESULT_CODE php_http_querystring_xlate(zval *dst, zval *src, const char *ie, const char *oe TSRMLS_DC)
83 {
84 HashPosition pos;
85 zval **entry = NULL;
86 char *xlate_str = NULL, *xkey;
87 size_t xlate_len = 0, xlen;
88 php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
89
90 FOREACH_KEYVAL(pos, src, key, entry) {
91 if (key.type == HASH_KEY_IS_STRING) {
92 if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(key.str, key.len-1, &xkey, &xlen, oe, ie)) {
93 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to convert '%.*s' from '%s' to '%s'", key.len-1, key.str, ie, oe);
94 return FAILURE;
95 }
96 }
97
98 if (Z_TYPE_PP(entry) == IS_STRING) {
99 if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), &xlate_str, &xlate_len, oe, ie)) {
100 if (key.type == HASH_KEY_IS_STRING) {
101 efree(xkey);
102 }
103 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to convert '%.*s' from '%s' to '%s'", Z_STRLEN_PP(entry), Z_STRVAL_PP(entry), ie, oe);
104 return FAILURE;
105 }
106 if (key.type == HASH_KEY_IS_STRING) {
107 add_assoc_stringl_ex(dst, xkey, xlen+1, xlate_str, xlate_len, 0);
108 } else {
109 add_index_stringl(dst, key.num, xlate_str, xlate_len, 0);
110 }
111 } else if (Z_TYPE_PP(entry) == IS_ARRAY) {
112 zval *subarray;
113
114 MAKE_STD_ZVAL(subarray);
115 array_init(subarray);
116 if (key.type == HASH_KEY_IS_STRING) {
117 add_assoc_zval_ex(dst, xkey, xlen+1, subarray);
118 } else {
119 add_index_zval(dst, key.num, subarray);
120 }
121 if (SUCCESS != php_http_querystring_xlate(subarray, *entry, ie, oe TSRMLS_CC)) {
122 if (key.type == HASH_KEY_IS_STRING) {
123 efree(xkey);
124 }
125 return FAILURE;
126 }
127 }
128
129 if (key.type == HASH_KEY_IS_STRING) {
130 efree(xkey);
131 }
132 }
133 return SUCCESS;
134 }
135 #endif /* HAVE_ICONV */
136
137 ZEND_RESULT_CODE php_http_querystring_ctor(zval *instance, zval *params TSRMLS_DC)
138 {
139 php_http_querystring_set(instance, params, 0 TSRMLS_CC);
140 return SUCCESS;
141 }
142
143 static int apply_querystring(void *pData TSRMLS_DC)
144 {
145 zval **val = pData;
146
147 if (Z_TYPE_PP(val) == IS_ARRAY) {
148 zval **zvalue;
149
150 if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(val), ZEND_STRS("value"), (void *) &zvalue)) {
151 zval *tmp = *val;
152
153 Z_ADDREF_PP(zvalue);
154 *val = *zvalue;
155 zval_dtor(tmp);
156 Z_TYPE_P(tmp) = IS_NULL;
157 zval_ptr_dtor(&tmp);
158 }
159 }
160
161 return ZEND_HASH_APPLY_KEEP;
162 }
163
164 ZEND_RESULT_CODE php_http_querystring_parse(HashTable *ht, const char *str, size_t len TSRMLS_DC)
165 {
166 ZEND_RESULT_CODE rv = FAILURE;
167 php_http_params_opts_t opts;
168 php_http_params_token_t psep = { ZEND_STRL("&") }, *psepp[] = { &psep, NULL };
169 php_http_params_token_t vsep = { ZEND_STRL("=") }, *vsepp[] = { &vsep, NULL };
170 const char *asi_str = NULL;
171 size_t asi_len = 0;
172
173 opts.input.str = estrndup(str, len);
174 opts.input.len = len;
175 opts.param = psepp;
176 opts.arg = NULL;
177 opts.val = vsepp;
178 opts.flags = PHP_HTTP_PARAMS_QUERY;
179
180 if (SUCCESS == php_http_ini_entry(ZEND_STRL("arg_separator.input"), &asi_str, &asi_len, 0 TSRMLS_CC) && asi_len) {
181 zval *arr;
182
183 MAKE_STD_ZVAL(arr);
184 array_init_size(arr, asi_len);
185
186 do {
187 add_next_index_stringl(arr, asi_str++, 1, 1);
188 } while (*asi_str);
189
190 opts.param = php_http_params_separator_init(arr TSRMLS_CC);
191
192 zval_ptr_dtor(&arr);
193 }
194
195 MAKE_STD_ZVAL(opts.defval);
196 ZVAL_NULL(opts.defval);
197
198 if (php_http_params_parse(ht, &opts TSRMLS_CC)) {
199 zend_hash_apply(ht, apply_querystring TSRMLS_CC);
200 rv = SUCCESS;
201 }
202
203 if (asi_len) {
204 php_http_params_separator_free(opts.param);
205 }
206
207 zval_ptr_dtor(&opts.defval);
208 efree(opts.input.str);
209 return rv;
210 }
211
212 ZEND_RESULT_CODE php_http_querystring_update(zval *qarray, zval *params, zval *outstring TSRMLS_DC)
213 {
214 /* enforce proper type */
215 if (Z_TYPE_P(qarray) != IS_ARRAY) {
216 convert_to_array(qarray);
217 }
218
219 /* modify qarray */
220 if (params) {
221 HashPosition pos;
222 HashTable *ptr;
223 php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
224 zval **params_entry, **qarray_entry;
225 zval zv, *zv_ptr = NULL;
226
227 INIT_PZVAL(&zv);
228 ZVAL_NULL(&zv);
229
230 /* squeeze the hash out of the zval */
231 if (Z_TYPE_P(params) == IS_OBJECT && instanceof_function(Z_OBJCE_P(params), php_http_querystring_class_entry TSRMLS_CC)) {
232 zv_ptr = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_querystring_class_entry, params, ZEND_STRL("queryArray"), 0 TSRMLS_CC));
233 ptr = Z_ARRVAL_P(zv_ptr);
234 } else if (Z_TYPE_P(params) == IS_OBJECT || Z_TYPE_P(params) == IS_ARRAY) {
235 ptr = HASH_OF(params);
236 } else {
237 zv_ptr = php_http_ztyp(IS_STRING, params);
238 array_init(&zv);
239 php_http_querystring_parse(Z_ARRVAL(zv), Z_STRVAL_P(zv_ptr), Z_STRLEN_P(zv_ptr) TSRMLS_CC);
240 zval_ptr_dtor(&zv_ptr);
241 zv_ptr = NULL;
242 ptr = Z_ARRVAL(zv);
243 }
244
245 FOREACH_HASH_KEYVAL(pos, ptr, key, params_entry) {
246 /* only public properties */
247 if (key.type != HASH_KEY_IS_STRING || *key.str) {
248 if (Z_TYPE_PP(params_entry) == IS_NULL) {
249 /*
250 * delete
251 */
252 if (key.type == HASH_KEY_IS_STRING) {
253 zend_hash_del(Z_ARRVAL_P(qarray), key.str, key.len);
254 } else {
255 zend_hash_index_del(Z_ARRVAL_P(qarray), key.num);
256 }
257 } else if ( ((key.type == HASH_KEY_IS_STRING) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), key.str, key.len, (void *) &qarray_entry)))
258 || ((key.type == HASH_KEY_IS_LONG) && (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(qarray), key.num, (void *) &qarray_entry)))) {
259 /*
260 * update
261 */
262 zval equal, *entry = NULL;
263
264 /* recursive */
265 if (Z_TYPE_PP(params_entry) == IS_ARRAY || Z_TYPE_PP(params_entry) == IS_OBJECT) {
266 entry = php_http_zsep(1, IS_ARRAY, *qarray_entry);
267 php_http_querystring_update(entry, *params_entry, NULL TSRMLS_CC);
268 } else if ((FAILURE == is_equal_function(&equal, *qarray_entry, *params_entry TSRMLS_CC)) || !Z_BVAL(equal)) {
269 Z_ADDREF_PP(params_entry);
270 entry = *params_entry;
271 }
272
273 if (entry) {
274 if (key.type == HASH_KEY_IS_STRING) {
275 zend_hash_update(Z_ARRVAL_P(qarray), key.str, key.len, (void *) &entry, sizeof(zval *), NULL);
276 } else {
277 zend_hash_index_update(Z_ARRVAL_P(qarray), key.num, (void *) &entry, sizeof(zval *), NULL);
278 }
279 }
280 } else {
281 zval *entry;
282 /*
283 * add
284 */
285 if (Z_TYPE_PP(params_entry) == IS_OBJECT) {
286 MAKE_STD_ZVAL(entry);
287 array_init(entry);
288 php_http_querystring_update(entry, *params_entry, NULL TSRMLS_CC);
289 } else {
290 Z_ADDREF_PP(params_entry);
291 entry = *params_entry;
292 }
293 if (key.type == HASH_KEY_IS_STRING) {
294 add_assoc_zval_ex(qarray, key.str, key.len, entry);
295 } else {
296 add_index_zval(qarray, key.num, entry);
297 }
298 }
299 }
300 }
301 /* clean up */
302 if (zv_ptr) {
303 zval_ptr_dtor(&zv_ptr);
304 }
305 zval_dtor(&zv);
306 }
307
308 /* serialize to string */
309 if (outstring) {
310 char *s;
311 size_t l;
312
313 if (SUCCESS == php_http_url_encode_hash(Z_ARRVAL_P(qarray), NULL, 0, &s, &l TSRMLS_CC)) {
314 zval_dtor(outstring);
315 ZVAL_STRINGL(outstring, s, l, 0);
316 } else {
317 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to encode query string");
318 return FAILURE;
319 }
320 }
321
322 return SUCCESS;
323 }
324
325 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString___construct, 0, 0, 0)
326 ZEND_ARG_INFO(0, params)
327 ZEND_END_ARG_INFO();
328 PHP_METHOD(HttpQueryString, __construct)
329 {
330 zval *params = NULL;
331 zend_error_handling zeh;
332
333 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &params), invalid_arg, return);
334
335 zend_replace_error_handling(EH_THROW, php_http_exception_bad_querystring_class_entry, &zeh TSRMLS_CC);
336 php_http_querystring_set(getThis(), params, 0 TSRMLS_CC);
337 zend_restore_error_handling(&zeh TSRMLS_CC);
338 }
339
340 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_getGlobalInstance, 0, 0, 0)
341 ZEND_END_ARG_INFO();
342 PHP_METHOD(HttpQueryString, getGlobalInstance)
343 {
344 zval *instance;
345
346 php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
347
348 instance = *zend_std_get_static_property(php_http_querystring_class_entry, ZEND_STRL("instance"), 0 PHP_HTTP_ZEND_LITERAL_CCN TSRMLS_CC);
349
350 if (Z_TYPE_P(instance) != IS_OBJECT) {
351 zval **_GET = NULL;
352
353 zend_is_auto_global("_GET", lenof("_GET") TSRMLS_CC);
354
355 if ((SUCCESS == zend_hash_find(&EG(symbol_table), "_GET", sizeof("_GET"), (void *) &_GET))
356 && (Z_TYPE_PP(_GET) == IS_ARRAY)
357 ) {
358 MAKE_STD_ZVAL(instance);
359 ZVAL_OBJVAL(instance, php_http_querystring_object_new(php_http_querystring_class_entry TSRMLS_CC), 0);
360
361 SEPARATE_ZVAL_TO_MAKE_IS_REF(_GET);
362 convert_to_array(*_GET);
363 zend_update_property(php_http_querystring_class_entry, instance, ZEND_STRL("queryArray"), *_GET TSRMLS_CC);
364
365 zend_update_static_property(php_http_querystring_class_entry, ZEND_STRL("instance"), instance TSRMLS_CC);
366 zval_ptr_dtor(&instance);
367 } else {
368 php_http_throw(unexpected_val, "Could not acquire reference to superglobal GET array", NULL);
369 }
370 }
371
372 RETVAL_ZVAL(instance, 1, 0);
373 }
374
375 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_getIterator, 0, 0, 0)
376 ZEND_END_ARG_INFO();
377 PHP_METHOD(HttpQueryString, getIterator)
378 {
379 zval *retval = NULL, *qa;
380
381 php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
382
383 qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
384
385 object_init_ex(return_value, spl_ce_RecursiveArrayIterator);
386 zend_call_method_with_1_params(&return_value, spl_ce_RecursiveArrayIterator, NULL, "__construct", &retval, qa);
387 if (retval) {
388 zval_ptr_dtor(&retval);
389 }
390 }
391
392 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_toString, 0, 0, 0)
393 ZEND_END_ARG_INFO();
394 PHP_METHOD(HttpQueryString, toString)
395 {
396 if (SUCCESS != zend_parse_parameters_none()) {
397 return;
398 }
399 php_http_querystring_str(getThis(), return_value TSRMLS_CC);
400 }
401
402 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_toArray, 0, 0, 0)
403 ZEND_END_ARG_INFO();
404 PHP_METHOD(HttpQueryString, toArray)
405 {
406 zval *zqa;
407
408 if (SUCCESS != zend_parse_parameters_none()) {
409 return;
410 }
411
412 zqa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
413 RETURN_ZVAL(zqa, 1, 0);
414 }
415
416 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_get, 0, 0, 0)
417 ZEND_ARG_INFO(0, name)
418 ZEND_ARG_INFO(0, type)
419 ZEND_ARG_INFO(0, defval)
420 ZEND_ARG_INFO(0, delete)
421 ZEND_END_ARG_INFO();
422 PHP_METHOD(HttpQueryString, get)
423 {
424 char *name_str = NULL;
425 int name_len = 0;
426 long type = 0;
427 zend_bool del = 0;
428 zval *ztype = NULL, *defval = NULL;
429
430 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szzb", &name_str, &name_len, &ztype, &defval, &del)) {
431 if (name_str && name_len) {
432 if (ztype) {
433 if (Z_TYPE_P(ztype) == IS_LONG) {
434 type = Z_LVAL_P(ztype);
435 } else if(Z_TYPE_P(ztype) == IS_STRING) {
436 switch (Z_STRVAL_P(ztype)[0]) {
437 case 'B':
438 case 'b': type = PHP_HTTP_QUERYSTRING_TYPE_BOOL; break;
439 case 'L':
440 case 'l':
441 case 'I':
442 case 'i': type = PHP_HTTP_QUERYSTRING_TYPE_INT; break;
443 case 'd':
444 case 'D':
445 case 'F':
446 case 'f': type = PHP_HTTP_QUERYSTRING_TYPE_FLOAT; break;
447 case 'S':
448 case 's': type = PHP_HTTP_QUERYSTRING_TYPE_STRING; break;
449 case 'A':
450 case 'a': type = PHP_HTTP_QUERYSTRING_TYPE_ARRAY; break;
451 case 'O':
452 case 'o': type = PHP_HTTP_QUERYSTRING_TYPE_OBJECT; break;
453 }
454 }
455 }
456 php_http_querystring_get(getThis(), type, name_str, name_len, defval, del, return_value TSRMLS_CC);
457 } else {
458 php_http_querystring_str(getThis(), return_value TSRMLS_CC);
459 }
460 }
461 }
462
463 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_set, 0, 0, 1)
464 ZEND_ARG_INFO(0, params)
465 ZEND_END_ARG_INFO();
466 PHP_METHOD(HttpQueryString, set)
467 {
468 zval *params;
469
470 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &params)) {
471 return;
472 }
473
474 php_http_querystring_set(getThis(), params, QS_MERGE TSRMLS_CC);
475 RETVAL_ZVAL(getThis(), 1, 0);
476 }
477
478 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_mod, 0, 0, 0)
479 ZEND_ARG_INFO(0, params)
480 ZEND_END_ARG_INFO();
481 PHP_METHOD(HttpQueryString, mod)
482 {
483 zval *params;
484 zend_error_handling zeh;
485
486 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &params), invalid_arg, return);
487
488 zend_replace_error_handling(EH_THROW, php_http_exception_bad_querystring_class_entry, &zeh TSRMLS_CC);
489 ZVAL_OBJVAL(return_value, Z_OBJ_HT_P(getThis())->clone_obj(getThis() TSRMLS_CC), 0);
490 php_http_querystring_set(return_value, params, QS_MERGE TSRMLS_CC);
491 zend_restore_error_handling(&zeh TSRMLS_CC);
492 }
493
494 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString___getter, 0, 0, 1)
495 ZEND_ARG_INFO(0, name)
496 ZEND_ARG_INFO(0, defval)
497 ZEND_ARG_INFO(0, delete)
498 ZEND_END_ARG_INFO();
499 #define PHP_HTTP_QUERYSTRING_GETTER(method, TYPE) \
500 PHP_METHOD(HttpQueryString, method) \
501 { \
502 char *name; \
503 int name_len; \
504 zval *defval = NULL; \
505 zend_bool del = 0; \
506 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zb", &name, &name_len, &defval, &del)) { \
507 php_http_querystring_get(getThis(), TYPE, name, name_len, defval, del, return_value TSRMLS_CC); \
508 } \
509 }
510 PHP_HTTP_QUERYSTRING_GETTER(getBool, IS_BOOL);
511 PHP_HTTP_QUERYSTRING_GETTER(getInt, IS_LONG);
512 PHP_HTTP_QUERYSTRING_GETTER(getFloat, IS_DOUBLE);
513 PHP_HTTP_QUERYSTRING_GETTER(getString, IS_STRING);
514 PHP_HTTP_QUERYSTRING_GETTER(getArray, IS_ARRAY);
515 PHP_HTTP_QUERYSTRING_GETTER(getObject, IS_OBJECT);
516
517 #ifdef PHP_HTTP_HAVE_ICONV
518 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_xlate, 0, 0, 2)
519 ZEND_ARG_INFO(0, from_encoding)
520 ZEND_ARG_INFO(0, to_encoding)
521 ZEND_END_ARG_INFO();
522 PHP_METHOD(HttpQueryString, xlate)
523 {
524 char *ie, *oe;
525 int ie_len, oe_len;
526 zval *na, *qa;
527
528 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ie, &ie_len, &oe, &oe_len), invalid_arg, return);
529
530 MAKE_STD_ZVAL(na);
531 array_init(na);
532 qa = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC));
533
534 php_http_expect(SUCCESS == php_http_querystring_xlate(na, qa, ie, oe TSRMLS_CC), bad_conversion,
535 zval_ptr_dtor(&na);
536 zval_ptr_dtor(&qa);
537 return;
538 );
539
540 php_http_querystring_set(getThis(), na, 0 TSRMLS_CC);
541 RETVAL_ZVAL(getThis(), 1, 0);
542
543 zval_ptr_dtor(&na);
544 zval_ptr_dtor(&qa);
545 }
546 #endif /* HAVE_ICONV */
547
548 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_serialize, 0, 0, 0)
549 ZEND_END_ARG_INFO();
550 PHP_METHOD(HttpQueryString, serialize)
551 {
552 if (SUCCESS != zend_parse_parameters_none()) {
553 return;
554 }
555 php_http_querystring_str(getThis(), return_value TSRMLS_CC);
556 }
557
558 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_unserialize, 0, 0, 1)
559 ZEND_ARG_INFO(0, serialized)
560 ZEND_END_ARG_INFO();
561 PHP_METHOD(HttpQueryString, unserialize)
562 {
563 zval *serialized;
564
565 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &serialized)) {
566 return;
567 }
568
569 if (Z_TYPE_P(serialized) == IS_STRING) {
570 php_http_querystring_set(getThis(), serialized, 0 TSRMLS_CC);
571 } else {
572 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected a string as parameter");
573 }
574 }
575
576 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_offsetGet, 0, 0, 1)
577 ZEND_ARG_INFO(0, offset)
578 ZEND_END_ARG_INFO();
579 PHP_METHOD(HttpQueryString, offsetGet)
580 {
581 char *offset_str;
582 int offset_len;
583 zval **value, *qa;
584
585 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
586 return;
587 }
588
589 qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
590
591 if (Z_TYPE_P(qa) == IS_ARRAY) {
592 if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(qa), offset_str, offset_len + 1, (void *) &value)) {
593 RETVAL_ZVAL(*value, 1, 0);
594 }
595 }
596 }
597
598 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_offsetSet, 0, 0, 2)
599 ZEND_ARG_INFO(0, offset)
600 ZEND_ARG_INFO(0, value)
601 ZEND_END_ARG_INFO();
602 PHP_METHOD(HttpQueryString, offsetSet)
603 {
604 char *offset_str;
605 int offset_len;
606 zval *value, *param;
607
608 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &offset_str, &offset_len, &value)) {
609 return;
610 }
611
612 param = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
613
614 if (Z_TYPE_P(param) == IS_ARRAY && zend_symtable_exists(Z_ARRVAL_P(param), offset_str, offset_len + 1)) {
615 Z_ADDREF_P(value);
616 zend_symtable_update(Z_ARRVAL_P(param), offset_str, offset_len + 1, (void *) &value, sizeof(zval *), NULL);
617 Z_ADDREF_P(param);
618 } else {
619 MAKE_STD_ZVAL(param);
620 array_init(param);
621 Z_ADDREF_P(value);
622 add_assoc_zval_ex(param, offset_str, offset_len + 1, value);
623 }
624 php_http_querystring_set(getThis(), param, QS_MERGE TSRMLS_CC);
625 zval_ptr_dtor(&param);
626 }
627
628 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_offsetExists, 0, 0, 1)
629 ZEND_ARG_INFO(0, offset)
630 ZEND_END_ARG_INFO();
631 PHP_METHOD(HttpQueryString, offsetExists)
632 {
633 char *offset_str;
634 int offset_len;
635 zval **value, *qa;
636
637 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
638 return;
639 }
640
641 qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0 TSRMLS_CC);
642
643 if (Z_TYPE_P(qa) == IS_ARRAY) {
644 if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(qa), offset_str, offset_len + 1, (void *) &value)) {
645 RETURN_BOOL(Z_TYPE_PP(value) != IS_NULL);
646 }
647 }
648 RETURN_FALSE;
649 }
650
651 ZEND_BEGIN_ARG_INFO_EX(ai_HttpQueryString_offsetUnset, 0, 0, 1)
652 ZEND_ARG_INFO(0, offset)
653 ZEND_END_ARG_INFO();
654 PHP_METHOD(HttpQueryString, offsetUnset)
655 {
656 char *offset_str;
657 int offset_len;
658 zval *param;
659
660 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
661 return;
662 }
663
664 MAKE_STD_ZVAL(param);
665 array_init(param);
666 add_assoc_null_ex(param, offset_str, offset_len + 1);
667 php_http_querystring_set(getThis(), param, QS_MERGE TSRMLS_CC);
668 zval_ptr_dtor(&param);
669 }
670
671 zend_class_entry *php_http_querystring_class_entry;
672
673 static zend_function_entry php_http_querystring_methods[] = {
674 PHP_ME(HttpQueryString, __construct, ai_HttpQueryString___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR|ZEND_ACC_FINAL)
675
676 PHP_ME(HttpQueryString, toArray, ai_HttpQueryString_toArray, ZEND_ACC_PUBLIC)
677 PHP_ME(HttpQueryString, toString, ai_HttpQueryString_toString, ZEND_ACC_PUBLIC)
678 ZEND_MALIAS(HttpQueryString, __toString, toString, ai_HttpQueryString_toString, ZEND_ACC_PUBLIC)
679
680 PHP_ME(HttpQueryString, get, ai_HttpQueryString_get, ZEND_ACC_PUBLIC)
681 PHP_ME(HttpQueryString, set, ai_HttpQueryString_set, ZEND_ACC_PUBLIC)
682 PHP_ME(HttpQueryString, mod, ai_HttpQueryString_mod, ZEND_ACC_PUBLIC)
683
684 PHP_ME(HttpQueryString, getBool, ai_HttpQueryString___getter, ZEND_ACC_PUBLIC)
685 PHP_ME(HttpQueryString, getInt, ai_HttpQueryString___getter, ZEND_ACC_PUBLIC)
686 PHP_ME(HttpQueryString, getFloat, ai_HttpQueryString___getter, ZEND_ACC_PUBLIC)
687 PHP_ME(HttpQueryString, getString, ai_HttpQueryString___getter, ZEND_ACC_PUBLIC)
688 PHP_ME(HttpQueryString, getArray, ai_HttpQueryString___getter, ZEND_ACC_PUBLIC)
689 PHP_ME(HttpQueryString, getObject, ai_HttpQueryString___getter, ZEND_ACC_PUBLIC)
690
691 PHP_ME(HttpQueryString, getIterator, ai_HttpQueryString_getIterator, ZEND_ACC_PUBLIC)
692
693 PHP_ME(HttpQueryString, getGlobalInstance, ai_HttpQueryString_getGlobalInstance, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
694 #ifdef PHP_HTTP_HAVE_ICONV
695 PHP_ME(HttpQueryString, xlate, ai_HttpQueryString_xlate, ZEND_ACC_PUBLIC)
696 #endif
697
698 /* Implements Serializable */
699 PHP_ME(HttpQueryString, serialize, ai_HttpQueryString_serialize, ZEND_ACC_PUBLIC)
700 PHP_ME(HttpQueryString, unserialize, ai_HttpQueryString_unserialize, ZEND_ACC_PUBLIC)
701
702 /* Implements ArrayAccess */
703 PHP_ME(HttpQueryString, offsetGet, ai_HttpQueryString_offsetGet, ZEND_ACC_PUBLIC)
704 PHP_ME(HttpQueryString, offsetSet, ai_HttpQueryString_offsetSet, ZEND_ACC_PUBLIC)
705 PHP_ME(HttpQueryString, offsetExists, ai_HttpQueryString_offsetExists, ZEND_ACC_PUBLIC)
706 PHP_ME(HttpQueryString, offsetUnset, ai_HttpQueryString_offsetUnset, ZEND_ACC_PUBLIC)
707
708 EMPTY_FUNCTION_ENTRY
709 };
710
711 PHP_MINIT_FUNCTION(http_querystring)
712 {
713 zend_class_entry ce = {0};
714
715 INIT_NS_CLASS_ENTRY(ce, "http", "QueryString", php_http_querystring_methods);
716 php_http_querystring_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
717 php_http_querystring_class_entry->create_object = php_http_querystring_object_new;
718 zend_class_implements(php_http_querystring_class_entry TSRMLS_CC, 3, zend_ce_serializable, zend_ce_arrayaccess, zend_ce_aggregate);
719
720 zend_declare_property_null(php_http_querystring_class_entry, ZEND_STRL("instance"), (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
721 zend_declare_property_null(php_http_querystring_class_entry, ZEND_STRL("queryArray"), ZEND_ACC_PRIVATE TSRMLS_CC);
722
723 zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_BOOL"), PHP_HTTP_QUERYSTRING_TYPE_BOOL TSRMLS_CC);
724 zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_INT"), PHP_HTTP_QUERYSTRING_TYPE_INT TSRMLS_CC);
725 zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_FLOAT"), PHP_HTTP_QUERYSTRING_TYPE_FLOAT TSRMLS_CC);
726 zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_STRING"), PHP_HTTP_QUERYSTRING_TYPE_STRING TSRMLS_CC);
727 zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_ARRAY"), PHP_HTTP_QUERYSTRING_TYPE_ARRAY TSRMLS_CC);
728 zend_declare_class_constant_long(php_http_querystring_class_entry, ZEND_STRL("TYPE_OBJECT"), PHP_HTTP_QUERYSTRING_TYPE_OBJECT TSRMLS_CC);
729
730 return SUCCESS;
731 }
732
733 /*
734 * Local variables:
735 * tab-width: 4
736 * c-basic-offset: 4
737 * End:
738 * vim600: noet sw=4 ts=4 fdm=marker
739 * vim<600: noet sw=4 ts=4
740 */