X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=php_http_params.c;h=b91314df617e8766d0d772f62d45939955ec8f6a;hp=4b02e8c925874345f5b369478e69e0d6382fe0b3;hb=16bf75db1f89db511833657630cff588576088e2;hpb=3aba2100e0b6ae8f34f688825d1c00d69175dd53 diff --git a/php_http_params.c b/php_http_params.c index 4b02e8c..b91314d 100644 --- a/php_http_params.c +++ b/php_http_params.c @@ -60,7 +60,7 @@ static inline void sanitize_escaped(zval *zv TSRMLS_DC) ZVAL_STRINGL(zv, deq, deq_len, 0); } - php_stripslashes(Z_STRVAL_P(zv), &Z_STRLEN_P(zv) TSRMLS_CC); + php_stripcslashes(Z_STRVAL_P(zv), &Z_STRLEN_P(zv)); } static inline void prepare_escaped(zval *zv TSRMLS_DC) @@ -68,9 +68,10 @@ static inline void prepare_escaped(zval *zv TSRMLS_DC) if (Z_TYPE_P(zv) == IS_STRING) { int len = Z_STRLEN_P(zv); - Z_STRVAL_P(zv) = php_addslashes(Z_STRVAL_P(zv), Z_STRLEN_P(zv), &Z_STRLEN_P(zv), 1 TSRMLS_CC); + Z_STRVAL_P(zv) = php_addcslashes(Z_STRVAL_P(zv), Z_STRLEN_P(zv), &Z_STRLEN_P(zv), 1, + ZEND_STRL("\0..\37\173\\\"") TSRMLS_CC); - if (len != Z_STRLEN_P(zv)) { + if (len != Z_STRLEN_P(zv) || strpbrk(Z_STRVAL_P(zv), "()<>@,;:\"[]?={} ")) { zval tmp = *zv; int len = Z_STRLEN_P(zv) + 2; char *str = emalloc(len + 1); @@ -223,6 +224,10 @@ static inline void sanitize_key(unsigned flags, char *str, size_t len, zval *zv, if (flags & PHP_HTTP_PARAMS_ESCAPED) { sanitize_escaped(zv TSRMLS_CC); } + + if (!Z_STRLEN_P(zv)) { + return; + } eos = &Z_STRVAL_P(zv)[Z_STRLEN_P(zv)-1]; if (*eos == '*') { @@ -252,7 +257,7 @@ static inline void sanitize_rfc5987(zval *zv, char **language, zend_bool *latin1 switch (Z_STRVAL_P(zv)[0]) { case 'I': case 'i': - if (!strncasecmp(Z_STRVAL_P(zv), ZEND_STRL("iso-8859-1"))) { + if (!strncasecmp(Z_STRVAL_P(zv), "iso-8859-1", lenof("iso-8859-1"))) { *latin1 = 1; ptr = Z_STRVAL_P(zv) + lenof("iso-8859-1"); break; @@ -260,7 +265,7 @@ static inline void sanitize_rfc5987(zval *zv, char **language, zend_bool *latin1 /* no break */ case 'U': case 'u': - if (!strncasecmp(Z_STRVAL_P(zv), ZEND_STRL("utf-8"))) { + if (!strncasecmp(Z_STRVAL_P(zv), "utf-8", lenof("utf-8"))) { *latin1 = 0; ptr = Z_STRVAL_P(zv) + lenof("utf-8"); break; @@ -286,6 +291,12 @@ static inline void sanitize_rfc5987(zval *zv, char **language, zend_bool *latin1 } } +static inline void sanitize_rfc5988(char *str, size_t len, zval *zv TSRMLS_DC) +{ + zval_dtor(zv); + php_trim(str, len, " ><", 3, zv, 3 TSRMLS_CC); +} + static void utf8encode(zval *zv) { size_t pos, len = 0; @@ -342,7 +353,7 @@ static inline void sanitize_value(unsigned flags, char *str, size_t len, zval *z ZVAL_COPY_VALUE(tmp, zv); array_init(zv); add_assoc_zval(zv, language, tmp); - STR_FREE(language); + PTR_FREE(language); } } @@ -536,8 +547,12 @@ static void push_param(HashTable *params, php_http_params_state_t *state, const MAKE_STD_ZVAL(key); ZVAL_NULL(key); - sanitize_key(opts->flags, state->param.str, state->param.len, key, &rfc5987 TSRMLS_CC); - state->rfc5987 = rfc5987; + if (opts->flags & PHP_HTTP_PARAMS_RFC5988) { + sanitize_rfc5988(state->param.str, state->param.len, key TSRMLS_CC); + } else { + sanitize_key(opts->flags, state->param.str, state->param.len, key, &rfc5987 TSRMLS_CC); + state->rfc5987 = rfc5987; + } if (Z_TYPE_P(key) != IS_STRING) { merge_param(params, key, &state->current.val, &state->current.args TSRMLS_CC); } else if (Z_STRLEN_P(key)) { @@ -569,7 +584,7 @@ static void push_param(HashTable *params, php_http_params_state_t *state, const } static inline zend_bool check_str(const char *chk_str, size_t chk_len, const char *sep_str, size_t sep_len) { - return 0 < sep_len && chk_len >= sep_len && !memcmp(chk_str, sep_str, sep_len); + return 0 < sep_len && chk_len >= sep_len && *chk_str == *sep_str && !memcmp(chk_str + 1, sep_str + 1, sep_len - 1); } static size_t check_sep(php_http_params_state_t *state, php_http_params_token_t **separators) @@ -618,7 +633,13 @@ HashTable *php_http_params_parse(HashTable *params, const php_http_params_opts_t } while (state.input.len) { - if (*state.input.str == '"' && !state.escape) { + if ((opts->flags & PHP_HTTP_PARAMS_RFC5988) && !state.arg.str) { + if (*state.input.str == '<') { + state.quotes = 1; + } else if (*state.input.str == '>') { + state.quotes = 0; + } + } else if (*state.input.str == '"' && !state.escape) { state.quotes = !state.quotes; } else { state.escape = (*state.input.str == '\\'); @@ -725,6 +746,22 @@ static inline void shift_rfc5987(php_http_buffer_t *buf, zval *zvalue, const cha } } +static inline void shift_rfc5988(php_http_buffer_t *buf, char *key_str, size_t key_len, const char *ass, size_t asl, unsigned flags TSRMLS_DC) +{ + char *str; + size_t len; + + if (buf->used) { + php_http_buffer_append(buf, ass, asl); + } + + prepare_key(flags, key_str, key_len, &str, &len TSRMLS_CC); + php_http_buffer_appends(buf, "<"); + php_http_buffer_append(buf, str, len); + php_http_buffer_appends(buf, ">"); + efree(str); +} + static inline void shift_val(php_http_buffer_t *buf, zval *zvalue, const char *vss, size_t vsl, unsigned flags TSRMLS_DC) { if (Z_TYPE_P(zvalue) != IS_BOOL) { @@ -784,7 +821,11 @@ static void shift_param(php_http_buffer_t *buf, char *key_str, size_t key_len, z shift_arg(buf, key_str, key_len, zvalue, ass, asl, vss, vsl, flags TSRMLS_CC); } } else { - shift_key(buf, key_str, key_len, pss, psl, flags TSRMLS_CC); + if (flags & PHP_HTTP_PARAMS_RFC5988) { + shift_rfc5988(buf, key_str, key_len, pss, psl, flags TSRMLS_CC); + } else { + shift_key(buf, key_str, key_len, pss, psl, flags TSRMLS_CC); + } shift_val(buf, zvalue, vss, vsl, flags TSRMLS_CC); } } @@ -880,7 +921,7 @@ void php_http_params_separator_free(php_http_params_token_t **separator) php_http_params_token_t **sep = separator; if (sep) { while (*sep) { - STR_FREE((*sep)->str); + PTR_FREE((*sep)->str); efree(*sep); ++sep; } @@ -1175,6 +1216,7 @@ PHP_MINIT_FUNCTION(http_params) zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_URLENCODED"), PHP_HTTP_PARAMS_URLENCODED TSRMLS_CC); zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_DIMENSION"), PHP_HTTP_PARAMS_DIMENSION TSRMLS_CC); zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_RFC5987"), PHP_HTTP_PARAMS_RFC5987 TSRMLS_CC); + zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_RFC5988"), PHP_HTTP_PARAMS_RFC5988 TSRMLS_CC); zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_DEFAULT"), PHP_HTTP_PARAMS_DEFAULT TSRMLS_CC); zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_QUERY"), PHP_HTTP_PARAMS_QUERY TSRMLS_CC);