fix serialization of http\Params; one test still fails though
[m6w6/ext-http] / php_http_params.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-2011, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #include "php_http_api.h"
14
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,
22 .defval = NULL,
23 .flags = PHP_HTTP_PARAMS_DEFAULT
24 };
25
26 PHP_HTTP_API php_http_params_opts_t *php_http_params_opts_default_get(php_http_params_opts_t *opts)
27 {
28 if (!opts) {
29 opts = emalloc(sizeof(*opts));
30 }
31
32 memcpy(opts, &def_opts, sizeof(def_opts));
33
34 return opts;
35 }
36
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;
42 struct {
43 zval **param;
44 zval **args;
45 zval **val;
46 } current;
47 } php_http_params_state_t;
48
49 static void sanitize_default(zval *zv TSRMLS_DC)
50 {
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);
54
55 zval_dtor(zv);
56 ZVAL_STRINGL(zv, deq, deq_len, 0);
57 }
58
59 php_stripslashes(Z_STRVAL_P(zv), &Z_STRLEN_P(zv) TSRMLS_CC);
60 }
61
62 static void prepare_default(zval *zv TSRMLS_DC)
63 {
64 int len = Z_STRLEN_P(zv);
65
66 Z_STRVAL_P(zv) = php_addslashes(Z_STRVAL_P(zv), Z_STRLEN_P(zv), &Z_STRLEN_P(zv), 1 TSRMLS_CC);
67
68 if (len != Z_STRLEN_P(zv)) {
69 zval tmp = *zv;
70 int len = Z_STRLEN_P(zv) + 2;
71 char *str = emalloc(len + 1);
72
73 str[0] = '"';
74 memcpy(&str[1], Z_STRVAL_P(zv), Z_STRLEN_P(zv));
75 str[len-1] = '"';
76 str[len] = '\0';
77
78 zval_dtor(&tmp);
79 ZVAL_STRINGL(zv, str, len, 0);
80 }
81 }
82
83 static void sanitize_urlencoded(zval *zv TSRMLS_DC)
84 {
85 Z_STRLEN_P(zv) = php_raw_url_decode(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
86 }
87
88 static void prepare_urlencoded(zval *zv TSRMLS_DC)
89 {
90 int len;
91 char *str = php_raw_url_encode(Z_STRVAL_P(zv), Z_STRLEN_P(zv), &len);
92
93 zval_dtor(zv);
94 ZVAL_STRINGL(zv, str, len, 0);
95 }
96
97 static void sanitize_dimension(zval *zv TSRMLS_DC)
98 {
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);
101 long level = 0;
102
103 MAKE_STD_ZVAL(arr);
104 array_init(arr);
105 cur = &arr;
106
107 while (ptr < end) {
108 if (!var) {
109 var = ptr;
110 }
111
112 switch (*ptr) {
113 case '[':
114 if (++level > PG(max_input_nesting_level)) {
115 zval_ptr_dtor(&arr);
116 php_http_error(HE_WARNING, PHP_HTTP_E_QUERYSTRING, "Max input nesting level of %ld exceeded", PG(max_input_nesting_level));
117 return;
118 }
119 if (ptr - var == 0) {
120 ++var;
121 break;
122 }
123 /* no break */
124
125 case ']':
126
127 MAKE_STD_ZVAL(tmp);
128 ZVAL_NULL(tmp);
129 convert_to_array(*cur);
130
131 if (ptr - var) {
132 char chr = *ptr;
133 *ptr = '\0';
134 zend_symtable_update(Z_ARRVAL_PP(cur), var, ptr - var + 1, (void *) &tmp, sizeof(zval *), (void *) &cur);
135 *ptr = chr;
136 } else {
137 zend_hash_next_index_insert(Z_ARRVAL_PP(cur), (void *) &tmp, sizeof(zval *), (void *) &cur);
138 }
139
140 var = NULL;
141 break;
142 }
143
144 ++ptr;
145 }
146
147 if (zend_hash_num_elements(Z_ARRVAL_P(arr))) {
148 zval_dtor(zv);
149 ZVAL_COPY_VALUE(zv, arr);
150 FREE_ZVAL(arr);
151 } else {
152 zval_ptr_dtor(&arr);
153 }
154 }
155
156 static void prepare_dimension(zval *zv TSRMLS_DC)
157 {
158 if (Z_TYPE_P(zv) == IS_ARRAY) {
159 zval **zdata = &zv;
160 php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
161 php_http_buffer_t buf;
162
163 php_http_buffer_init(&buf);
164
165 do {
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);
168 } else {
169 php_http_buffer_appendf(&buf, "[%lu]", key.num);
170 }
171 } while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(zdata), (void *) &zdata) && Z_TYPE_PP(zdata) == IS_ARRAY);
172
173 php_http_buffer_fix(&buf);
174 zval_dtor(zv);
175 ZVAL_STRINGL(zv, buf.data, buf.used, 0);
176 }
177 }
178
179 static void sanitize_key(unsigned flags, char *str, size_t len, zval *zv TSRMLS_DC)
180 {
181 php_trim(str, len, NULL, 0, zv, 3 TSRMLS_CC);
182
183 if (flags & PHP_HTTP_PARAMS_DEFAULT) {
184 sanitize_default(zv TSRMLS_CC);
185 }
186
187 if (flags & PHP_HTTP_PARAMS_URLENCODED) {
188 sanitize_urlencoded(zv TSRMLS_CC);
189 }
190
191 if (flags & PHP_HTTP_PARAMS_DIMENSION) {
192 sanitize_dimension(zv TSRMLS_CC);
193 }
194 }
195
196 static void sanitize_value(unsigned flags, char *str, size_t len, zval *zv TSRMLS_DC)
197 {
198 php_trim(str, len, NULL, 0, zv, 3 TSRMLS_CC);
199
200 if (flags & PHP_HTTP_PARAMS_DEFAULT) {
201 sanitize_default(zv TSRMLS_CC);
202 }
203
204 if (flags & PHP_HTTP_PARAMS_URLENCODED) {
205 sanitize_urlencoded(zv TSRMLS_CC);
206 }
207 }
208
209 static void prepare_key(unsigned flags, char *old_key, size_t old_len, char **new_key, size_t *new_len TSRMLS_DC)
210 {
211 zval zv;
212
213 INIT_PZVAL(&zv);
214 ZVAL_STRINGL(&zv, old_key, old_len, 1);
215
216 if (flags & PHP_HTTP_PARAMS_DIMENSION) {
217 prepare_dimension(&zv TSRMLS_CC);
218 }
219
220 if (flags & PHP_HTTP_PARAMS_URLENCODED) {
221 prepare_urlencoded(&zv TSRMLS_CC);
222 }
223
224 if (flags & PHP_HTTP_PARAMS_DEFAULT) {
225 prepare_default(&zv TSRMLS_CC);
226 }
227
228 *new_key = Z_STRVAL(zv);
229 *new_len = Z_STRLEN(zv);
230 }
231
232 static void prepare_value(unsigned flags, zval *zv TSRMLS_DC)
233 {
234 if (flags & PHP_HTTP_PARAMS_DIMENSION) {
235 prepare_dimension(zv TSRMLS_CC);
236 }
237
238 if (flags & PHP_HTTP_PARAMS_URLENCODED) {
239 prepare_urlencoded(zv TSRMLS_CC);
240 }
241
242 if (flags & PHP_HTTP_PARAMS_DEFAULT) {
243 prepare_default(zv TSRMLS_CC);
244 }
245 }
246
247 static void merge_param(HashTable *params, zval *zdata, zval ***cur TSRMLS_DC)
248 {
249 zval **ptr, **zdata_ptr;
250 php_http_array_hashkey_t hkey = php_http_array_hashkey_init(0);
251
252 #if 0
253 {
254 zval tmp;
255 INIT_PZVAL_ARRAY(&tmp, params);
256 fprintf(stderr, "params = ");
257 zend_print_zval_r(&tmp, 1 TSRMLS_CC);
258 fprintf(stderr, "\n");
259 }
260 #endif
261
262 hkey.type = zend_hash_get_current_key_ex(Z_ARRVAL_P(zdata), &hkey.str, &hkey.len, &hkey.num, hkey.dup, NULL);
263
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))
266 ) {
267 zval *tmp;
268
269 /* create the entry if it doesn't exist */
270 zend_hash_get_current_data(Z_ARRVAL_P(zdata), (void *) &ptr);
271 Z_ADDREF_PP(ptr);
272 MAKE_STD_ZVAL(tmp);
273 array_init(tmp);
274 add_assoc_zval_ex(tmp, ZEND_STRS("value"), *ptr);
275
276 if (hkey.type == HASH_KEY_IS_STRING) {
277 zend_hash_update(params, hkey.str, hkey.len, (void *) &tmp, sizeof(zval *), (void *) &ptr);
278 } else {
279 zend_hash_index_update(params, hkey.num, (void *) &tmp, sizeof(zval *), (void *) &ptr);
280 }
281 } else {
282 /* merge */
283 if (hkey.type == HASH_KEY_IS_STRING) {
284 zend_hash_find(params, hkey.str, hkey.len, (void *) &ptr);
285 } else {
286 zend_hash_index_find(params, hkey.num, (void *) &ptr);
287 }
288
289 zdata_ptr = &zdata;
290
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)
294 ) {
295 /*
296 * params = [arr => [value => [0 => 1]]]
297 * ^- ptr
298 * zdata = [arr => [0 => NULL]]
299 * ^- zdata_ptr
300 */
301 zval **test_ptr;
302
303 while (Z_TYPE_PP(zdata_ptr) == IS_ARRAY
304 && SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(zdata_ptr), (void *) &test_ptr)
305 ) {
306 if (Z_TYPE_PP(test_ptr) == IS_ARRAY) {
307
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;
312 } else {
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);
315 break;
316 }
317 } else {
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);
323 break;
324 } else {
325 Z_ADDREF_PP(test_ptr);
326 zend_hash_next_index_insert(Z_ARRVAL_PP(ptr), (void *) test_ptr, sizeof(zval *), (void *) &ptr);
327 break;
328 }
329 }
330 } else {
331 /* this is the leaf */
332 Z_ADDREF_PP(test_ptr);
333 if (Z_TYPE_PP(ptr) != IS_ARRAY) {
334 zval_dtor(*ptr);
335 array_init(*ptr);
336 }
337 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)) {
338 zend_hash_update(Z_ARRVAL_PP(ptr), hkey.str, hkey.len, (void *) test_ptr, sizeof(zval *), (void *) &ptr);
339 } else if (hkey.num) {
340 zend_hash_index_update(Z_ARRVAL_PP(ptr), hkey.num, (void *) test_ptr, sizeof(zval *), (void *) &ptr);
341 } else {
342 zend_hash_next_index_insert(Z_ARRVAL_PP(ptr), (void *) test_ptr, sizeof(zval *), (void *) &ptr);
343 }
344 break;
345 }
346 }
347
348 }
349 }
350
351 /* bubble up */
352 while (Z_TYPE_PP(ptr) == IS_ARRAY && SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(ptr), (void *) &ptr));
353 *cur = ptr;
354 }
355
356 static void push_param(HashTable *params, php_http_params_state_t *state, const php_http_params_opts_t *opts TSRMLS_DC)
357 {
358 if (state->val.str) {
359 if (0 < (state->val.len = state->input.str - state->val.str)) {
360 sanitize_value(opts->flags, state->val.str, state->val.len, *(state->current.val) TSRMLS_CC);
361 }
362 } else if (state->arg.str) {
363 if (0 < (state->arg.len = state->input.str - state->arg.str)) {
364 zval *val, key;
365
366 INIT_PZVAL(&key);
367 sanitize_key(opts->flags, state->arg.str, state->arg.len, &key TSRMLS_CC);
368 if (Z_STRLEN(key)) {
369 MAKE_STD_ZVAL(val);
370 ZVAL_TRUE(val);
371 zend_symtable_update(Z_ARRVAL_PP(state->current.args), Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &val, sizeof(zval *), (void *) &state->current.val);
372 }
373 zval_dtor(&key);
374 }
375 } else if (state->param.str) {
376 if (0 < (state->param.len = state->input.str - state->param.str)) {
377 zval *prm, *arg, *val, *key;
378
379 MAKE_STD_ZVAL(key);
380 ZVAL_NULL(key);
381 sanitize_key(opts->flags, state->param.str, state->param.len, key TSRMLS_CC);
382 if (Z_TYPE_P(key) != IS_STRING) {
383 merge_param(params, key, &state->current.val TSRMLS_CC);
384 } else if (Z_STRLEN_P(key)) {
385 MAKE_STD_ZVAL(prm);
386 array_init(prm);
387
388 MAKE_STD_ZVAL(val);
389 if (opts->defval) {
390 ZVAL_COPY_VALUE(val, opts->defval);
391 zval_copy_ctor(val);
392 } else {
393 ZVAL_TRUE(val);
394 }
395 zend_hash_update(Z_ARRVAL_P(prm), "value", sizeof("value"), (void *) &val, sizeof(zval *), (void *) &state->current.val);
396
397 MAKE_STD_ZVAL(arg);
398 array_init(arg);
399 zend_hash_update(Z_ARRVAL_P(prm), "arguments", sizeof("arguments"), (void *) &arg, sizeof(zval *), (void *) &state->current.args);
400
401 zend_symtable_update(params, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void *) &prm, sizeof(zval *), (void *) &state->current.param);
402 }
403 zval_ptr_dtor(&key);
404 }
405 }
406 }
407
408 static inline zend_bool check_str(const char *chk_str, size_t chk_len, const char *sep_str, size_t sep_len) {
409 return 0 < sep_len && chk_len >= sep_len && !memcmp(chk_str, sep_str, sep_len);
410 }
411
412 static size_t check_sep(php_http_params_state_t *state, php_http_params_token_t **separators)
413 {
414 php_http_params_token_t **sep = separators;
415
416 if (sep) while (*sep) {
417 if (check_str(state->input.str, state->input.len, (*sep)->str, (*sep)->len)) {
418 return (*sep)->len;
419 }
420 ++sep;
421 }
422 return 0;
423 }
424
425 static void skip_sep(size_t skip, php_http_params_state_t *state, php_http_params_token_t **param, php_http_params_token_t **arg, php_http_params_token_t **val TSRMLS_DC)
426 {
427 size_t sep_len;
428
429 state->input.str += skip;
430 state->input.len -= skip;
431
432 while ( (param && (sep_len = check_sep(state, param)))
433 || (arg && (sep_len = check_sep(state, arg)))
434 || (val && (sep_len = check_sep(state, val)))
435 ) {
436 state->input.str += sep_len;
437 state->input.len -= sep_len;
438 }
439 }
440
441 PHP_HTTP_API HashTable *php_http_params_parse(HashTable *params, const php_http_params_opts_t *opts TSRMLS_DC)
442 {
443 php_http_params_state_t state = {{NULL,0}, {NULL,0}, {NULL,0}, {NULL,0}, {NULL,NULL,NULL}};
444
445 state.input.str = opts->input.str;
446 state.input.len = opts->input.len;
447
448 if (!params) {
449 ALLOC_HASHTABLE(params);
450 ZEND_INIT_SYMTABLE(params);
451 }
452
453 while (state.input.len) {
454 if (*state.input.str == '\\') {
455 ++state.input.str;
456 --state.input.len;
457 } else if (!state.param.str) {
458 /* initialize */
459 skip_sep(0, &state, opts->param, opts->arg, opts->val TSRMLS_CC);
460 state.param.str = state.input.str;
461 } else {
462 size_t sep_len;
463 /* are we at a param separator? */
464 if (0 < (sep_len = check_sep(&state, opts->param))) {
465 push_param(params, &state, opts TSRMLS_CC);
466
467 skip_sep(sep_len, &state, opts->param, opts->arg, opts->val TSRMLS_CC);
468
469 /* start off with a new param */
470 state.param.str = state.input.str;
471 state.param.len = 0;
472 state.arg.str = NULL;
473 state.arg.len = 0;
474 state.val.str = NULL;
475 state.val.len = 0;
476 } else
477 /* are we at an arg separator? */
478 if (0 < (sep_len = check_sep(&state, opts->arg))) {
479 push_param(params, &state, opts TSRMLS_CC);
480
481 skip_sep(sep_len, &state, NULL, opts->arg, opts->val TSRMLS_CC);
482
483 /* continue with a new arg */
484 state.arg.str = state.input.str;
485 state.arg.len = 0;
486 state.val.str = NULL;
487 state.val.len = 0;
488 } else
489 /* are we at a val separator? */
490 if (0 < (sep_len = check_sep(&state, opts->val))) {
491 /* only handle separator if we're not already reading in a val */
492 if (!state.val.str) {
493 push_param(params, &state, opts TSRMLS_CC);
494
495 skip_sep(sep_len, &state, NULL, NULL, opts->val TSRMLS_CC);
496
497 state.val.str = state.input.str;
498 state.val.len = 0;
499 }
500 }
501 }
502
503 if (state.input.len) {
504 ++state.input.str;
505 --state.input.len;
506 }
507 }
508 /* finalize */
509 push_param(params, &state, opts TSRMLS_CC);
510
511 return params;
512 }
513
514 static void shift_param(php_http_buffer_t *buf, char *key_str, size_t key_len, zval **zvalue, const char *css, size_t csl, const char *vss, size_t vsl, unsigned flags TSRMLS_DC)
515 {
516 if (Z_TYPE_PP(zvalue) == IS_ARRAY) {
517 zval *tmp = php_http_zsep(1, IS_ARRAY, *zvalue);
518
519 do {
520 char *str;
521 size_t len;
522 zval *tmp2;
523
524 if (PHP_HTTP_BUFFER_LEN(buf)) {
525 php_http_buffer_append(buf, css, csl);
526 }
527
528 prepare_key(flags, key_str, key_len, &str, &len TSRMLS_CC);
529 php_http_buffer_append(buf, str, len);
530 efree(str);
531
532 tmp2 = php_http_zsep(1, IS_ARRAY, tmp);
533 prepare_value(flags, tmp2 TSRMLS_CC);
534 php_http_buffer_append(buf, Z_STRVAL_P(tmp2), Z_STRLEN_P(tmp2));
535 zval_ptr_dtor(&tmp2);
536
537 zvalue = &tmp;
538 while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(zvalue), (void *) &zvalue) && Z_TYPE_PP(zvalue) == IS_ARRAY);
539
540 if (Z_TYPE_PP(zvalue) != IS_BOOL) {
541 php_http_buffer_append(buf, vss, vsl);
542
543 tmp2 = php_http_ztyp(IS_STRING, *zvalue);
544 prepare_value(flags, tmp2 TSRMLS_CC);
545 php_http_buffer_append(buf, Z_STRVAL_P(tmp2), Z_STRLEN_P(tmp2));
546 zval_ptr_dtor(&tmp2);
547 } else if (!Z_BVAL_PP(zvalue)) {
548 php_http_buffer_append(buf, vss, vsl);
549 php_http_buffer_appends(buf, "0");
550 }
551
552 } while (SUCCESS == zend_hash_move_forward(Z_ARRVAL_P(tmp)) && SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(tmp), (void *) &zvalue));
553
554 zval_ptr_dtor(&tmp);
555
556 } else {
557 zval *tmp;
558 char *str;
559 size_t len;
560
561 if (PHP_HTTP_BUFFER_LEN(buf)) {
562 php_http_buffer_append(buf, css, csl);
563 }
564
565 prepare_key(flags, key_str, key_len, &str, &len TSRMLS_CC);
566 php_http_buffer_append(buf, str, len);
567 efree(str);
568
569 if (Z_TYPE_PP(zvalue) != IS_BOOL) {
570 tmp = php_http_ztyp(IS_STRING, *zvalue);
571 prepare_value(flags, tmp TSRMLS_CC);
572 php_http_buffer_append(buf, vss, vsl);
573 php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
574 zval_ptr_dtor(&tmp);
575 } else if (!Z_BVAL_PP(zvalue)) {
576 php_http_buffer_append(buf, vss, vsl);
577 php_http_buffer_appends(buf, "0");
578 }
579 }
580 }
581
582 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)
583 {
584 zval **zparam;
585 HashPosition pos, pos1;
586 php_http_array_hashkey_t key = php_http_array_hashkey_init(0), key1 = php_http_array_hashkey_init(0);
587
588 if (!buf) {
589 buf = php_http_buffer_init(NULL);
590 }
591
592 FOREACH_HASH_KEYVAL(pos, params, key, zparam) {
593 zval **zvalue, **zargs;
594
595 if (Z_TYPE_PP(zparam) != IS_ARRAY || SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("value"), (void *) &zvalue)) {
596 zvalue = zparam;
597 }
598
599 php_http_array_hashkey_stringify(&key);
600 shift_param(buf, key.str, key.len - 1, zvalue, pss, psl, vss, vsl, flags TSRMLS_CC);
601 php_http_array_hashkey_stringfree(&key);
602
603 if (Z_TYPE_PP(zparam) == IS_ARRAY && SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("arguments"), (void *) &zvalue)) {
604 zvalue = zparam;
605 }
606
607 FOREACH_KEYVAL(pos1, *zvalue, key1, zargs) {
608 if (zvalue == zparam && key1.type == HASH_KEY_IS_STRING && !strcmp(key1.str, "value")) {
609 continue;
610 }
611
612 php_http_array_hashkey_stringify(&key1);
613 shift_param(buf, key1.str, key1.len - 1, zargs, ass, asl, vss, vsl, flags TSRMLS_CC);
614 php_http_array_hashkey_stringfree(&key1);
615 }
616 }
617 /*
618 FOREACH_HASH_KEYVAL(pos1, params, key1, zparam) {
619 if (PHP_HTTP_BUFFER_LEN(buf)) {
620 php_http_buffer_append(buf, pss, psl);
621 }
622
623 if (key1.type == HASH_KEY_IS_STRING) {
624 char *key;
625 size_t len;
626
627 prepare_key(flags, key1.str, key1.len - 1, &key, &len TSRMLS_CC);
628 php_http_buffer_append(buf, key, len);
629 efree(key);
630 } else {
631 php_http_buffer_appendf(buf, "%lu", key1.num);
632 }
633
634 if (Z_TYPE_PP(zparam) != IS_ARRAY) {
635 zval *tmp = php_http_ztyp(IS_STRING, *zparam);
636
637 prepare_value(flags, tmp TSRMLS_CC);
638
639 php_http_buffer_append(buf, vss, vsl);
640 php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
641 zval_ptr_dtor(&tmp);
642 } else {
643 zval **zvalue, **zargs, **zarg;
644
645 if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("value"), (void *) &zvalue)) {
646 if (Z_TYPE_PP(zvalue) != IS_BOOL) {
647 zval *tmp, *tmp2;
648
649 if (Z_TYPE_PP(zvalue) == IS_ARRAY) {
650 tmp = php_http_zsep(1, IS_ARRAY, *zvalue);
651 do {
652 if (key1.type == HASH_KEY_IS_STRING) {
653 char *key;
654 size_t len;
655
656 prepare_key(flags, key1.str, key1.len - 1, &key, &len TSRMLS_CC);
657 php_http_buffer_append(buf, key, len);
658 efree(key);
659 } else {
660 php_http_buffer_appendf(buf, "%lu", key1.num);
661 }
662
663 tmp2 = php_http_zsep(1, IS_ARRAY, tmp);
664 prepare_value(flags, tmp2 TSRMLS_CC);
665 php_http_buffer_append(buf, Z_STRVAL_P(tmp2), Z_STRLEN_P(tmp2));
666 zval_ptr_dtor(&tmp2);
667
668 while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(tmp), (void *) &zvalue) && Z_TYPE_PP(zvalue) == IS_ARRAY);
669
670 tmp2 = php_http_ztyp(IS_STRING, *zvalue);
671 prepare_value(flags, tmp2 TSRMLS_CC);
672 php_http_buffer_append(buf, vss, vsl);
673 php_http_buffer_append(buf, Z_STRVAL_P(tmp2), Z_STRLEN_P(tmp2));
674 zval_ptr_dtor(&tmp2);
675 } while (SUCCESS == zend_hash_move_forward(Z_ARRVAL_P(tmp)));
676 zval_ptr_dtor(&tmp);
677 } else {
678
679 tmp = php_http_ztyp(IS_STRING, *zvalue);
680 prepare_value(flags, tmp TSRMLS_CC);
681 php_http_buffer_append(buf, vss, vsl);
682 php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
683 zval_ptr_dtor(&tmp);
684 }
685 } else if (!Z_BVAL_PP(zvalue)) {
686 php_http_buffer_append(buf, vss, vsl);
687 php_http_buffer_appends(buf, "0");
688 }
689 }
690 if (SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("arguments"), (void *) &zargs)) {
691 zargs = zparam;
692 }
693
694 if (Z_TYPE_PP(zargs) == IS_ARRAY) {
695 FOREACH_KEYVAL(pos2, *zargs, key2, zarg) {
696 if (zargs == zparam && key2.type == HASH_KEY_IS_STRING && !strcmp(key2.str, "value")) {
697 continue;
698 }
699
700 if (PHP_HTTP_BUFFER_LEN(buf)) {
701 php_http_buffer_append(buf, ass, asl);
702 }
703
704 if (key2.type == HASH_KEY_IS_STRING) {
705 char *key;
706 size_t len;
707
708 prepare_key(flags, key2.str, key2.len - 1, &key, &len TSRMLS_CC);
709 php_http_buffer_append(buf, key, len);
710 efree(key);
711 } else {
712 php_http_buffer_appendf(buf, "%lu", key2.num);
713 }
714 if (Z_TYPE_PP(zarg) != IS_BOOL) {
715 zval *tmp;
716
717 if (Z_TYPE_PP(zarg) == IS_ARRAY) {
718 tmp = php_http_zsep(1, IS_ARRAY, *zarg);
719 prepare_value(flags, tmp TSRMLS_CC);
720 php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
721 zval_ptr_dtor(&tmp);
722
723 while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(zarg), (void *) &zarg) && Z_TYPE_PP(zarg) == IS_ARRAY);
724 }
725
726 tmp = php_http_ztyp(IS_STRING, *zarg);
727 prepare_value(flags, tmp TSRMLS_CC);
728 php_http_buffer_append(buf, vss, vsl);
729 php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
730 zval_ptr_dtor(&tmp);
731 } else if (!Z_BVAL_PP(zarg)) {
732 php_http_buffer_append(buf, vss, vsl);
733 php_http_buffer_appends(buf, "0");
734 }
735 }
736 }
737 }
738 }
739 */
740 php_http_buffer_shrink(buf);
741 php_http_buffer_fix(buf);
742
743 return buf;
744 }
745
746 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpParams, method, 0, req_args)
747 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpParams, method, 0)
748 #define PHP_HTTP_PARAMS_ME(method, visibility) PHP_ME(HttpParams, method, PHP_HTTP_ARGS(HttpParams, method), visibility)
749 #define PHP_HTTP_PARAMS_GME(method, visibility) PHP_ME(HttpParams, method, PHP_HTTP_ARGS(HttpParams, __getter), visibility)
750
751 PHP_HTTP_BEGIN_ARGS(__construct, 0)
752 PHP_HTTP_ARG_VAL(params, 0)
753 PHP_HTTP_ARG_VAL(param_sep, 0)
754 PHP_HTTP_ARG_VAL(arg_sep, 0)
755 PHP_HTTP_ARG_VAL(val_sep, 0)
756 PHP_HTTP_ARG_VAL(flags, 0)
757 PHP_HTTP_END_ARGS;
758
759 PHP_HTTP_EMPTY_ARGS(toArray);
760 PHP_HTTP_EMPTY_ARGS(toString);
761
762 PHP_HTTP_BEGIN_ARGS(offsetExists, 1)
763 PHP_HTTP_ARG_VAL(name, 0)
764 PHP_HTTP_END_ARGS;
765
766 PHP_HTTP_BEGIN_ARGS(offsetUnset, 1)
767 PHP_HTTP_ARG_VAL(name, 0)
768 PHP_HTTP_END_ARGS;
769
770 PHP_HTTP_BEGIN_ARGS(offsetGet, 1)
771 PHP_HTTP_ARG_VAL(name, 0)
772 PHP_HTTP_END_ARGS;
773
774 PHP_HTTP_BEGIN_ARGS(offsetSet, 2)
775 PHP_HTTP_ARG_VAL(name, 0)
776 PHP_HTTP_ARG_VAL(value, 0)
777 PHP_HTTP_END_ARGS;
778
779 static zend_class_entry *php_http_params_class_entry;
780
781 zend_class_entry *php_http_params_get_class_entry(void)
782 {
783 return php_http_params_class_entry;
784 }
785
786 static zend_function_entry php_http_params_method_entry[] = {
787 PHP_HTTP_PARAMS_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR|ZEND_ACC_FINAL)
788
789 PHP_HTTP_PARAMS_ME(toArray, ZEND_ACC_PUBLIC)
790 PHP_HTTP_PARAMS_ME(toString, ZEND_ACC_PUBLIC)
791 ZEND_MALIAS(HttpParams, __toString, toString, PHP_HTTP_ARGS(HttpParams, toString), ZEND_ACC_PUBLIC)
792
793 PHP_HTTP_PARAMS_ME(offsetExists, ZEND_ACC_PUBLIC)
794 PHP_HTTP_PARAMS_ME(offsetUnset, ZEND_ACC_PUBLIC)
795 PHP_HTTP_PARAMS_ME(offsetSet, ZEND_ACC_PUBLIC)
796 PHP_HTTP_PARAMS_ME(offsetGet, ZEND_ACC_PUBLIC)
797
798 EMPTY_FUNCTION_ENTRY
799 };
800
801 PHP_MINIT_FUNCTION(http_params)
802 {
803 PHP_HTTP_REGISTER_CLASS(http, Params, http_params, php_http_object_get_class_entry(), 0);
804
805 zend_class_implements(php_http_params_class_entry TSRMLS_CC, 1, zend_ce_arrayaccess);
806
807 zend_declare_class_constant_stringl(php_http_params_class_entry, ZEND_STRL("DEF_PARAM_SEP"), ZEND_STRL(",") TSRMLS_CC);
808 zend_declare_class_constant_stringl(php_http_params_class_entry, ZEND_STRL("DEF_ARG_SEP"), ZEND_STRL(";") TSRMLS_CC);
809 zend_declare_class_constant_stringl(php_http_params_class_entry, ZEND_STRL("DEF_VAL_SEP"), ZEND_STRL("=") TSRMLS_CC);
810 zend_declare_class_constant_stringl(php_http_params_class_entry, ZEND_STRL("COOKIE_PARAM_SEP"), ZEND_STRL("") TSRMLS_CC);
811
812 zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_RAW"), PHP_HTTP_PARAMS_RAW TSRMLS_CC);
813 zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_DEFAULT"), PHP_HTTP_PARAMS_DEFAULT TSRMLS_CC);
814 zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_URLENCODED"), PHP_HTTP_PARAMS_URLENCODED TSRMLS_CC);
815 zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_DIMENSION"), PHP_HTTP_PARAMS_DIMENSION TSRMLS_CC);
816 zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_QUERY"), PHP_HTTP_PARAMS_QUERY TSRMLS_CC);
817
818 zend_declare_property_null(php_http_params_class_entry, ZEND_STRL("params"), ZEND_ACC_PUBLIC TSRMLS_CC);
819 zend_declare_property_stringl(php_http_params_class_entry, ZEND_STRL("param_sep"), ZEND_STRL(","), ZEND_ACC_PUBLIC TSRMLS_CC);
820 zend_declare_property_stringl(php_http_params_class_entry, ZEND_STRL("arg_sep"), ZEND_STRL(";"), ZEND_ACC_PUBLIC TSRMLS_CC);
821 zend_declare_property_stringl(php_http_params_class_entry, ZEND_STRL("val_sep"), ZEND_STRL("="), ZEND_ACC_PUBLIC TSRMLS_CC);
822 zend_declare_property_long(php_http_params_class_entry, ZEND_STRL("flags"), PHP_HTTP_PARAMS_DEFAULT, ZEND_ACC_PUBLIC TSRMLS_CC);
823
824 return SUCCESS;
825 }
826
827 PHP_HTTP_API php_http_params_token_t **php_http_params_separator_init(zval *zv TSRMLS_DC)
828 {
829 zval **sep;
830 HashPosition pos;
831 php_http_params_token_t **ret, **tmp;
832
833 if (!zv) {
834 return NULL;
835 }
836
837 zv = php_http_ztyp(IS_ARRAY, zv);
838 ret = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(zv)) + 1, sizeof(*ret));
839
840 tmp = ret;
841 FOREACH_VAL(pos, zv, sep) {
842 zval *zt = php_http_ztyp(IS_STRING, *sep);
843
844 if (Z_STRLEN_P(zt)) {
845 *tmp = emalloc(sizeof(**tmp));
846 (*tmp)->str = estrndup(Z_STRVAL_P(zt), (*tmp)->len = Z_STRLEN_P(zt));
847 ++tmp;
848 }
849 zval_ptr_dtor(&zt);
850 }
851 zval_ptr_dtor(&zv);
852
853 *tmp = NULL;
854 return ret;
855 }
856
857 PHP_HTTP_API void php_http_params_separator_free(php_http_params_token_t **separator)
858 {
859 php_http_params_token_t **sep = separator;
860 if (sep) {
861 while (*sep) {
862 STR_FREE((*sep)->str);
863 efree(*sep);
864 ++sep;
865 }
866 efree(separator);
867 }
868 }
869
870 PHP_METHOD(HttpParams, __construct)
871 {
872 with_error_handling(EH_THROW, php_http_exception_get_class_entry()) {
873 zval *zcopy, *zparams = NULL, *param_sep = NULL, *arg_sep = NULL, *val_sep = NULL;
874 long flags = PHP_HTTP_PARAMS_DEFAULT;
875
876 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/z/z/z/l", &zparams, &param_sep, &arg_sep, &val_sep, &flags)) {
877 switch (ZEND_NUM_ARGS()) {
878 case 5:
879 zend_update_property_long(php_http_params_class_entry, getThis(), ZEND_STRL("flags"), flags TSRMLS_CC);
880 /* no break */
881 case 4:
882 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), val_sep TSRMLS_CC);
883 /* no break */
884 case 3:
885 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), arg_sep TSRMLS_CC);
886 /* no break */
887 case 2:
888 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), param_sep TSRMLS_CC);
889 /* no break */
890 }
891
892 if (zparams) {
893 switch (Z_TYPE_P(zparams)) {
894 case IS_OBJECT:
895 case IS_ARRAY:
896 zcopy = php_http_zsep(1, IS_ARRAY, zparams);
897 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zcopy TSRMLS_CC);
898 zval_ptr_dtor(&zcopy);
899 break;
900 default:
901 zcopy = php_http_ztyp(IS_STRING, zparams);
902 if (Z_STRLEN_P(zcopy)) {
903 php_http_params_opts_t opts = {
904 .input = {
905 .str = Z_STRVAL_P(zcopy),
906 .len = Z_STRLEN_P(zcopy)
907 },
908 .param = php_http_params_separator_init(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC) TSRMLS_CC),
909 .arg = php_http_params_separator_init(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC) TSRMLS_CC),
910 .val = php_http_params_separator_init(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC) TSRMLS_CC),
911 .flags = flags
912 };
913
914 MAKE_STD_ZVAL(zparams);
915 array_init(zparams);
916 php_http_params_parse(Z_ARRVAL_P(zparams), &opts TSRMLS_CC);
917 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC);
918 zval_ptr_dtor(&zparams);
919
920 php_http_params_separator_free(opts.param);
921 php_http_params_separator_free(opts.arg);
922 php_http_params_separator_free(opts.val);
923 }
924 zval_ptr_dtor(&zcopy);
925 break;
926 }
927 } else {
928 MAKE_STD_ZVAL(zparams);
929 array_init(zparams);
930 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC);
931 zval_ptr_dtor(&zparams);
932 }
933 }
934 } end_error_handling();
935 }
936
937 PHP_METHOD(HttpParams, toArray)
938 {
939 if (SUCCESS != zend_parse_parameters_none()) {
940 RETURN_FALSE;
941 }
942 RETURN_PROP(php_http_params_class_entry, "params");
943 }
944
945 PHP_METHOD(HttpParams, toString)
946 {
947 zval **tmp, *zparams, *zpsep, *zasep, *zvsep, *zflags;
948 php_http_buffer_t buf;
949
950 zparams = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));
951 zflags = php_http_ztyp(IS_LONG, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("flags"), 0 TSRMLS_CC));
952 zpsep = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC);
953 zasep = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC);
954 zvsep = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC);
955
956 zpsep = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC);
957 if (Z_TYPE_P(zpsep) == IS_ARRAY && SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zpsep), (void *) &tmp)) {
958 zpsep = php_http_ztyp(IS_STRING, *tmp);
959 } else {
960 zpsep = php_http_ztyp(IS_STRING, zpsep);
961 }
962 zasep = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC);
963 if (Z_TYPE_P(zasep) == IS_ARRAY && SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zasep), (void *) &tmp)) {
964 zasep = php_http_ztyp(IS_STRING, *tmp);
965 } else {
966 zasep = php_http_ztyp(IS_STRING, zasep);
967 }
968 zvsep = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC);
969 if (Z_TYPE_P(zvsep) == IS_ARRAY && SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zvsep), (void *) &tmp)) {
970 zvsep = php_http_ztyp(IS_STRING, *tmp);
971 } else {
972 zvsep = php_http_ztyp(IS_STRING, zvsep);
973 }
974
975 php_http_buffer_init(&buf);
976 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);
977
978 zval_ptr_dtor(&zparams);
979 zval_ptr_dtor(&zpsep);
980 zval_ptr_dtor(&zasep);
981 zval_ptr_dtor(&zvsep);
982 zval_ptr_dtor(&zflags);
983
984 RETVAL_PHP_HTTP_BUFFER_VAL(&buf);
985 }
986
987 PHP_METHOD(HttpParams, offsetExists)
988 {
989 char *name_str;
990 int name_len;
991
992 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
993 zval **zparam, *zparams = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));
994
995 if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(zparams), name_str, name_len + 1, (void *) &zparam)) {
996 RETVAL_BOOL(Z_TYPE_PP(zparam) != IS_NULL);
997 } else {
998 RETVAL_FALSE;
999 }
1000 zval_ptr_dtor(&zparams);
1001 }
1002 }
1003
1004 PHP_METHOD(HttpParams, offsetGet)
1005 {
1006 char *name_str;
1007 int name_len;
1008
1009 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
1010 zval **zparam, *zparams = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));
1011
1012 if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(zparams), name_str, name_len + 1, (void *) &zparam)) {
1013 RETVAL_ZVAL(*zparam, 1, 0);
1014 }
1015
1016 zval_ptr_dtor(&zparams);
1017 }
1018 }
1019
1020
1021 PHP_METHOD(HttpParams, offsetUnset)
1022 {
1023 char *name_str;
1024 int name_len;
1025
1026 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
1027 zval *zparams = php_http_zsep(1, IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));
1028
1029 zend_symtable_del(Z_ARRVAL_P(zparams), name_str, name_len + 1);
1030 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC);
1031
1032 zval_ptr_dtor(&zparams);
1033 }
1034 }
1035
1036 PHP_METHOD(HttpParams, offsetSet)
1037 {
1038 zval *nvalue;
1039 char *name_str;
1040 int name_len;
1041
1042 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name_str, &name_len, &nvalue)) {
1043 zval **zparam, *zparams = php_http_zsep(1, IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));
1044
1045 if (name_len) {
1046 if (Z_TYPE_P(nvalue) == IS_ARRAY) {
1047 zval *new_zparam;
1048
1049 if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(zparams), name_str, name_len + 1, (void *) &zparam)) {
1050 new_zparam = php_http_zsep(1, IS_ARRAY, *zparam);
1051 array_join(Z_ARRVAL_P(nvalue), Z_ARRVAL_P(new_zparam), 0, 0);
1052 } else {
1053 new_zparam = nvalue;
1054 Z_ADDREF_P(new_zparam);
1055 }
1056 add_assoc_zval_ex(zparams, name_str, name_len + 1, new_zparam);
1057 } else {
1058 zval *tmp;
1059
1060 if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(zparams), name_str, name_len + 1, (void *) &zparam)) {
1061 tmp = php_http_zsep(1, IS_ARRAY, *zparam);
1062 } else {
1063 MAKE_STD_ZVAL(tmp);
1064 array_init(tmp);
1065 }
1066
1067 Z_ADDREF_P(nvalue);
1068 add_assoc_zval_ex(tmp, ZEND_STRS("value"), nvalue);
1069 add_assoc_zval_ex(zparams, name_str, name_len + 1, tmp);
1070 }
1071 } else {
1072 zval *tmp = php_http_ztyp(IS_STRING, nvalue), *arr;
1073
1074 MAKE_STD_ZVAL(arr);
1075 array_init(arr);
1076 add_assoc_bool_ex(arr, ZEND_STRS("value"), 1);
1077 add_assoc_zval_ex(zparams, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp) + 1, arr);
1078 zval_ptr_dtor(&tmp);
1079 }
1080
1081 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC);
1082 zval_ptr_dtor(&zparams);
1083 }
1084 }
1085
1086 /*
1087 * Local variables:
1088 * tab-width: 4
1089 * c-basic-offset: 4
1090 * End:
1091 * vim600: noet sw=4 ts=4 fdm=marker
1092 * vim<600: noet sw=4 ts=4
1093 */
1094