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