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