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