prepare v4.2.5
[m6w6/ext-http] / src / php_http_params.c
index 8db5c353bd18c004ecc8bef617431577fafcb526..f40b89f9c0fddbdbd06f72a69d54f8fd8aa9249c 100644 (file)
@@ -20,7 +20,7 @@ static php_http_params_opts_t def_opts = {
        def_param_sep_ptr,
        def_arg_sep_ptr,
        def_val_sep_ptr,
-       {{0}},
+       {{0}, {0}, {0}},
        PHP_HTTP_PARAMS_DEFAULT
 };
 
@@ -63,24 +63,30 @@ static inline void sanitize_escaped(zval *zv)
        php_stripcslashes(Z_STR_P(zv));
 }
 
-static inline void quote_string(zend_string **zs, zend_bool force)
+static inline zend_string *quote_string(zend_string *zs, zend_bool force)
 {
-       int len = (*zs)->len;
+       size_t len = (zs)->len;
 
-       *zs = php_addcslashes(*zs, 1, ZEND_STRL("\0..\37\173\\\""));
+#if PHP_VERSION_ID < 70300
+       zs = php_addcslashes(zs, 0, ZEND_STRL("\0..\37\173\\\""));
+#else
+       zs = php_addcslashes(zs, ZEND_STRL("\0..\37\173\\\""));
+#endif
 
-       if (force || len != (*zs)->len || strpbrk((*zs)->val, "()<>@,;:\"[]?={} ")) {
-               int len = (*zs)->len + 2;
+       if (force || len != (zs)->len || strpbrk((zs)->val, "()<>@,;:\"[]?={} ")) {
+               int len = (zs)->len + 2;
 
-               *zs = zend_string_extend(*zs, len, 0);
+               zs = zend_string_extend(zs, len, 0);
 
-               memmove(&(*zs)->val[1], (*zs)->val, (*zs)->len);
-               (*zs)->val[0] = '"';
-               (*zs)->val[len-1] = '"';
-               (*zs)->val[len] = '\0';
+               memmove(&(zs)->val[1], (zs)->val, (zs)->len);
+               (zs)->val[0] = '"';
+               (zs)->val[len-1] = '"';
+               (zs)->val[len] = '\0';
 
-               zend_string_forget_hash_val(*zs);
+               zend_string_forget_hash_val(zs);
        }
+
+       return zs;
 }
 
 /*     if (Z_TYPE_P(zv) == IS_STRING) {
@@ -109,7 +115,10 @@ static inline void quote_string(zend_string **zs, zend_bool force)
 static inline void prepare_escaped(zval *zv)
 {
        if (Z_TYPE_P(zv) == IS_STRING) {
-               quote_string(&Z_STR_P(zv), 0);
+               zend_string *str = quote_string(Z_STR_P(zv), 0);
+
+               zval_dtor(zv);
+               ZVAL_STR(zv, str);
        } else {
                zval_dtor(zv);
                ZVAL_EMPTY_STRING(zv);
@@ -118,7 +127,7 @@ static inline void prepare_escaped(zval *zv)
 
 static inline void sanitize_urlencoded(zval *zv)
 {
-       Z_STRLEN_P(zv) = php_raw_url_decode(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
+       Z_STRLEN_P(zv) = php_url_decode(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
 }
 
 static inline void prepare_urlencoded(zval *zv)
@@ -131,12 +140,11 @@ static inline void prepare_urlencoded(zval *zv)
 
 static void sanitize_dimension(zval *zv)
 {
-       zval arr, tmp, *cur = NULL;
+       zval arr, tmp, *cur = &arr;
        char *var = NULL, *ptr = Z_STRVAL_P(zv), *end = Z_STRVAL_P(zv) + Z_STRLEN_P(zv);
        long level = 0;
 
        array_init(&arr);
-       cur = &arr;
 
        while (ptr < end) {
                if (!var) {
@@ -195,8 +203,8 @@ static void prepare_dimension(php_http_buffer_t *buf, php_http_buffer_t *keybuf,
        zval *val;
        php_http_buffer_t prefix;
 
-       if (!ZEND_HASH_GET_APPLY_COUNT(ht)) {
-               ZEND_HASH_INC_APPLY_COUNT(ht);
+       if (!HT_IS_RECURSIVE(ht)) {
+               HT_PROTECT_RECURSION(ht);
                php_http_buffer_init(&prefix);
                php_http_buffer_append(&prefix, keybuf->data, keybuf->used);
 
@@ -230,7 +238,7 @@ static void prepare_dimension(php_http_buffer_t *buf, php_http_buffer_t *keybuf,
                        php_http_buffer_cut(&prefix, keybuf->used, prefix.used - keybuf->used);
                }
                ZEND_HASH_FOREACH_END();
-               ZEND_HASH_DEC_APPLY_COUNT(ht);
+               HT_UNPROTECT_RECURSION(ht);
 
                php_http_buffer_dtor(&prefix);
        }
@@ -248,16 +256,18 @@ static inline void sanitize_key(unsigned flags, const char *str, size_t len, zva
        if (flags & PHP_HTTP_PARAMS_ESCAPED) {
                sanitize_escaped(zv);
        }
-       
+
        if (!Z_STRLEN_P(zv)) {
                return;
        }
 
-       eos = &Z_STRVAL_P(zv)[Z_STRLEN_P(zv)-1];
-       if (*eos == '*') {
-               *eos = '\0';
-               *rfc5987 = 1;
-               Z_STRLEN_P(zv) -= 1;
+       if (flags & PHP_HTTP_PARAMS_RFC5987) {
+               eos = &Z_STRVAL_P(zv)[Z_STRLEN_P(zv)-1];
+               if (*eos == '*') {
+                       *eos = '\0';
+                       *rfc5987 = 1;
+                       Z_STRLEN_P(zv) -= 1;
+               }
        }
 
        if (flags & PHP_HTTP_PARAMS_URLENCODED) {
@@ -487,7 +497,7 @@ static void merge_param(HashTable *params, zval *zdata, zval **current_param, zv
                        zval *test_ptr;
 
                        while (Z_TYPE_P(zdata_ptr) == IS_ARRAY && (test_ptr = zend_hash_get_current_data(Z_ARRVAL_P(zdata_ptr)))) {
-                               if (Z_TYPE_P(test_ptr) == IS_ARRAY) {
+                               if (Z_TYPE_P(test_ptr) == IS_ARRAY && Z_TYPE_P(ptr) == IS_ARRAY) {
                                        zval *tmp_ptr = ptr;
 
                                        /* now find key in ptr */
@@ -552,8 +562,12 @@ static void merge_param(HashTable *params, zval *zdata, zval **current_param, zv
 static void push_param(HashTable *params, php_http_params_state_t *state, const php_http_params_opts_t *opts)
 {
        if (state->val.str) {
-               if (0 < (state->val.len = state->input.str - state->val.str)) {
+               if (!state->current.val) {
+                       return;
+               } else if (0 < (state->val.len = state->input.str - state->val.str)) {
                        sanitize_value(opts->flags, state->val.str, state->val.len, state->current.val, state->rfc5987);
+               } else {
+                       ZVAL_EMPTY_STRING(state->current.val);
                }
                state->rfc5987 = 0;
        } else if (state->arg.str) {
@@ -635,7 +649,7 @@ static size_t check_sep(php_http_params_state_t *state, php_http_params_token_t
        if (state->quotes || state->escape) {
                return 0;
        }
-       
+
        if (sep) while (*sep) {
                if (check_str(state->input.str, state->input.len, (*sep)->str, (*sep)->len)) {
                        return (*sep)->len;
@@ -663,8 +677,9 @@ static void skip_sep(size_t skip, php_http_params_state_t *state, php_http_param
 
 HashTable *php_http_params_parse(HashTable *params, const php_http_params_opts_t *opts)
 {
-       php_http_params_state_t state = {{NULL,0}, {NULL,0}, {NULL,0}, {NULL,0}, {NULL,NULL,NULL}, 0, 0};
+       php_http_params_state_t state;
 
+       memset(&state, 0, sizeof(state));
        state.input.str = opts->input.str;
        state.input.len = opts->input.len;
 
@@ -685,7 +700,7 @@ HashTable *php_http_params_parse(HashTable *params, const php_http_params_opts_t
                } else {
                        state.escape = (*state.input.str == '\\');
                }
-               
+
                if (!state.param.str) {
                        /* initialize */
                        skip_sep(0, &state, opts->param, opts->arg, opts->val);
@@ -739,7 +754,7 @@ HashTable *php_http_params_parse(HashTable *params, const php_http_params_opts_t
                                }
                        }
                }
-               
+
                if (state.input.len) {
                        ++state.input.str;
                        --state.input.len;
@@ -810,13 +825,14 @@ static inline void shift_rfc5988(php_http_buffer_t *buf, char *key_str, size_t k
 
 static inline void shift_rfc5988_val(php_http_buffer_t *buf, zval *zv, const char *vss, size_t vsl, unsigned flags)
 {
-       zend_string *zs = zval_get_string(zv);
-
-       quote_string(&zs, 1);
-       php_http_buffer_append(buf, vss, vsl);
-       php_http_buffer_append(buf, zs->val, zs->len);
+       zend_string *str, *zs = zval_get_string(zv);
 
+       str = quote_string(zs, 1);
        zend_string_release(zs);
+
+       php_http_buffer_append(buf, vss, vsl);
+       php_http_buffer_append(buf, str->val, str->len);
+       zend_string_release(str);
 }
 
 static inline void shift_val(php_http_buffer_t *buf, zval *zvalue, const char *vss, size_t vsl, unsigned flags)
@@ -1053,16 +1069,16 @@ PHP_METHOD(HttpParams, __construct)
        {
                switch (ZEND_NUM_ARGS()) {
                        case 5:
-                               zend_update_property_long(php_http_params_class_entry, getThis(), ZEND_STRL("flags"), flags);
+                               zend_update_property_long(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("flags"), flags);
                                /* no break */
                        case 4:
-                               zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), val_sep);
+                               zend_update_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("val_sep"), val_sep);
                                /* no break */
                        case 3:
-                               zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), arg_sep);
+                               zend_update_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("arg_sep"), arg_sep);
                                /* no break */
                        case 2:
-                               zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), param_sep);
+                               zend_update_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("param_sep"), param_sep);
                                /* no break */
                }
 
@@ -1071,7 +1087,7 @@ PHP_METHOD(HttpParams, __construct)
                                case IS_OBJECT:
                                case IS_ARRAY:
                                        convert_to_array(zparams);
-                                       zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zparams);
+                                       zend_update_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("params"), zparams);
                                        break;
                                default:
                                        zs = zval_get_string(zparams);
@@ -1080,15 +1096,15 @@ PHP_METHOD(HttpParams, __construct)
 
                                                php_http_params_opts_t opts = {
                                                        {zs->val, zs->len},
-                                                       php_http_params_separator_init(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0, &tmp)),
-                                                       php_http_params_separator_init(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0, &tmp)),
-                                                       php_http_params_separator_init(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0, &tmp)),
-                                                       {{0}}, flags
+                                                       php_http_params_separator_init(zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("param_sep"), 0, &tmp)),
+                                                       php_http_params_separator_init(zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("arg_sep"), 0, &tmp)),
+                                                       php_http_params_separator_init(zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("val_sep"), 0, &tmp)),
+                                                       {{0}, {0}, {0}}, flags
                                                };
 
                                                array_init(&tmp);
                                                php_http_params_parse(Z_ARRVAL(tmp), &opts);
