From 4fa594d2099832b6d1eea0c01cdee3b44109577f Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 12 Apr 2012 14:07:09 +0000 Subject: [PATCH] fiy a serialization issue; always add "arguments" key to params array; add tests --- php_http_params.c | 32 +++++++++++++++++---------- phpunit/ParamsTest.php | 49 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/php_http_params.c b/php_http_params.c index 9db11c2..76313a0 100644 --- a/php_http_params.c +++ b/php_http_params.c @@ -244,7 +244,7 @@ static void prepare_value(unsigned flags, zval *zv TSRMLS_DC) } } -static void merge_param(HashTable *params, zval *zdata, zval ***cur TSRMLS_DC) +static void merge_param(HashTable *params, zval *zdata, zval ***current_param, zval ***current_args TSRMLS_DC) { zval **ptr, **zdata_ptr; php_http_array_hashkey_t hkey = php_http_array_hashkey_init(0); @@ -264,7 +264,7 @@ static void merge_param(HashTable *params, zval *zdata, zval ***cur TSRMLS_DC) if ((hkey.type == HASH_KEY_IS_STRING && !zend_hash_exists(params, hkey.str, hkey.len)) || (hkey.type == HASH_KEY_IS_LONG && !zend_hash_index_exists(params, hkey.num)) ) { - zval *tmp; + zval *tmp, *arg, **args; /* create the entry if it doesn't exist */ zend_hash_get_current_data(Z_ARRVAL_P(zdata), (void *) &ptr); @@ -273,6 +273,11 @@ static void merge_param(HashTable *params, zval *zdata, zval ***cur TSRMLS_DC) array_init(tmp); add_assoc_zval_ex(tmp, ZEND_STRS("value"), *ptr); + MAKE_STD_ZVAL(arg); + array_init(arg); + zend_hash_update(Z_ARRVAL_P(tmp), "arguments", sizeof("arguments"), (void *) &arg, sizeof(zval *), (void *) &args); + *current_args = args; + if (hkey.type == HASH_KEY_IS_STRING) { zend_hash_update(params, hkey.str, hkey.len, (void *) &tmp, sizeof(zval *), (void *) &ptr); } else { @@ -350,7 +355,7 @@ static void merge_param(HashTable *params, zval *zdata, zval ***cur TSRMLS_DC) /* bubble up */ while (Z_TYPE_PP(ptr) == IS_ARRAY && SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(ptr), (void *) &ptr)); - *cur = ptr; + *current_param = ptr; } static void push_param(HashTable *params, php_http_params_state_t *state, const php_http_params_opts_t *opts TSRMLS_DC) @@ -380,7 +385,7 @@ static void push_param(HashTable *params, php_http_params_state_t *state, const ZVAL_NULL(key); sanitize_key(opts->flags, state->param.str, state->param.len, key TSRMLS_CC); if (Z_TYPE_P(key) != IS_STRING) { - merge_param(params, key, &state->current.val TSRMLS_CC); + merge_param(params, key, &state->current.val, &state->current.args TSRMLS_CC); } else if (Z_STRLEN_P(key)) { MAKE_STD_ZVAL(prm); array_init(prm); @@ -609,17 +614,22 @@ PHP_HTTP_API php_http_buffer_t *php_http_params_to_string(php_http_buffer_t *buf php_http_array_hashkey_stringfree(&key); if (Z_TYPE_PP(zparam) == IS_ARRAY && SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("arguments"), (void *) &zvalue)) { + if (zvalue == zparam) { + continue; + } zvalue = zparam; } - FOREACH_KEYVAL(pos1, *zvalue, key1, zargs) { - if (zvalue == zparam && key1.type == HASH_KEY_IS_STRING && !strcmp(key1.str, "value")) { - continue; - } + if (Z_TYPE_PP(zvalue) == IS_ARRAY) { + FOREACH_KEYVAL(pos1, *zvalue, key1, zargs) { + if (zvalue == zparam && key1.type == HASH_KEY_IS_STRING && !strcmp(key1.str, "value")) { + continue; + } - php_http_array_hashkey_stringify(&key1); - shift_param(buf, key1.str, key1.len - 1, zargs, ass, asl, vss, vsl, flags TSRMLS_CC); - php_http_array_hashkey_stringfree(&key1); + php_http_array_hashkey_stringify(&key1); + shift_param(buf, key1.str, key1.len - 1, zargs, ass, asl, vss, vsl, flags TSRMLS_CC); + php_http_array_hashkey_stringfree(&key1); + } } } diff --git a/phpunit/ParamsTest.php b/phpunit/ParamsTest.php index a06d72e..71bfcf4 100644 --- a/phpunit/ParamsTest.php +++ b/phpunit/ParamsTest.php @@ -50,6 +50,55 @@ class ParamsTest extends PHPUnit_Framework_TestCase { $this->assertEquals("form-data;name=upload;filename=\"trick\\\"\\0\\\"ed\"", (string) $p); } + function testUrlencoded() { + $s = "foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1"; + $p = new http\Params($s, "&", "", "=", http\Params::PARSE_URLENCODED); + $this->assertEquals( + array( + "foo" => array( + "value" => "b\"r", + "arguments" => array(), + ), + "bar" => array( + "value" => "b\"z", + "arguments" => array(), + ), + "a[][]" => array( + "value" => "1", + "arguments" => array(), + ), + ), + $p->params + ); + $this->assertEquals("foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1", (string) $p); + } + + function testQuery() { + $s = "foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1"; + $p = new http\Params($s, "&", "", "=", http\Params::PARSE_QUERY); + $this->assertEquals( + array( + "foo" => array( + "value" => "b\"r", + "arguments" => array(), + ), + "bar" => array( + "value" => "b\"z", + "arguments" => array(), + ), + "a" => array( + "value" => array( + array("1") + ), + "arguments" => array(), + ), + ), + $p->params + ); + $this->assertEquals("foo=b%22r&bar=b%22z&a%5B0%5D%5B0%5D=1", (string) $p); + } + + function testEmpty() { $p = new http\Params(NULL); $this->assertEquals(array(), $p->params); -- 2.30.2