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