-                                               zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), &tmp);
+                                               zend_update_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("params"), &tmp);
                                                zval_ptr_dtor(&tmp);
 
                                                php_http_params_separator_free(opts.param);
@@ -1102,7 +1118,7 @@ PHP_METHOD(HttpParams, __construct)
                        zval tmp;
 
                        array_init(&tmp);
-                       zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), &tmp);
+                       zend_update_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("params"), &tmp);
                        zval_ptr_dtor(&tmp);
                }
        }
@@ -1118,7 +1134,7 @@ PHP_METHOD(HttpParams, toArray)
        if (SUCCESS != zend_parse_parameters_none()) {
                return;
        }
-       zparams = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0, &zparams_tmp);
+       zparams = zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("params"), 0, &zparams_tmp);
        RETURN_ZVAL(zparams, 1, 0);
 }
 
@@ -1132,23 +1148,23 @@ PHP_METHOD(HttpParams, toString)
        long flags;
        php_http_buffer_t buf;
 
-       zparams = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0, &zparams_tmp);
+       zparams = zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("params"), 0, &zparams_tmp);
        convert_to_array_ex(zparams);
-       flags = zval_get_long(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("flags"), 0, &flags_tmp));
+       flags = zval_get_long(zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("flags"), 0, &flags_tmp));
 
