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