move the param string builder into it's own function
[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 };
23
24 PHP_HTTP_API php_http_params_opts_t *php_http_params_opts_default_get(php_http_params_opts_t *opts)
25 {
26 if (!opts) {
27 opts = emalloc(sizeof(*opts));
28 }
29
30 memcpy(opts, &def_opts, sizeof(def_opts));
31
32 return opts;
33 }
34
35 typedef struct php_http_params_state {
36 php_http_params_token_t input;
37 php_http_params_token_t param;
38 php_http_params_token_t arg;
39 php_http_params_token_t val;
40 struct {
41 zval **param;
42 zval **args;
43 zval **val;
44 } current;
45 } php_http_params_state_t;
46
47 static inline void sanitize_string(char *str, size_t len, zval *zv TSRMLS_DC)
48 {
49 /* trim whitespace */
50 php_trim(str, len, NULL, 0, zv, 3 TSRMLS_CC);
51
52 /* dequote */
53 if (Z_STRVAL_P(zv)[0] == '"' && Z_STRVAL_P(zv)[Z_STRLEN_P(zv) - 1] == '"') {
54 size_t deq_len = Z_STRLEN_P(zv) - 2;
55 char *deq = estrndup(Z_STRVAL_P(zv) + 1, deq_len);
56
57 zval_dtor(zv);
58 ZVAL_STRINGL(zv, deq, deq_len, 0);
59 }
60
61 /* strip slashes */
62 php_stripslashes(Z_STRVAL_P(zv), &Z_STRLEN_P(zv) TSRMLS_CC);
63 }
64
65 static void push_param(HashTable *params, php_http_params_state_t *state, const php_http_params_opts_t *opts TSRMLS_DC)
66 {
67 if (state->val.str) {
68 if (0 < (state->val.len = state->input.str - state->val.str)) {
69 sanitize_string(state->val.str, state->val.len, *(state->current.val) TSRMLS_CC);
70 }
71 } else if (state->arg.str) {
72 if (0 < (state->arg.len = state->input.str - state->arg.str)) {
73 zval *val, key;
74
75 INIT_PZVAL(&key);
76 sanitize_string(state->arg.str, state->arg.len, &key TSRMLS_CC);
77 if (Z_STRLEN(key)) {
78 MAKE_STD_ZVAL(val);
79 ZVAL_TRUE(val);
80 zend_symtable_update(Z_ARRVAL_PP(state->current.args), Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &val, sizeof(zval *), (void *) &state->current.val);
81 }
82 zval_dtor(&key);
83 }
84 } else if (state->param.str) {
85 if (0 < (state->param.len = state->input.str - state->param.str)) {
86 zval *prm, *arg, *val, key;
87
88 INIT_PZVAL(&key);
89 sanitize_string(state->param.str, state->param.len, &key TSRMLS_CC);
90 if (Z_STRLEN(key)) {
91 MAKE_STD_ZVAL(prm);
92 array_init(prm);
93 MAKE_STD_ZVAL(val);
94 ZVAL_TRUE(val);
95 zend_hash_update(Z_ARRVAL_P(prm), "value", sizeof("value"), (void *) &val, sizeof(zval *), (void *) &state->current.val);
96
97 MAKE_STD_ZVAL(arg);
98 array_init(arg);
99 zend_hash_update(Z_ARRVAL_P(prm), "arguments", sizeof("arguments"), (void *) &arg, sizeof(zval *), (void *) &state->current.args);
100
101 zend_symtable_update(params, Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &prm, sizeof(zval *), (void *) &state->current.param);
102 }
103 zval_dtor(&key);
104 }
105 }
106 }
107
108 static inline zend_bool check_str(const char *chk_str, size_t chk_len, const char *sep_str, size_t sep_len) {
109 return 0 < sep_len && chk_len >= sep_len && !memcmp(chk_str, sep_str, sep_len);
110 }
111
112 static size_t check_sep(php_http_params_state_t *state, php_http_params_token_t **separators)
113 {
114 php_http_params_token_t **sep = separators;
115
116 if (sep) while (*sep) {
117 if (check_str(state->input.str, state->input.len, (*sep)->str, (*sep)->len)) {
118 return (*sep)->len;
119 }
120 ++sep;
121 }
122 return 0;
123 }
124
125 PHP_HTTP_API HashTable *php_http_params_parse(HashTable *params, const php_http_params_opts_t *opts TSRMLS_DC)
126 {
127 php_http_params_state_t state = {{NULL,0}, {NULL,0}, {NULL,0}, {NULL,0}, {NULL,NULL,NULL}};
128
129 state.input.str = opts->input.str;
130 state.input.len = opts->input.len;
131
132 if (!params) {
133 ALLOC_HASHTABLE(params);
134 ZEND_INIT_SYMTABLE(params);
135 }
136
137 while (state.input.len) {
138 if (!state.param.str) {
139 /* initialize */
140 state.param.str = state.input.str;
141 } else {
142 size_t sep_len;
143 /* are we at a param separator? */
144 if (0 < (sep_len = check_sep(&state, opts->param))) {
145 push_param(params, &state, opts TSRMLS_CC);
146
147 /* start off with a new param */
148 state.param.str = state.input.str + sep_len;
149 state.param.len = 0;
150 state.arg.str = NULL;
151 state.arg.len = 0;
152 state.val.str = NULL;
153 state.val.len = 0;
154 } else
155 /* are we at an arg separator? */
156 if (0 < (sep_len = check_sep(&state, opts->arg))) {
157 push_param(params, &state, opts TSRMLS_CC);
158
159 /* continue with a new arg */
160 state.arg.str = state.input.str + sep_len;
161 state.arg.len = 0;
162 state.val.str = NULL;
163 state.val.len = 0;
164 } else
165 /* are we at a val separator? */
166 if (0 < (sep_len = check_sep(&state, opts->val))) {
167 /* only handle separator if we're not already reading in a val */
168 if (!state.val.str) {
169 push_param(params, &state, opts TSRMLS_CC);
170
171 state.val.str = state.input.str + sep_len;
172 state.val.len = 0;
173 }
174 }
175 }
176
177 ++state.input.str;
178 --state.input.len;
179 }
180 /* finalize */
181 push_param(params, &state, opts TSRMLS_CC);
182
183 return params;
184 }
185
186 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 TSRMLS_DC)
187 {
188 zval **zparam;
189 HashPosition pos1, pos2;
190 php_http_array_hashkey_t key1 = php_http_array_hashkey_init(0), key2 = php_http_array_hashkey_init(0);
191
192 if (!buf) {
193 buf = php_http_buffer_init(NULL);
194 }
195
196 FOREACH_HASH_KEYVAL(pos1, params, key1, zparam) {
197 /* new param ? */
198 if (PHP_HTTP_BUFFER_LEN(buf)) {
199 php_http_buffer_append(buf, pss, psl);
200 }
201
202 /* add name */
203 if (key1.type == HASH_KEY_IS_STRING) {
204 php_http_buffer_append(buf, key1.str, key1.len - 1);
205 } else {
206 php_http_buffer_appendf(buf, "%lu", key1.num);
207 }
208
209 if (Z_TYPE_PP(zparam) == IS_ARRAY) {
210 zval **zvalue, **zargs, **zarg;
211
212 /* got a value? */
213 if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("value"), (void *) &zvalue)) {
214 if (Z_TYPE_PP(zvalue) != IS_BOOL) {
215 zval *tmp = php_http_ztyp(IS_STRING, *zvalue);
216
217 php_http_buffer_append(buf, vss, vsl);
218 php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
219 zval_ptr_dtor(&tmp);
220 } else if (!Z_BVAL_PP(zvalue)) {
221 php_http_buffer_append(buf, vss, vsl);
222 php_http_buffer_appends(buf, "0");
223 }
224 }
225 /* add arguments */
226 if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("arguments"), (void *) &zargs)) {
227 if (Z_TYPE_PP(zargs) == IS_ARRAY) {
228 FOREACH_KEYVAL(pos2, *zargs, key2, zarg) {
229 /* new arg? */
230 if (PHP_HTTP_BUFFER_LEN(buf)) {
231 php_http_buffer_append(buf, ass, asl);
232 }
233
234 /* add name */
235 if (key2.type == HASH_KEY_IS_STRING) {
236 php_http_buffer_append(buf, key2.str, key2.len - 1);
237 } else {
238 php_http_buffer_appendf(buf, "%lu", key2.num);
239 }
240 /* add value */
241 if (Z_TYPE_PP(zarg) != IS_BOOL) {
242 zval *tmp = php_http_ztyp(IS_STRING, *zarg);
243 int escaped_len;
244
245 Z_STRVAL_P(tmp) = php_addslashes(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), &escaped_len, 1 TSRMLS_CC);
246 php_http_buffer_append(buf, vss, vsl);
247 if (escaped_len != Z_STRLEN_P(tmp)) {
248 php_http_buffer_appends(buf, "\"");
249 php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp) = escaped_len);
250 php_http_buffer_appends(buf, "\"");
251 } else {
252 php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
253 }
254 zval_ptr_dtor(&tmp);
255 } else if (!Z_BVAL_PP(zarg)) {
256 php_http_buffer_append(buf, vss, vsl);
257 php_http_buffer_appends(buf, "0");
258 }
259 }
260 }
261 }
262 }
263 }
264
265 php_http_buffer_shrink(buf);
266 php_http_buffer_fix(buf);
267
268 return buf;
269 }
270
271 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpParams, method, 0, req_args)
272 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpParams, method, 0)
273 #define PHP_HTTP_PARAMS_ME(method, visibility) PHP_ME(HttpParams, method, PHP_HTTP_ARGS(HttpParams, method), visibility)
274 #define PHP_HTTP_PARAMS_GME(method, visibility) PHP_ME(HttpParams, method, PHP_HTTP_ARGS(HttpParams, __getter), visibility)
275
276 PHP_HTTP_BEGIN_ARGS(__construct, 0)
277 PHP_HTTP_ARG_VAL(params, 0)
278 PHP_HTTP_ARG_VAL(param_sep, 0)
279 PHP_HTTP_ARG_VAL(arg_sep, 0)
280 PHP_HTTP_ARG_VAL(val_sep, 0)
281 PHP_HTTP_END_ARGS;
282
283 PHP_HTTP_EMPTY_ARGS(toArray);
284 PHP_HTTP_EMPTY_ARGS(toString);
285
286 PHP_HTTP_BEGIN_ARGS(offsetExists, 1)
287 PHP_HTTP_ARG_VAL(name, 0)
288 PHP_HTTP_END_ARGS;
289
290 PHP_HTTP_BEGIN_ARGS(offsetUnset, 1)
291 PHP_HTTP_ARG_VAL(name, 0)
292 PHP_HTTP_END_ARGS;
293
294 PHP_HTTP_BEGIN_ARGS(offsetGet, 1)
295 PHP_HTTP_ARG_VAL(name, 0)
296 PHP_HTTP_END_ARGS;
297
298 PHP_HTTP_BEGIN_ARGS(offsetSet, 2)
299 PHP_HTTP_ARG_VAL(name, 0)
300 PHP_HTTP_ARG_VAL(value, 0)
301 PHP_HTTP_END_ARGS;
302
303 zend_class_entry *php_http_params_class_entry;
304 zend_function_entry php_http_params_method_entry[] = {
305 PHP_HTTP_PARAMS_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR|ZEND_ACC_FINAL)
306
307 PHP_HTTP_PARAMS_ME(toArray, ZEND_ACC_PUBLIC)
308 PHP_HTTP_PARAMS_ME(toString, ZEND_ACC_PUBLIC)
309 ZEND_MALIAS(HttpParams, __toString, toString, PHP_HTTP_ARGS(HttpParams, toString), ZEND_ACC_PUBLIC)
310
311 PHP_HTTP_PARAMS_ME(offsetExists, ZEND_ACC_PUBLIC)
312 PHP_HTTP_PARAMS_ME(offsetUnset, ZEND_ACC_PUBLIC)
313 PHP_HTTP_PARAMS_ME(offsetSet, ZEND_ACC_PUBLIC)
314 PHP_HTTP_PARAMS_ME(offsetGet, ZEND_ACC_PUBLIC)
315
316 EMPTY_FUNCTION_ENTRY
317 };
318
319 PHP_MINIT_FUNCTION(http_params)
320 {
321 PHP_HTTP_REGISTER_CLASS(http, Params, http_params, php_http_object_class_entry, 0);
322
323 zend_class_implements(php_http_params_class_entry TSRMLS_CC, 1, zend_ce_arrayaccess);
324
325 zend_declare_class_constant_stringl(php_http_params_class_entry, ZEND_STRL("DEF_PARAM_SEP"), ZEND_STRL(",") TSRMLS_CC);
326 zend_declare_class_constant_stringl(php_http_params_class_entry, ZEND_STRL("DEF_ARG_SEP"), ZEND_STRL(";") TSRMLS_CC);
327 zend_declare_class_constant_stringl(php_http_params_class_entry, ZEND_STRL("DEF_VAL_SEP"), ZEND_STRL("=") TSRMLS_CC);
328 zend_declare_class_constant_stringl(php_http_params_class_entry, ZEND_STRL("COOKIE_PARAM_SEP"), ZEND_STRL("") TSRMLS_CC);
329
330 zend_declare_property_null(php_http_params_class_entry, ZEND_STRL("params"), ZEND_ACC_PUBLIC TSRMLS_CC);
331 zend_declare_property_stringl(php_http_params_class_entry, ZEND_STRL("param_sep"), ZEND_STRL(","), ZEND_ACC_PUBLIC TSRMLS_CC);
332 zend_declare_property_stringl(php_http_params_class_entry, ZEND_STRL("arg_sep"), ZEND_STRL(";"), ZEND_ACC_PUBLIC TSRMLS_CC);
333 zend_declare_property_stringl(php_http_params_class_entry, ZEND_STRL("val_sep"), ZEND_STRL("="), ZEND_ACC_PUBLIC TSRMLS_CC);
334
335 return SUCCESS;
336 }
337
338 static php_http_params_token_t **parse_sep(zval *zv TSRMLS_DC)
339 {
340 zval **sep;
341 HashPosition pos;
342 php_http_params_token_t **ret, **tmp;
343
344 if (!zv) {
345 return NULL;
346 }
347
348 zv = php_http_ztyp(IS_ARRAY, zv);
349 ret = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(zv)) + 1, sizeof(*ret));
350
351 tmp = ret;
352 FOREACH_VAL(pos, zv, sep) {
353 zval *zt = php_http_ztyp(IS_STRING, *sep);
354
355 if (Z_STRLEN_P(zt)) {
356 *tmp = emalloc(sizeof(**tmp));
357 (*tmp)->str = estrndup(Z_STRVAL_P(zt), (*tmp)->len = Z_STRLEN_P(zt));
358 ++tmp;
359 }
360 zval_ptr_dtor(&zt);
361 }
362 zval_ptr_dtor(&zv);
363
364 *tmp = NULL;
365 return ret;
366 }
367
368 static void free_sep(php_http_params_token_t **separator) {
369 php_http_params_token_t **sep = separator;
370 if (sep) {
371 while (*sep) {
372 STR_FREE((*sep)->str);
373 efree(*sep);
374 ++sep;
375 }
376 efree(separator);
377 }
378 }
379
380 PHP_METHOD(HttpParams, __construct)
381 {
382 with_error_handling(EH_THROW, php_http_exception_class_entry) {
383 zval *zcopy, *zparams = NULL, *param_sep = NULL, *arg_sep = NULL, *val_sep = NULL;
384
385 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/z/z/z/", &zparams, &param_sep, &arg_sep, &val_sep)) {
386 switch (ZEND_NUM_ARGS()) {
387 case 4:
388 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), val_sep TSRMLS_CC);
389 /* no break */
390 case 3:
391 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), arg_sep TSRMLS_CC);
392 /* no break */
393 case 2:
394 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), param_sep TSRMLS_CC);
395 /* no break */
396 }
397
398 if (zparams) {
399 switch (Z_TYPE_P(zparams)) {
400 case IS_OBJECT:
401 case IS_ARRAY:
402 zcopy = php_http_zsep(1, IS_ARRAY, zparams);
403 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zcopy TSRMLS_CC);
404 zval_ptr_dtor(&zcopy);
405 break;
406 default:
407 zcopy = php_http_ztyp(IS_STRING, zparams);
408 if (Z_STRLEN_P(zcopy)) {
409 php_http_params_opts_t opts = {
410 .input = {
411 .str = Z_STRVAL_P(zcopy),
412 .len = Z_STRLEN_P(zcopy)
413 },
414 .param = parse_sep(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC) TSRMLS_CC),
415 .arg = parse_sep(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC) TSRMLS_CC),
416 .val = parse_sep(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC) TSRMLS_CC)
417 };
418
419 MAKE_STD_ZVAL(zparams);
420 array_init(zparams);
421 php_http_params_parse(Z_ARRVAL_P(zparams), &opts TSRMLS_CC);
422 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC);
423 zval_ptr_dtor(&zparams);
424
425 free_sep(opts.param);
426 free_sep(opts.arg);
427 free_sep(opts.val);
428 }
429 zval_ptr_dtor(&zcopy);
430 break;
431 }
432 } else {
433 MAKE_STD_ZVAL(zparams);
434 array_init(zparams);
435 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC);
436 zval_ptr_dtor(&zparams);
437 }
438 }
439 } end_error_handling();
440 }
441
442 PHP_METHOD(HttpParams, toArray)
443 {
444 if (SUCCESS != zend_parse_parameters_none()) {
445 RETURN_FALSE;
446 }
447 RETURN_PROP(php_http_params_class_entry, "params");
448 }
449
450 PHP_METHOD(HttpParams, toString)
451 {
452 zval *zparams, *zpsep, *zasep, *zvsep;
453 php_http_buffer_t buf;
454
455 zparams = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));
456 zpsep = php_http_ztyp(IS_STRING, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC));
457 zasep = php_http_ztyp(IS_STRING, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC));
458 zvsep = php_http_ztyp(IS_STRING, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC));
459
460 php_http_buffer_init(&buf);
461 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) TSRMLS_CC);
462
463 zval_ptr_dtor(&zparams);
464 zval_ptr_dtor(&zpsep);
465 zval_ptr_dtor(&zasep);
466 zval_ptr_dtor(&zvsep);
467
468 RETVAL_PHP_HTTP_BUFFER_VAL(&buf);
469 }
470
471 PHP_METHOD(HttpParams, offsetExists)
472 {
473 char *name_str;
474 int name_len;
475
476 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
477 zval **zparam, *zparams = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));
478
479 if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(zparams), name_str, name_len + 1, (void *) &zparam)) {
480 RETVAL_BOOL(Z_TYPE_PP(zparam) != IS_NULL);
481 } else {
482 RETVAL_FALSE;
483 }
484 zval_ptr_dtor(&zparams);
485 }
486 }
487
488 PHP_METHOD(HttpParams, offsetGet)
489 {
490 char *name_str;
491 int name_len;
492
493 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
494 zval **zparam, *zparams = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));
495
496 if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(zparams), name_str, name_len + 1, (void *) &zparam)) {
497 RETVAL_ZVAL(*zparam, 1, 0);
498 }
499
500 zval_ptr_dtor(&zparams);
501 }
502 }
503
504
505 PHP_METHOD(HttpParams, offsetUnset)
506 {
507 char *name_str;
508 int name_len;
509
510 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
511 zval *zparams = php_http_zsep(1, IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));
512
513 zend_symtable_del(Z_ARRVAL_P(zparams), name_str, name_len + 1);
514 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC);
515
516 zval_ptr_dtor(&zparams);
517 }
518 }
519
520 PHP_METHOD(HttpParams, offsetSet)
521 {
522 zval *nvalue;
523 char *name_str;
524 int name_len;
525
526 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name_str, &name_len, &nvalue)) {
527 zval **zparam, *zparams = php_http_zsep(1, IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));
528
529 if (name_len) {
530 if (Z_TYPE_P(nvalue) == IS_ARRAY) {
531 zval *new_zparam;
532
533 if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(zparams), name_str, name_len + 1, (void *) &zparam)) {
534 new_zparam = php_http_zsep(1, IS_ARRAY, *zparam);
535 array_join(Z_ARRVAL_P(nvalue), Z_ARRVAL_P(new_zparam), 0, 0);
536 } else {
537 new_zparam = nvalue;
538 Z_ADDREF_P(new_zparam);
539 }
540 add_assoc_zval_ex(zparams, name_str, name_len + 1, new_zparam);
541 } else {
542 zval *tmp;
543
544 if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(zparams), name_str, name_len + 1, (void *) &zparam)) {
545 tmp = php_http_zsep(1, IS_ARRAY, *zparam);
546 } else {
547 MAKE_STD_ZVAL(tmp);
548 array_init(tmp);
549 }
550
551 Z_ADDREF_P(nvalue);
552 add_assoc_zval_ex(tmp, ZEND_STRS("value"), nvalue);
553 add_assoc_zval_ex(zparams, name_str, name_len + 1, tmp);
554 }
555 } else {
556 zval *tmp = php_http_ztyp(IS_STRING, nvalue), *arr;
557
558 MAKE_STD_ZVAL(arr);
559 array_init(arr);
560 add_assoc_bool_ex(arr, ZEND_STRS("value"), 1);
561 add_assoc_zval_ex(zparams, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp) + 1, arr);
562 zval_ptr_dtor(&tmp);
563 }
564
565 zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC);
566 zval_ptr_dtor(&zparams);
567 }
568 }
569
570 /*
571 * Local variables:
572 * tab-width: 4
573 * c-basic-offset: 4
574 * End:
575 * vim600: noet sw=4 ts=4 fdm=marker
576 * vim<600: noet sw=4 ts=4
577 */
578