-       zpsep = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0, &psep_tmp);
+       zpsep = zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("param_sep"), 0, &psep_tmp);
        if (Z_TYPE_P(zpsep) == IS_ARRAY && (tmp = zend_hash_get_current_data(Z_ARRVAL_P(zpsep)))) {
                psep = zval_get_string(tmp);
        } else {
                psep = zval_get_string(zpsep);
        }
-       zasep = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0, &asep_tmp);
+       zasep = zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("arg_sep"), 0, &asep_tmp);
        if (Z_TYPE_P(zasep) == IS_ARRAY && (tmp = zend_hash_get_current_data(Z_ARRVAL_P(zasep)))) {
                asep = zval_get_string(tmp);
        } else {
                asep = zval_get_string(zasep);
        }
-       zvsep = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0, &vsep_tmp);
+       zvsep = zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("val_sep"), 0, &vsep_tmp);
        if (Z_TYPE_P(zvsep) == IS_ARRAY && (tmp = zend_hash_get_current_data(Z_ARRVAL_P(zvsep)))) {
                vsep = zval_get_string(tmp);
        } else {
@@ -1165,7 +1181,7 @@ PHP_METHOD(HttpParams, toString)
        RETVAL_STR(php_http_cs2zs(buf.data, buf.used));
 }
 
