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