X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=php_http_params.c;h=4b9844820542bbe9c53f0c92f354d2ece9edca7d;hp=4b0e3f4b72cd20cc4cb6e4b99c4789becb875849;hb=2769c041b77a0aaba7acbee4ae469571eaeb2b0a;hpb=29a54250b58e444974ae19840194e214cab80bd5 diff --git a/php_http_params.c b/php_http_params.c index 4b0e3f4..4b98448 100644 --- a/php_http_params.c +++ b/php_http_params.c @@ -12,9 +12,6 @@ #include "php_http_api.h" -#include -#include - static php_http_params_token_t def_param_sep = {",", 1}, *def_param_sep_ptr[] = {&def_param_sep, NULL}; static php_http_params_token_t def_arg_sep = {";", 1}, *def_arg_sep_ptr[] = {&def_arg_sep, NULL}; static php_http_params_token_t def_val_sep = {"=", 1}, *def_val_sep_ptr[] = {&def_val_sep, NULL}; @@ -47,42 +44,62 @@ typedef struct php_http_params_state { } current; } php_http_params_state_t; +static inline void sanitize_string(char *str, size_t len, zval *zv TSRMLS_DC) +{ + /* trim whitespace */ + php_trim(str, len, NULL, 0, zv, 3 TSRMLS_CC); + + /* dequote */ + if (Z_STRVAL_P(zv)[0] == '"' && Z_STRVAL_P(zv)[Z_STRLEN_P(zv) - 1] == '"') { + size_t deq_len = Z_STRLEN_P(zv) - 2; + char *deq = estrndup(Z_STRVAL_P(zv) + 1, deq_len); + + zval_dtor(zv); + ZVAL_STRINGL(zv, deq, deq_len, 0); + } + + /* strip slashes */ + php_stripslashes(Z_STRVAL_P(zv), &Z_STRLEN_P(zv) TSRMLS_CC); +} + static void push_param(HashTable *params, php_http_params_state_t *state, const php_http_params_opts_t *opts TSRMLS_DC) { if (state->val.str) { if (0 < (state->val.len = state->input.str - state->val.str)) { - php_trim(state->val.str, state->val.len, NULL, 0, *(state->current.val), 3 TSRMLS_CC); + sanitize_string(state->val.str, state->val.len, *(state->current.val) TSRMLS_CC); } } else if (state->arg.str) { if (0 < (state->arg.len = state->input.str - state->arg.str)) { zval *val, key; INIT_PZVAL(&key); - php_trim(state->arg.str, state->arg.len, NULL, 0, &key, 3 TSRMLS_CC); - MAKE_STD_ZVAL(val); - ZVAL_TRUE(val); - zend_symtable_update(Z_ARRVAL_PP(state->current.args), Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &val, sizeof(zval *), (void *) &state->current.val); - + sanitize_string(state->arg.str, state->arg.len, &key TSRMLS_CC); + if (Z_STRLEN(key)) { + MAKE_STD_ZVAL(val); + ZVAL_TRUE(val); + zend_symtable_update(Z_ARRVAL_PP(state->current.args), Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &val, sizeof(zval *), (void *) &state->current.val); + } zval_dtor(&key); } } else if (state->param.str) { if (0 < (state->param.len = state->input.str - state->param.str)) { zval *prm, *arg, *val, key; - MAKE_STD_ZVAL(prm); - array_init(prm); - MAKE_STD_ZVAL(val); - ZVAL_TRUE(val); - zend_hash_update(Z_ARRVAL_P(prm), "value", sizeof("value"), (void *) &val, sizeof(zval *), (void *) &state->current.val); - - MAKE_STD_ZVAL(arg); - array_init(arg); - zend_hash_update(Z_ARRVAL_P(prm), "arguments", sizeof("arguments"), (void *) &arg, sizeof(zval *), (void *) &state->current.args); - INIT_PZVAL(&key); - php_trim(state->param.str, state->param.len, NULL, 0, &key, 3 TSRMLS_CC); - zend_symtable_update(params, Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &prm, sizeof(zval *), (void *) &state->current.param); - + sanitize_string(state->param.str, state->param.len, &key TSRMLS_CC); + if (Z_STRLEN(key)) { + MAKE_STD_ZVAL(prm); + array_init(prm); + MAKE_STD_ZVAL(val); + ZVAL_TRUE(val); + zend_hash_update(Z_ARRVAL_P(prm), "value", sizeof("value"), (void *) &val, sizeof(zval *), (void *) &state->current.val); + + MAKE_STD_ZVAL(arg); + array_init(arg); + zend_hash_update(Z_ARRVAL_P(prm), "arguments", sizeof("arguments"), (void *) &arg, sizeof(zval *), (void *) &state->current.args); + + zend_symtable_update(params, Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &prm, sizeof(zval *), (void *) &state->current.param); + } zval_dtor(&key); } } @@ -107,16 +124,10 @@ static size_t check_sep(php_http_params_state_t *state, php_http_params_token_t PHP_HTTP_API HashTable *php_http_params_parse(HashTable *params, const php_http_params_opts_t *opts TSRMLS_DC) { - php_http_params_state_t state = { - .input.str = opts->input.str, - .input.len = opts->input.len, - .param.str = NULL, - .param.len = 0, - .arg.str = NULL, - .arg.len = 0, - .val.str = NULL, - .val.len = 0 - }; + php_http_params_state_t state = {{NULL,0}, {NULL,0}, {NULL,0}, {NULL,0}, {NULL,NULL,NULL}}; + + state.input.str = opts->input.str; + state.input.len = opts->input.len; if (!params) { ALLOC_HASHTABLE(params); @@ -172,6 +183,104 @@ PHP_HTTP_API HashTable *php_http_params_parse(HashTable *params, const php_http_ return params; } +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) +{ + zval **zparam; + HashPosition pos1, pos2; + php_http_array_hashkey_t key1 = php_http_array_hashkey_init(0), key2 = php_http_array_hashkey_init(0); + + if (!buf) { + buf = php_http_buffer_init(NULL); + } + + FOREACH_HASH_KEYVAL(pos1, params, key1, zparam) { + /* new param ? */ + if (PHP_HTTP_BUFFER_LEN(buf)) { + php_http_buffer_append(buf, pss, psl); + } + + /* add name */ + if (key1.type == HASH_KEY_IS_STRING) { + php_http_buffer_append(buf, key1.str, key1.len - 1); + } else { + php_http_buffer_appendf(buf, "%lu", key1.num); + } + + if (Z_TYPE_PP(zparam) != IS_ARRAY) { + zval *tmp = php_http_ztyp(IS_STRING, *zparam); + + php_http_buffer_append(buf, vss, vsl); + php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); + zval_ptr_dtor(&tmp); + } else { + zval **zvalue, **zargs, **zarg; + + /* got a value? */ + if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("value"), (void *) &zvalue)) { + if (Z_TYPE_PP(zvalue) != IS_BOOL) { + zval *tmp = php_http_ztyp(IS_STRING, *zvalue); + + php_http_buffer_append(buf, vss, vsl); + php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); + zval_ptr_dtor(&tmp); + } else if (!Z_BVAL_PP(zvalue)) { + php_http_buffer_append(buf, vss, vsl); + php_http_buffer_appends(buf, "0"); + } + } + /* add arguments */ + if (SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("arguments"), (void *) &zargs)) { + zargs = zparam; + } + + if (Z_TYPE_PP(zargs) == IS_ARRAY) { + FOREACH_KEYVAL(pos2, *zargs, key2, zarg) { + /* skip "value" if zargs == zparam */ + if (zargs == zparam && key2.type == HASH_KEY_IS_STRING && !strcmp(key2.str, "value")) { + continue; + } + + /* new arg? */ + if (PHP_HTTP_BUFFER_LEN(buf)) { + php_http_buffer_append(buf, ass, asl); + } + + /* add name */ + if (key2.type == HASH_KEY_IS_STRING) { + php_http_buffer_append(buf, key2.str, key2.len - 1); + } else { + php_http_buffer_appendf(buf, "%lu", key2.num); + } + /* add value */ + if (Z_TYPE_PP(zarg) != IS_BOOL) { + zval *tmp = php_http_ztyp(IS_STRING, *zarg); + int escaped_len; + + Z_STRVAL_P(tmp) = php_addslashes(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), &escaped_len, 1 TSRMLS_CC); + php_http_buffer_append(buf, vss, vsl); + if (escaped_len != Z_STRLEN_P(tmp)) { + php_http_buffer_appends(buf, "\""); + php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp) = escaped_len); + php_http_buffer_appends(buf, "\""); + } else { + php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); + } + zval_ptr_dtor(&tmp); + } else if (!Z_BVAL_PP(zarg)) { + php_http_buffer_append(buf, vss, vsl); + php_http_buffer_appends(buf, "0"); + } + } + } + } + } + + php_http_buffer_shrink(buf); + php_http_buffer_fix(buf); + + return buf; +} + #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpParams, method, 0, req_args) #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpParams, method, 0) #define PHP_HTTP_PARAMS_ME(method, visibility) PHP_ME(HttpParams, method, PHP_HTTP_ARGS(HttpParams, method), visibility) @@ -179,7 +288,9 @@ PHP_HTTP_API HashTable *php_http_params_parse(HashTable *params, const php_http_ PHP_HTTP_BEGIN_ARGS(__construct, 0) PHP_HTTP_ARG_VAL(params, 0) - PHP_HTTP_ARG_VAL(flags, 0) + PHP_HTTP_ARG_VAL(param_sep, 0) + PHP_HTTP_ARG_VAL(arg_sep, 0) + PHP_HTTP_ARG_VAL(val_sep, 0) PHP_HTTP_END_ARGS; PHP_HTTP_EMPTY_ARGS(toArray); @@ -287,11 +398,14 @@ PHP_METHOD(HttpParams, __construct) if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/z/z/z/", &zparams, ¶m_sep, &arg_sep, &val_sep)) { switch (ZEND_NUM_ARGS()) { case 4: - zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), param_sep TSRMLS_CC); + zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), val_sep TSRMLS_CC); + /* no break */ case 3: zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), arg_sep TSRMLS_CC); + /* no break */ case 2: - zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), val_sep TSRMLS_CC); + zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), param_sep TSRMLS_CC); + /* no break */ } if (zparams) { @@ -306,8 +420,10 @@ PHP_METHOD(HttpParams, __construct) zcopy = php_http_ztyp(IS_STRING, zparams); if (Z_STRLEN_P(zcopy)) { php_http_params_opts_t opts = { - .input.str = Z_STRVAL_P(zcopy), - .input.len = Z_STRLEN_P(zcopy), + .input = { + .str = Z_STRVAL_P(zcopy), + .len = Z_STRLEN_P(zcopy) + }, .param = parse_sep(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC) TSRMLS_CC), .arg = parse_sep(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC) TSRMLS_CC), .val = parse_sep(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC) TSRMLS_CC) @@ -347,82 +463,21 @@ PHP_METHOD(HttpParams, toArray) PHP_METHOD(HttpParams, toString) { zval *zparams, *zpsep, *zasep, *zvsep; - zval **zparam, **zvalue, **zargs, **zarg; - HashPosition pos1, pos2; - php_http_array_hashkey_t key1 = php_http_array_hashkey_init(0), key2 = php_http_array_hashkey_init(0); php_http_buffer_t buf; zparams = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC)); zpsep = php_http_ztyp(IS_STRING, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC)); zasep = php_http_ztyp(IS_STRING, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC)); zvsep = php_http_ztyp(IS_STRING, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC)); - php_http_buffer_init(&buf); - - FOREACH_KEYVAL(pos1, zparams, key1, zparam) { - /* new param ? */ - if (PHP_HTTP_BUFFER_LEN(&buf)) { - php_http_buffer_append(&buf, Z_STRVAL_P(zpsep), Z_STRLEN_P(zpsep)); - } - - /* add name */ - if (key1.type == HASH_KEY_IS_STRING) { - php_http_buffer_append(&buf, key1.str, key1.len - 1); - } else { - php_http_buffer_appendf(&buf, "%lu", key1.num); - } - - if (Z_TYPE_PP(zparam) == IS_ARRAY) { - /* got a value? */ - if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("value"), (void *) &zvalue)) { - if (Z_TYPE_PP(zvalue) != IS_BOOL) { - zval *tmp = php_http_ztyp(IS_STRING, *zvalue); - - php_http_buffer_append(&buf, Z_STRVAL_P(zvsep), Z_STRLEN_P(zvsep)); - php_http_buffer_append(&buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); - zval_ptr_dtor(&tmp); - } else if (!Z_BVAL_PP(zvalue)) { - php_http_buffer_append(&buf, Z_STRVAL_P(zvsep), Z_STRLEN_P(zvsep)); - php_http_buffer_appends(&buf, "0"); - } - } - /* add arguments */ - if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("arguments"), (void *) &zargs)) { - if (Z_TYPE_PP(zargs) == IS_ARRAY) { - FOREACH_KEYVAL(pos2, *zargs, key2, zarg) { - /* new arg? */ - if (PHP_HTTP_BUFFER_LEN(&buf)) { - php_http_buffer_append(&buf, Z_STRVAL_P(zasep), Z_STRLEN_P(zasep)); - } - /* add name */ - if (key2.type == HASH_KEY_IS_STRING) { - php_http_buffer_append(&buf, key2.str, key2.len - 1); - } else { - php_http_buffer_appendf(&buf, "%lu", key2.num); - } - /* add value */ - if (Z_TYPE_PP(zarg) != IS_BOOL) { - zval *tmp = php_http_ztyp(IS_STRING, *zarg); - - php_http_buffer_append(&buf, Z_STRVAL_P(zvsep), Z_STRLEN_P(zvsep)); - php_http_buffer_append(&buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); - zval_ptr_dtor(&tmp); - } else if (!Z_BVAL_PP(zarg)) { - php_http_buffer_append(&buf, Z_STRVAL_P(zvsep), Z_STRLEN_P(zvsep)); - php_http_buffer_appends(&buf, "0"); - } - } - } - } - } - } + php_http_buffer_init(&buf); + 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); zval_ptr_dtor(&zparams); zval_ptr_dtor(&zpsep); zval_ptr_dtor(&zasep); zval_ptr_dtor(&zvsep); - php_http_buffer_shrink(&buf); RETVAL_PHP_HTTP_BUFFER_VAL(&buf); }