-ZEND_BEGIN_ARG_INFO_EX(ai_HttpParams_offsetExists, 0, 0, 1)
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_HttpParams_offsetExists, 0, 1, _IS_BOOL, 0)
        ZEND_ARG_INFO(0, name)
 ZEND_END_ARG_INFO();
 PHP_METHOD(HttpParams, offsetExists)
@@ -1177,7 +1193,7 @@ PHP_METHOD(HttpParams, offsetExists)
                return;
        }
 
-       zparams = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0, &zparams_tmp);
+       zparams = zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("params"), 0, &zparams_tmp);
 
        if (Z_TYPE_P(zparams) == IS_ARRAY && (zparam = zend_symtable_find(Z_ARRVAL_P(zparams), name))) {
                RETVAL_BOOL(Z_TYPE_P(zparam) != IS_NULL);
@@ -1186,7 +1202,7 @@ PHP_METHOD(HttpParams, offsetExists)
        }
 }
 
-ZEND_BEGIN_ARG_INFO_EX(ai_HttpParams_offsetGet, 0, 0, 1)
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_HttpParams_offsetGet, 0, 1, IS_MIXED, 1)
        ZEND_ARG_INFO(0, name)
 ZEND_END_ARG_INFO();
 PHP_METHOD(HttpParams, offsetGet)
@@ -1198,14 +1214,14 @@ PHP_METHOD(HttpParams, offsetGet)
                return;
        }
 
