2 +--------------------------------------------------------------------+
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-2011, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
13 #include "php_http_api.h"
15 static php_http_params_token_t def_param_sep
= {",", 1}, *def_param_sep_ptr
[] = {&def_param_sep
, NULL
};
16 static php_http_params_token_t def_arg_sep
= {";", 1}, *def_arg_sep_ptr
[] = {&def_arg_sep
, NULL
};
17 static php_http_params_token_t def_val_sep
= {"=", 1}, *def_val_sep_ptr
[] = {&def_val_sep
, NULL
};
18 static php_http_params_opts_t def_opts
= {
19 .param
= def_param_sep_ptr
,
20 .arg
= def_arg_sep_ptr
,
21 .val
= def_val_sep_ptr
,
23 .flags
= PHP_HTTP_PARAMS_DEFAULT
26 PHP_HTTP_API php_http_params_opts_t
*php_http_params_opts_default_get(php_http_params_opts_t
*opts
)
29 opts
= emalloc(sizeof(*opts
));
32 memcpy(opts
, &def_opts
, sizeof(def_opts
));
37 typedef struct php_http_params_state
{
38 php_http_params_token_t input
;
39 php_http_params_token_t param
;
40 php_http_params_token_t arg
;
41 php_http_params_token_t val
;
47 } php_http_params_state_t
;
49 static void sanitize_default(zval
*zv TSRMLS_DC
)
51 if (Z_STRVAL_P(zv
)[0] == '"' && Z_STRVAL_P(zv
)[Z_STRLEN_P(zv
) - 1] == '"') {
52 size_t deq_len
= Z_STRLEN_P(zv
) - 2;
53 char *deq
= estrndup(Z_STRVAL_P(zv
) + 1, deq_len
);
56 ZVAL_STRINGL(zv
, deq
, deq_len
, 0);
59 php_stripslashes(Z_STRVAL_P(zv
), &Z_STRLEN_P(zv
) TSRMLS_CC
);
62 static void prepare_default(zval
*zv TSRMLS_DC
)
64 int len
= Z_STRLEN_P(zv
);
66 Z_STRVAL_P(zv
) = php_addslashes(Z_STRVAL_P(zv
), Z_STRLEN_P(zv
), &Z_STRLEN_P(zv
), 1 TSRMLS_CC
);
68 if (len
!= Z_STRLEN_P(zv
)) {
70 int len
= Z_STRLEN_P(zv
) + 2;
71 char *str
= emalloc(len
+ 1);
74 memcpy(&str
[1], Z_STRVAL_P(zv
), Z_STRLEN_P(zv
));
79 ZVAL_STRINGL(zv
, str
, len
, 0);
83 static void sanitize_urlencoded(zval
*zv TSRMLS_DC
)
85 Z_STRLEN_P(zv
) = php_raw_url_decode(Z_STRVAL_P(zv
), Z_STRLEN_P(zv
));
88 static void prepare_urlencoded(zval
*zv TSRMLS_DC
)
91 char *str
= php_raw_url_encode(Z_STRVAL_P(zv
), Z_STRLEN_P(zv
), &len
);
94 ZVAL_STRINGL(zv
, str
, len
, 0);
97 static void sanitize_dimension(zval
*zv TSRMLS_DC
)
99 zval
*arr
= NULL
, *tmp
= NULL
, **cur
= NULL
;
100 char *var
= NULL
, *ptr
= Z_STRVAL_P(zv
), *end
= Z_STRVAL_P(zv
) + Z_STRLEN_P(zv
);
114 if (++level
> PG(max_input_nesting_level
)) {
116 php_http_error(HE_WARNING
, PHP_HTTP_E_QUERYSTRING
, "Max input nesting level of %ld exceeded", PG(max_input_nesting_level
));
119 if (ptr
- var
== 0) {
129 convert_to_array(*cur
);
134 zend_symtable_update(Z_ARRVAL_PP(cur
), var
, ptr
- var
+ 1, (void *) &tmp
, sizeof(zval
*), (void *) &cur
);
137 zend_hash_next_index_insert(Z_ARRVAL_PP(cur
), (void *) &tmp
, sizeof(zval
*), (void *) &cur
);
147 if (zend_hash_num_elements(Z_ARRVAL_P(arr
))) {
149 ZVAL_COPY_VALUE(zv
, arr
);
156 static void prepare_dimension(zval
*zv TSRMLS_DC
)
158 if (Z_TYPE_P(zv
) == IS_ARRAY
) {
160 php_http_array_hashkey_t key
= php_http_array_hashkey_init(0);
161 php_http_buffer_t buf
;
163 php_http_buffer_init(&buf
);
166 if (HASH_KEY_IS_STRING
== zend_hash_get_current_key_ex(Z_ARRVAL_PP(zdata
), &key
.str
, &key
.len
, &key
.num
, key
.dup
, NULL
)) {
167 php_http_buffer_appendf(&buf
, "[%s]", key
.str
);
169 php_http_buffer_appendf(&buf
, "[%lu]", key
.num
);
171 } while (SUCCESS
== zend_hash_get_current_data(Z_ARRVAL_PP(zdata
), (void *) &zdata
) && Z_TYPE_PP(zdata
) == IS_ARRAY
);
173 php_http_buffer_fix(&buf
);
175 ZVAL_STRINGL(zv
, buf
.data
, buf
.used
, 0);
179 static void sanitize_key(unsigned flags
, char *str
, size_t len
, zval
*zv TSRMLS_DC
)
181 php_trim(str
, len
, NULL
, 0, zv
, 3 TSRMLS_CC
);
183 if (flags
& PHP_HTTP_PARAMS_DEFAULT
) {
184 sanitize_default(zv TSRMLS_CC
);
187 if (flags
& PHP_HTTP_PARAMS_URLENCODED
) {
188 sanitize_urlencoded(zv TSRMLS_CC
);
191 if (flags
& PHP_HTTP_PARAMS_DIMENSION
) {
192 sanitize_dimension(zv TSRMLS_CC
);
196 static void sanitize_value(unsigned flags
, char *str
, size_t len
, zval
*zv TSRMLS_DC
)
198 php_trim(str
, len
, NULL
, 0, zv
, 3 TSRMLS_CC
);
200 if (flags
& PHP_HTTP_PARAMS_DEFAULT
) {
201 sanitize_default(zv TSRMLS_CC
);
204 if (flags
& PHP_HTTP_PARAMS_URLENCODED
) {
205 sanitize_urlencoded(zv TSRMLS_CC
);
209 static void prepare_key(unsigned flags
, char *old_key
, size_t old_len
, char **new_key
, size_t *new_len TSRMLS_DC
)
214 ZVAL_STRINGL(&zv
, old_key
, old_len
, 1);
216 if (flags
& PHP_HTTP_PARAMS_DIMENSION
) {
217 prepare_dimension(&zv TSRMLS_CC
);
220 if (flags
& PHP_HTTP_PARAMS_URLENCODED
) {
221 prepare_urlencoded(&zv TSRMLS_CC
);
224 if (flags
& PHP_HTTP_PARAMS_DEFAULT
) {
225 prepare_default(&zv TSRMLS_CC
);
228 *new_key
= Z_STRVAL(zv
);
229 *new_len
= Z_STRLEN(zv
);
232 static void prepare_value(unsigned flags
, zval
*zv TSRMLS_DC
)
234 if (flags
& PHP_HTTP_PARAMS_DIMENSION
) {
235 prepare_dimension(zv TSRMLS_CC
);
238 if (flags
& PHP_HTTP_PARAMS_URLENCODED
) {
239 prepare_urlencoded(zv TSRMLS_CC
);
242 if (flags
& PHP_HTTP_PARAMS_DEFAULT
) {
243 prepare_default(zv TSRMLS_CC
);
247 static void merge_param(HashTable
*params
, zval
*zdata
, zval
***cur TSRMLS_DC
)
249 zval
**ptr
, **zdata_ptr
;
250 php_http_array_hashkey_t hkey
= php_http_array_hashkey_init(0);
255 INIT_PZVAL_ARRAY(&tmp
, params
);
256 fprintf(stderr
, "params = ");
257 zend_print_zval_r(&tmp
, 1 TSRMLS_CC
);
258 fprintf(stderr
, "\n");
262 hkey
.type
= zend_hash_get_current_key_ex(Z_ARRVAL_P(zdata
), &hkey
.str
, &hkey
.len
, &hkey
.num
, hkey
.dup
, NULL
);
264 if ((hkey
.type
== HASH_KEY_IS_STRING
&& !zend_hash_exists(params
, hkey
.str
, hkey
.len
))
265 || (hkey
.type
== HASH_KEY_IS_LONG
&& !zend_hash_index_exists(params
, hkey
.num
))
269 /* create the entry if it doesn't exist */
270 zend_hash_get_current_data(Z_ARRVAL_P(zdata
), (void *) &ptr
);
274 add_assoc_zval_ex(tmp
, ZEND_STRS("value"), *ptr
);
276 if (hkey
.type
== HASH_KEY_IS_STRING
) {
277 zend_hash_update(params
, hkey
.str
, hkey
.len
, (void *) &tmp
, sizeof(zval
*), (void *) &ptr
);
279 zend_hash_index_update(params
, hkey
.num
, (void *) &tmp
, sizeof(zval
*), (void *) &ptr
);
283 if (hkey
.type
== HASH_KEY_IS_STRING
) {
284 zend_hash_find(params
, hkey
.str
, hkey
.len
, (void *) &ptr
);
286 zend_hash_index_find(params
, hkey
.num
, (void *) &ptr
);
291 if (Z_TYPE_PP(ptr
) == IS_ARRAY
292 && SUCCESS
== zend_hash_find(Z_ARRVAL_PP(ptr
), "value", sizeof("value"), (void *) &ptr
)
293 && SUCCESS
== zend_hash_get_current_data(Z_ARRVAL_PP(zdata_ptr
), (void *) &zdata_ptr
)
296 * params = [arr => [value => [0 => 1]]]
298 * zdata = [arr => [0 => NULL]]
303 while (Z_TYPE_PP(zdata_ptr
) == IS_ARRAY
304 && SUCCESS
== zend_hash_get_current_data(Z_ARRVAL_PP(zdata_ptr
), (void *) &test_ptr
)
306 if (Z_TYPE_PP(test_ptr
) == IS_ARRAY
) {
308 /* now find key in ptr */
309 if (HASH_KEY_IS_STRING
== zend_hash_get_current_key_ex(Z_ARRVAL_PP(zdata_ptr
), &hkey
.str
, &hkey
.len
, &hkey
.num
, hkey
.dup
, NULL
)) {
310 if (SUCCESS
== zend_hash_find(Z_ARRVAL_PP(ptr
), hkey
.str
, hkey
.len
, (void *) &ptr
)) {
311 zdata_ptr
= test_ptr
;
313 Z_ADDREF_PP(test_ptr
);
314 zend_hash_update(Z_ARRVAL_PP(ptr
), hkey
.str
, hkey
.len
, (void *) test_ptr
, sizeof(zval
*), (void *) &ptr
);
318 if (SUCCESS
== zend_hash_find(Z_ARRVAL_PP(ptr
), hkey
.str
, hkey
.len
, (void *) &ptr
)) {
319 zdata_ptr
= test_ptr
;
320 } else if (hkey
.num
) {
321 Z_ADDREF_PP(test_ptr
);
322 zend_hash_index_update(Z_ARRVAL_PP(ptr
), hkey
.num
, (void *) test_ptr
, sizeof(zval
*), (void *) &ptr
);
325 Z_ADDREF_PP(test_ptr
);
326 zend_hash_next_index_insert(Z_ARRVAL_PP(ptr
), (void *) test_ptr
, sizeof(zval
*), (void *) &ptr
);
331 /* this is the leaf */
332 Z_ADDREF_PP(test_ptr
);
333 if (HASH_KEY_IS_STRING
== zend_hash_get_current_key_ex(Z_ARRVAL_PP(zdata_ptr
), &hkey
.str
, &hkey
.len
, &hkey
.num
, hkey
.dup
, NULL
)) {
334 zend_hash_update(Z_ARRVAL_PP(ptr
), hkey
.str
, hkey
.len
, (void *) test_ptr
, sizeof(zval
*), (void *) &ptr
);
335 } else if (hkey
.num
) {
336 zend_hash_index_update(Z_ARRVAL_PP(ptr
), hkey
.num
, (void *) test_ptr
, sizeof(zval
*), (void *) &ptr
);
338 zend_hash_next_index_insert(Z_ARRVAL_PP(ptr
), (void *) test_ptr
, sizeof(zval
*), (void *) &ptr
);
348 while (Z_TYPE_PP(ptr
) == IS_ARRAY
&& SUCCESS
== zend_hash_get_current_data(Z_ARRVAL_PP(ptr
), (void *) &ptr
));
352 static void push_param(HashTable
*params
, php_http_params_state_t
*state
, const php_http_params_opts_t
*opts TSRMLS_DC
)
354 if (state
->val
.str
) {
355 if (0 < (state
->val
.len
= state
->input
.str
- state
->val
.str
)) {
356 sanitize_value(opts
->flags
, state
->val
.str
, state
->val
.len
, *(state
->current
.val
) TSRMLS_CC
);
358 } else if (state
->arg
.str
) {
359 if (0 < (state
->arg
.len
= state
->input
.str
- state
->arg
.str
)) {
363 sanitize_key(opts
->flags
, state
->arg
.str
, state
->arg
.len
, &key TSRMLS_CC
);
367 zend_symtable_update(Z_ARRVAL_PP(state
->current
.args
), Z_STRVAL(key
), Z_STRLEN(key
) + 1, (void *) &val
, sizeof(zval
*), (void *) &state
->current
.val
);
371 } else if (state
->param
.str
) {
372 if (0 < (state
->param
.len
= state
->input
.str
- state
->param
.str
)) {
373 zval
*prm
, *arg
, *val
, *key
;
377 sanitize_key(opts
->flags
, state
->param
.str
, state
->param
.len
, key TSRMLS_CC
);
378 if (Z_TYPE_P(key
) != IS_STRING
) {
379 merge_param(params
, key
, &state
->current
.val TSRMLS_CC
);
380 } else if (Z_STRLEN_P(key
)) {
386 ZVAL_COPY_VALUE(val
, opts
->defval
);
391 zend_hash_update(Z_ARRVAL_P(prm
), "value", sizeof("value"), (void *) &val
, sizeof(zval
*), (void *) &state
->current
.val
);
395 zend_hash_update(Z_ARRVAL_P(prm
), "arguments", sizeof("arguments"), (void *) &arg
, sizeof(zval
*), (void *) &state
->current
.args
);
397 zend_symtable_update(params
, Z_STRVAL_P(key
), Z_STRLEN_P(key
) + 1, (void *) &prm
, sizeof(zval
*), (void *) &state
->current
.param
);
404 static inline zend_bool
check_str(const char *chk_str
, size_t chk_len
, const char *sep_str
, size_t sep_len
) {
405 return 0 < sep_len
&& chk_len
>= sep_len
&& !memcmp(chk_str
, sep_str
, sep_len
);
408 static size_t check_sep(php_http_params_state_t
*state
, php_http_params_token_t
**separators
)
410 php_http_params_token_t
**sep
= separators
;
412 if (sep
) while (*sep
) {
413 if (check_str(state
->input
.str
, state
->input
.len
, (*sep
)->str
, (*sep
)->len
)) {
421 PHP_HTTP_API HashTable
*php_http_params_parse(HashTable
*params
, const php_http_params_opts_t
*opts TSRMLS_DC
)
423 php_http_params_state_t state
= {{NULL
,0}, {NULL
,0}, {NULL
,0}, {NULL
,0}, {NULL
,NULL
,NULL
}};
425 state
.input
.str
= opts
->input
.str
;
426 state
.input
.len
= opts
->input
.len
;
429 ALLOC_HASHTABLE(params
);
430 ZEND_INIT_SYMTABLE(params
);
433 while (state
.input
.len
) {
434 if (*state
.input
.str
== '\\') {
437 } else if (!state
.param
.str
) {
439 state
.param
.str
= state
.input
.str
;
442 /* are we at a param separator? */
443 if (0 < (sep_len
= check_sep(&state
, opts
->param
))) {
444 push_param(params
, &state
, opts TSRMLS_CC
);
446 /* start off with a new param */
447 state
.param
.str
= state
.input
.str
+ sep_len
;
449 state
.arg
.str
= NULL
;
451 state
.val
.str
= NULL
;
454 /* are we at an arg separator? */
455 if (0 < (sep_len
= check_sep(&state
, opts
->arg
))) {
456 push_param(params
, &state
, opts TSRMLS_CC
);
458 /* continue with a new arg */
459 state
.arg
.str
= state
.input
.str
+ sep_len
;
461 state
.val
.str
= NULL
;
464 /* are we at a val separator? */
465 if (0 < (sep_len
= check_sep(&state
, opts
->val
))) {
466 /* only handle separator if we're not already reading in a val */
467 if (!state
.val
.str
) {
468 push_param(params
, &state
, opts TSRMLS_CC
);
470 state
.val
.str
= state
.input
.str
+ sep_len
;
476 if (state
.input
.len
) {
482 push_param(params
, &state
, opts TSRMLS_CC
);
487 PHP_HTTP_API php_http_buffer_t
*php_http_params_to_string(php_http_buffer_t
*buf
, HashTable
*params
, const char *pss
, size_t psl
, const char *ass
, size_t asl
, const char *vss
, size_t vsl
, unsigned flags TSRMLS_DC
)
490 HashPosition pos1
, pos2
;
491 php_http_array_hashkey_t key1
= php_http_array_hashkey_init(0), key2
= php_http_array_hashkey_init(0), key3
= php_http_array_hashkey_init(0);
494 buf
= php_http_buffer_init(NULL
);
497 FOREACH_HASH_KEYVAL(pos1
, params
, key1
, zparam
) {
499 if (PHP_HTTP_BUFFER_LEN(buf
)) {
500 php_http_buffer_append(buf
, pss
, psl
);
504 if (key1
.type
== HASH_KEY_IS_STRING
) {
508 prepare_key(flags
, key1
.str
, key1
.len
- 1, &key
, &len TSRMLS_CC
);
509 php_http_buffer_append(buf
, key
, len
);
512 php_http_buffer_appendf(buf
, "%lu", key1
.num
);
515 if (Z_TYPE_PP(zparam
) != IS_ARRAY
) {
516 zval
*tmp
= php_http_ztyp(IS_STRING
, *zparam
);
518 prepare_value(flags
, tmp TSRMLS_CC
);
520 php_http_buffer_append(buf
, vss
, vsl
);
521 php_http_buffer_append(buf
, Z_STRVAL_P(tmp
), Z_STRLEN_P(tmp
));
524 zval
**zvalue
, **zargs
, **zarg
;
527 if (SUCCESS
== zend_hash_find(Z_ARRVAL_PP(zparam
), ZEND_STRS("value"), (void *) &zvalue
)) {
528 if (Z_TYPE_PP(zvalue
) != IS_BOOL
) {
531 if (Z_TYPE_PP(zvalue
) == IS_ARRAY
) {
532 tmp
= php_http_zsep(1, IS_ARRAY
, *zvalue
);
533 prepare_value(flags
, tmp TSRMLS_CC
);
534 php_http_buffer_append(buf
, Z_STRVAL_P(tmp
), Z_STRLEN_P(tmp
));
538 while (SUCCESS
== zend_hash_get_current_data(Z_ARRVAL_PP(zvalue
), (void *) &zvalue
) && Z_TYPE_PP(zvalue
) == IS_ARRAY
);
541 tmp
= php_http_ztyp(IS_STRING
, *zvalue
);
542 prepare_value(flags
, tmp TSRMLS_CC
);
543 php_http_buffer_append(buf
, vss
, vsl
);
544 php_http_buffer_append(buf
, Z_STRVAL_P(tmp
), Z_STRLEN_P(tmp
));
546 } else if (!Z_BVAL_PP(zvalue
)) {
547 php_http_buffer_append(buf
, vss
, vsl
);
548 php_http_buffer_appends(buf
, "0");
552 if (SUCCESS
!= zend_hash_find(Z_ARRVAL_PP(zparam
), ZEND_STRS("arguments"), (void *) &zargs
)) {
556 if (Z_TYPE_PP(zargs
) == IS_ARRAY
) {
557 FOREACH_KEYVAL(pos2
, *zargs
, key2
, zarg
) {
558 /* skip "value" if zargs == zparam */
559 if (zargs
== zparam
&& key2
.type
== HASH_KEY_IS_STRING
&& !strcmp(key2
.str
, "value")) {
564 if (PHP_HTTP_BUFFER_LEN(buf
)) {
565 php_http_buffer_append(buf
, ass
, asl
);
569 if (key2
.type
== HASH_KEY_IS_STRING
) {
573 prepare_key(flags
, key2
.str
, key2
.len
- 1, &key
, &len TSRMLS_CC
);
574 php_http_buffer_append(buf
, key
, len
);
577 php_http_buffer_appendf(buf
, "%lu", key2
.num
);
580 if (Z_TYPE_PP(zarg
) != IS_BOOL
) {
583 if (Z_TYPE_PP(zarg
) == IS_ARRAY
) {
584 tmp
= php_http_zsep(1, IS_ARRAY
, *zarg
);
585 prepare_value(flags
, tmp TSRMLS_CC
);
586 php_http_buffer_append(buf
, Z_STRVAL_P(tmp
), Z_STRLEN_P(tmp
));
590 while (SUCCESS
== zend_hash_get_current_data(Z_ARRVAL_PP(zarg
), (void *) &zarg
) && Z_TYPE_PP(zarg
) == IS_ARRAY
);
593 tmp
= php_http_ztyp(IS_STRING
, *zarg
);
594 prepare_value(flags
, tmp TSRMLS_CC
);
595 php_http_buffer_append(buf
, vss
, vsl
);
596 php_http_buffer_append(buf
, Z_STRVAL_P(tmp
), Z_STRLEN_P(tmp
));
598 } else if (!Z_BVAL_PP(zarg
)) {
599 php_http_buffer_append(buf
, vss
, vsl
);
600 php_http_buffer_appends(buf
, "0");
607 php_http_buffer_shrink(buf
);
608 php_http_buffer_fix(buf
);
613 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpParams, method, 0, req_args)
614 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpParams, method, 0)
615 #define PHP_HTTP_PARAMS_ME(method, visibility) PHP_ME(HttpParams, method, PHP_HTTP_ARGS(HttpParams, method), visibility)
616 #define PHP_HTTP_PARAMS_GME(method, visibility) PHP_ME(HttpParams, method, PHP_HTTP_ARGS(HttpParams, __getter), visibility)
618 PHP_HTTP_BEGIN_ARGS(__construct
, 0)
619 PHP_HTTP_ARG_VAL(params
, 0)
620 PHP_HTTP_ARG_VAL(param_sep
, 0)
621 PHP_HTTP_ARG_VAL(arg_sep
, 0)
622 PHP_HTTP_ARG_VAL(val_sep
, 0)
623 PHP_HTTP_ARG_VAL(flags
, 0)
626 PHP_HTTP_EMPTY_ARGS(toArray
);
627 PHP_HTTP_EMPTY_ARGS(toString
);
629 PHP_HTTP_BEGIN_ARGS(offsetExists
, 1)
630 PHP_HTTP_ARG_VAL(name
, 0)
633 PHP_HTTP_BEGIN_ARGS(offsetUnset
, 1)
634 PHP_HTTP_ARG_VAL(name
, 0)
637 PHP_HTTP_BEGIN_ARGS(offsetGet
, 1)
638 PHP_HTTP_ARG_VAL(name
, 0)
641 PHP_HTTP_BEGIN_ARGS(offsetSet
, 2)
642 PHP_HTTP_ARG_VAL(name
, 0)
643 PHP_HTTP_ARG_VAL(value
, 0)
646 static zend_class_entry
*php_http_params_class_entry
;
648 zend_class_entry
*php_http_params_get_class_entry(void)
650 return php_http_params_class_entry
;
653 static zend_function_entry php_http_params_method_entry
[] = {
654 PHP_HTTP_PARAMS_ME(__construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
|ZEND_ACC_FINAL
)
656 PHP_HTTP_PARAMS_ME(toArray
, ZEND_ACC_PUBLIC
)
657 PHP_HTTP_PARAMS_ME(toString
, ZEND_ACC_PUBLIC
)
658 ZEND_MALIAS(HttpParams
, __toString
, toString
, PHP_HTTP_ARGS(HttpParams
, toString
), ZEND_ACC_PUBLIC
)
660 PHP_HTTP_PARAMS_ME(offsetExists
, ZEND_ACC_PUBLIC
)
661 PHP_HTTP_PARAMS_ME(offsetUnset
, ZEND_ACC_PUBLIC
)
662 PHP_HTTP_PARAMS_ME(offsetSet
, ZEND_ACC_PUBLIC
)
663 PHP_HTTP_PARAMS_ME(offsetGet
, ZEND_ACC_PUBLIC
)
668 PHP_MINIT_FUNCTION(http_params
)
670 PHP_HTTP_REGISTER_CLASS(http
, Params
, http_params
, php_http_object_get_class_entry(), 0);
672 zend_class_implements(php_http_params_class_entry TSRMLS_CC
, 1, zend_ce_arrayaccess
);
674 zend_declare_class_constant_stringl(php_http_params_class_entry
, ZEND_STRL("DEF_PARAM_SEP"), ZEND_STRL(",") TSRMLS_CC
);
675 zend_declare_class_constant_stringl(php_http_params_class_entry
, ZEND_STRL("DEF_ARG_SEP"), ZEND_STRL(";") TSRMLS_CC
);
676 zend_declare_class_constant_stringl(php_http_params_class_entry
, ZEND_STRL("DEF_VAL_SEP"), ZEND_STRL("=") TSRMLS_CC
);
677 zend_declare_class_constant_stringl(php_http_params_class_entry
, ZEND_STRL("COOKIE_PARAM_SEP"), ZEND_STRL("") TSRMLS_CC
);
679 zend_declare_class_constant_long(php_http_params_class_entry
, ZEND_STRL("PARSE_RAW"), PHP_HTTP_PARAMS_RAW TSRMLS_CC
);
680 zend_declare_class_constant_long(php_http_params_class_entry
, ZEND_STRL("PARSE_DEFAULT"), PHP_HTTP_PARAMS_DEFAULT TSRMLS_CC
);
681 zend_declare_class_constant_long(php_http_params_class_entry
, ZEND_STRL("PARSE_URLENCODED"), PHP_HTTP_PARAMS_URLENCODED TSRMLS_CC
);
682 zend_declare_class_constant_long(php_http_params_class_entry
, ZEND_STRL("PARSE_DIMENSION"), PHP_HTTP_PARAMS_DIMENSION TSRMLS_CC
);
683 zend_declare_class_constant_long(php_http_params_class_entry
, ZEND_STRL("PARSE_QUERY"), PHP_HTTP_PARAMS_QUERY TSRMLS_CC
);
685 zend_declare_property_null(php_http_params_class_entry
, ZEND_STRL("params"), ZEND_ACC_PUBLIC TSRMLS_CC
);
686 zend_declare_property_stringl(php_http_params_class_entry
, ZEND_STRL("param_sep"), ZEND_STRL(","), ZEND_ACC_PUBLIC TSRMLS_CC
);
687 zend_declare_property_stringl(php_http_params_class_entry
, ZEND_STRL("arg_sep"), ZEND_STRL(";"), ZEND_ACC_PUBLIC TSRMLS_CC
);
688 zend_declare_property_stringl(php_http_params_class_entry
, ZEND_STRL("val_sep"), ZEND_STRL("="), ZEND_ACC_PUBLIC TSRMLS_CC
);
689 zend_declare_property_long(php_http_params_class_entry
, ZEND_STRL("flags"), PHP_HTTP_PARAMS_DEFAULT
, ZEND_ACC_PUBLIC TSRMLS_CC
);
694 PHP_HTTP_API php_http_params_token_t
**php_http_params_separator_init(zval
*zv TSRMLS_DC
)
698 php_http_params_token_t
**ret
, **tmp
;
704 zv
= php_http_ztyp(IS_ARRAY
, zv
);
705 ret
= ecalloc(zend_hash_num_elements(Z_ARRVAL_P(zv
)) + 1, sizeof(*ret
));
708 FOREACH_VAL(pos
, zv
, sep
) {
709 zval
*zt
= php_http_ztyp(IS_STRING
, *sep
);
711 if (Z_STRLEN_P(zt
)) {
712 *tmp
= emalloc(sizeof(**tmp
));
713 (*tmp
)->str
= estrndup(Z_STRVAL_P(zt
), (*tmp
)->len
= Z_STRLEN_P(zt
));
724 PHP_HTTP_API
void php_http_params_separator_free(php_http_params_token_t
**separator
)
726 php_http_params_token_t
**sep
= separator
;
729 STR_FREE((*sep
)->str
);
737 PHP_METHOD(HttpParams
, __construct
)
739 with_error_handling(EH_THROW
, php_http_exception_get_class_entry()) {
740 zval
*zcopy
, *zparams
= NULL
, *param_sep
= NULL
, *arg_sep
= NULL
, *val_sep
= NULL
;
741 long flags
= PHP_HTTP_PARAMS_DEFAULT
;
743 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|z!/z/z/z/l", &zparams
, ¶m_sep
, &arg_sep
, &val_sep
, &flags
)) {
744 switch (ZEND_NUM_ARGS()) {
746 zend_update_property_long(php_http_params_class_entry
, getThis(), ZEND_STRL("flags"), flags TSRMLS_CC
);
749 zend_update_property(php_http_params_class_entry
, getThis(), ZEND_STRL("val_sep"), val_sep TSRMLS_CC
);
752 zend_update_property(php_http_params_class_entry
, getThis(), ZEND_STRL("arg_sep"), arg_sep TSRMLS_CC
);
755 zend_update_property(php_http_params_class_entry
, getThis(), ZEND_STRL("param_sep"), param_sep TSRMLS_CC
);
760 switch (Z_TYPE_P(zparams
)) {
763 zcopy
= php_http_zsep(1, IS_ARRAY
, zparams
);
764 zend_update_property(php_http_params_class_entry
, getThis(), ZEND_STRL("params"), zcopy TSRMLS_CC
);
765 zval_ptr_dtor(&zcopy
);
768 zcopy
= php_http_ztyp(IS_STRING
, zparams
);
769 if (Z_STRLEN_P(zcopy
)) {
770 php_http_params_opts_t opts
= {
772 .str
= Z_STRVAL_P(zcopy
),
773 .len
= Z_STRLEN_P(zcopy
)
775 .param
= php_http_params_separator_init(zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC
) TSRMLS_CC
),
776 .arg
= php_http_params_separator_init(zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC
) TSRMLS_CC
),
777 .val
= php_http_params_separator_init(zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC
) TSRMLS_CC
),
781 MAKE_STD_ZVAL(zparams
);
783 php_http_params_parse(Z_ARRVAL_P(zparams
), &opts TSRMLS_CC
);
784 zend_update_property(php_http_params_class_entry
, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC
);
785 zval_ptr_dtor(&zparams
);
787 php_http_params_separator_free(opts
.param
);
788 php_http_params_separator_free(opts
.arg
);
789 php_http_params_separator_free(opts
.val
);
791 zval_ptr_dtor(&zcopy
);
795 MAKE_STD_ZVAL(zparams
);
797 zend_update_property(php_http_params_class_entry
, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC
);
798 zval_ptr_dtor(&zparams
);
801 } end_error_handling();
804 PHP_METHOD(HttpParams
, toArray
)
806 if (SUCCESS
!= zend_parse_parameters_none()) {
809 RETURN_PROP(php_http_params_class_entry
, "params");
812 PHP_METHOD(HttpParams
, toString
)
814 zval
*zparams
, *zpsep
, *zasep
, *zvsep
, *zflags
;
815 php_http_buffer_t buf
;
817 zparams
= php_http_ztyp(IS_ARRAY
, zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC
));
818 zpsep
= php_http_ztyp(IS_STRING
, zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC
));
819 zasep
= php_http_ztyp(IS_STRING
, zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC
));
820 zvsep
= php_http_ztyp(IS_STRING
, zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC
));
821 zflags
= php_http_ztyp(IS_LONG
, zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("flags"), 0 TSRMLS_CC
));
823 php_http_buffer_init(&buf
);
824 php_http_params_to_string(&buf
, Z_ARRVAL_P(zparams
), Z_STRVAL_P(zpsep
), Z_STRLEN_P(zpsep
), Z_STRVAL_P(zasep
), Z_STRLEN_P(zasep
), Z_STRVAL_P(zvsep
), Z_STRLEN_P(zvsep
), Z_LVAL_P(zflags
) TSRMLS_CC
);
826 zval_ptr_dtor(&zparams
);
827 zval_ptr_dtor(&zpsep
);
828 zval_ptr_dtor(&zasep
);
829 zval_ptr_dtor(&zvsep
);
830 zval_ptr_dtor(&zflags
);
832 RETVAL_PHP_HTTP_BUFFER_VAL(&buf
);
835 PHP_METHOD(HttpParams
, offsetExists
)
840 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &name_str
, &name_len
)) {
841 zval
**zparam
, *zparams
= php_http_ztyp(IS_ARRAY
, zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC
));
843 if (SUCCESS
== zend_symtable_find(Z_ARRVAL_P(zparams
), name_str
, name_len
+ 1, (void *) &zparam
)) {
844 RETVAL_BOOL(Z_TYPE_PP(zparam
) != IS_NULL
);
848 zval_ptr_dtor(&zparams
);
852 PHP_METHOD(HttpParams
, offsetGet
)
857 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &name_str
, &name_len
)) {
858 zval
**zparam
, *zparams
= php_http_ztyp(IS_ARRAY
, zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC
));
860 if (SUCCESS
== zend_symtable_find(Z_ARRVAL_P(zparams
), name_str
, name_len
+ 1, (void *) &zparam
)) {
861 RETVAL_ZVAL(*zparam
, 1, 0);
864 zval_ptr_dtor(&zparams
);
869 PHP_METHOD(HttpParams
, offsetUnset
)
874 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &name_str
, &name_len
)) {
875 zval
*zparams
= php_http_zsep(1, IS_ARRAY
, zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC
));
877 zend_symtable_del(Z_ARRVAL_P(zparams
), name_str
, name_len
+ 1);
878 zend_update_property(php_http_params_class_entry
, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC
);
880 zval_ptr_dtor(&zparams
);
884 PHP_METHOD(HttpParams
, offsetSet
)
890 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sz", &name_str
, &name_len
, &nvalue
)) {
891 zval
**zparam
, *zparams
= php_http_zsep(1, IS_ARRAY
, zend_read_property(php_http_params_class_entry
, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC
));
894 if (Z_TYPE_P(nvalue
) == IS_ARRAY
) {
897 if (SUCCESS
== zend_symtable_find(Z_ARRVAL_P(zparams
), name_str
, name_len
+ 1, (void *) &zparam
)) {
898 new_zparam
= php_http_zsep(1, IS_ARRAY
, *zparam
);
899 array_join(Z_ARRVAL_P(nvalue
), Z_ARRVAL_P(new_zparam
), 0, 0);
902 Z_ADDREF_P(new_zparam
);
904 add_assoc_zval_ex(zparams
, name_str
, name_len
+ 1, new_zparam
);
908 if (SUCCESS
== zend_symtable_find(Z_ARRVAL_P(zparams
), name_str
, name_len
+ 1, (void *) &zparam
)) {
909 tmp
= php_http_zsep(1, IS_ARRAY
, *zparam
);
916 add_assoc_zval_ex(tmp
, ZEND_STRS("value"), nvalue
);
917 add_assoc_zval_ex(zparams
, name_str
, name_len
+ 1, tmp
);
920 zval
*tmp
= php_http_ztyp(IS_STRING
, nvalue
), *arr
;
924 add_assoc_bool_ex(arr
, ZEND_STRS("value"), 1);
925 add_assoc_zval_ex(zparams
, Z_STRVAL_P(tmp
), Z_STRLEN_P(tmp
) + 1, arr
);
929 zend_update_property(php_http_params_class_entry
, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC
);
930 zval_ptr_dtor(&zparams
);
939 * vim600: noet sw=4 ts=4 fdm=marker
940 * vim<600: noet sw=4 ts=4