-       zparams = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0, &zparams_tmp);
+       zparams = zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("params"), 0, &zparams_tmp);
 
        if (Z_TYPE_P(zparams) == IS_ARRAY && (zparam = zend_symtable_find(Z_ARRVAL_P(zparams), name))) {
                RETVAL_ZVAL(zparam, 1, 0);
        }
 }
 
-ZEND_BEGIN_ARG_INFO_EX(ai_HttpParams_offsetUnset, 0, 0, 1)
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_HttpParams_offsetUnset, 0, 1, IS_VOID, 0)
        ZEND_ARG_INFO(0, name)
 ZEND_END_ARG_INFO();
 PHP_METHOD(HttpParams, offsetUnset)
@@ -1217,14 +1233,14 @@ PHP_METHOD(HttpParams, offsetUnset)
                return;
        }
 
-       zparams = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0, &zparams_tmp);
+       zparams = zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("params"), 0, &zparams_tmp);
 
        if (Z_TYPE_P(zparams) == IS_ARRAY) {
                zend_symtable_del(Z_ARRVAL_P(zparams), name);
        }
 }
 
-ZEND_BEGIN_ARG_INFO_EX(ai_HttpParams_offsetSet, 0, 0, 2)
+ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(ai_HttpParams_offsetSet, 0, 2, IS_VOID, 0)
        ZEND_ARG_INFO(0, name)
        ZEND_ARG_INFO(0, value)
 ZEND_END_ARG_INFO();
@@ -1233,14 +1249,14 @@ PHP_METHOD(HttpParams, offsetSet)
        zend_string *name;
        zval zparams_tmp, *zparam, *zparams, *nvalue;
 
-       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &name, &nvalue)) {
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "S!z", &name, &nvalue)) {
                return;
        }
 
-       zparams = zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0, &zparams_tmp);
+       zparams = zend_read_property(php_http_params_class_entry, Z_OBJ_P(ZEND_THIS), ZEND_STRL("params"), 0, &zparams_tmp);
        convert_to_array(zparams);
 
-       if (name->len) {
+       if (name && name->len) {
                if (Z_TYPE_P(nvalue) == IS_ARRAY) {
                        if ((zparam = zend_symtable_find(Z_ARRVAL_P(zparams), name))) {
                                convert_to_array(zparam);
@@ -1274,12 +1290,15 @@ PHP_METHOD(HttpParams, offsetSet)
        }
 }
 
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(ai_HttpParams___toString, 0, 0, IS_STRING, 0)
+ZEND_END_ARG_INFO();
+
 static zend_function_entry php_http_params_methods[] = {
-       PHP_ME(HttpParams, __construct,   ai_HttpParams___construct,   ZEND_ACC_PUBLIC|ZEND_ACC_CTOR|ZEND_ACC_FINAL)
+       PHP_ME(HttpParams, __construct,   ai_HttpParams___construct,   ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
 
        PHP_ME(HttpParams, toArray,       ai_HttpParams_toArray,       ZEND_ACC_PUBLIC)
        PHP_ME(HttpParams, toString,      ai_HttpParams_toString,      ZEND_ACC_PUBLIC)
-       ZEND_MALIAS(HttpParams, __toString, toString, ai_HttpParams_toString, ZEND_ACC_PUBLIC)
+       ZEND_MALIAS(HttpParams, __toString, toString, ai_HttpParams___toString, ZEND_ACC_PUBLIC)
 
        PHP_ME(HttpParams, offsetExists,  ai_HttpParams_offsetExists,  ZEND_ACC_PUBLIC)
        PHP_ME(HttpParams, offsetUnset,   ai_HttpParams_offsetUnset,   ZEND_ACC_PUBLIC)
@@ -1329,4 +1348,3 @@ PHP_MINIT_FUNCTION(http_params)
  * vim600: noet sw=4 ts=4 fdm=marker
  * vim<600: noet sw=4 ts=4
  */
-