From 0fba8595e6e2de88cad39460340d620a089c55ed Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 1 Nov 2005 11:08:58 +0000 Subject: [PATCH] - own, simpler hash urlencoder --- LICENSE | 60 ------------- http_functions.c | 10 +-- http_url_api.c | 213 ++++++++++++++------------------------------ php_http_std_defs.h | 9 +- php_http_url_api.h | 13 +-- 5 files changed, 81 insertions(+), 224 deletions(-) diff --git a/LICENSE b/LICENSE index c274794..a54036e 100644 --- a/LICENSE +++ b/LICENSE @@ -44,63 +44,3 @@ OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. - -=============================================================================== - -The hash urlencoder in file http_url_api.c is derived from the implementation -found in the original PHP source, licensed under the following conditions: - -Copyright (c) 1999 - 2005 The PHP Group. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, is permitted provided that the following conditions -are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - 3. The name "PHP" must not be used to endorse or promote products - derived from this software without prior written permission. For - written permission, please contact group@php.net. - - 4. Products derived from this software may not be called "PHP", nor - may "PHP" appear in their name, without prior written permission - from group@php.net. You may indicate that your software works in - conjunction with PHP by saying "Foo for PHP" instead of calling - it "PHP Foo" or "phpfoo" - - 5. The PHP Group may publish revised and/or new versions of the - license from time to time. Each version will be given a - distinguishing version number. - Once covered code has been published under a particular version - of the license, you may always continue to use it under the terms - of that version. You may also choose to use such covered code - under the terms of any subsequent version of the license - published by the PHP Group. No one other than the PHP Group has - the right to modify the terms applicable to covered code created - under this License. - - 6. Redistributions of any form whatsoever must retain the following - acknowledgment: - "This product includes PHP, freely available from - ". - -THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND -ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP -DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/http_functions.c b/http_functions.c index 5ff5e33..7d82438 100644 --- a/http_functions.c +++ b/http_functions.c @@ -1381,21 +1381,17 @@ PHP_FUNCTION(http_build_query) int prefix_len = 0, arg_sep_len = strlen(arg_sep); phpstr *formstr; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ss", &formdata, &prefix, &prefix_len, &arg_sep, &arg_sep_len) != SUCCESS) { - RETURN_FALSE; - } - - if (Z_TYPE_P(formdata) != IS_ARRAY && Z_TYPE_P(formdata) != IS_OBJECT) { - http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Parameter 1 expected to be Array or Object. Incorrect value given."); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ss", &formdata, &prefix, &prefix_len, &arg_sep, &arg_sep_len) != SUCCESS) { RETURN_FALSE; } if (!arg_sep_len) { arg_sep = HTTP_URL_ARGSEP; + arg_sep_len = lenof(HTTP_URL_ARGSEP); } formstr = phpstr_new(); - if (SUCCESS != http_urlencode_hash_implementation_ex(HASH_OF(formdata), formstr, arg_sep, prefix, prefix_len, NULL, 0, NULL, 0, (Z_TYPE_P(formdata) == IS_OBJECT ? formdata : NULL))) { + if (SUCCESS != http_urlencode_hash_recursive(HASH_OF(formdata), formstr, arg_sep, prefix, prefix_len)) { phpstr_free(&formstr); RETURN_FALSE; } diff --git a/http_url_api.c b/http_url_api.c index 2cde7bc..aa0c1f3 100644 --- a/http_url_api.c +++ b/http_url_api.c @@ -183,17 +183,19 @@ PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_ char **encoded_data, size_t *encoded_len TSRMLS_DC) { char *arg_sep; + size_t arg_sep_len; phpstr *qstr = phpstr_new(); - if (override_argsep || !strlen(arg_sep = INI_STR("arg_separator.output"))) { + if (override_argsep || !(arg_sep_len = strlen(arg_sep = INI_STR("arg_separator.output")))) { arg_sep = HTTP_URL_ARGSEP; + arg_sep_len = lenof(HTTP_URL_ARGSEP); } if (pre_encoded_len && pre_encoded_data) { phpstr_append(qstr, pre_encoded_data, pre_encoded_len); } - if (SUCCESS != http_urlencode_hash_implementation(hash, qstr, arg_sep)) { + if (SUCCESS != http_urlencode_hash_recursive(hash, qstr, arg_sep, arg_sep_len, NULL, 0)) { phpstr_free(&qstr); return FAILURE; } @@ -205,167 +207,88 @@ PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_ } /* }}} */ -/* {{{ http_urlencode_hash_implementation - Original Author: Sara Golemon */ -PHP_HTTP_API STATUS _http_urlencode_hash_implementation_ex( - HashTable *ht, phpstr *formstr, char *arg_sep, - const char *num_prefix, int num_prefix_len, - const char *key_prefix, int key_prefix_len, - const char *key_suffix, int key_suffix_len, - zval *type TSRMLS_DC) +/* {{{ http_urlencode_hash_recursive */ +PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, const char *arg_sep, size_t arg_sep_len, const char *prefix, size_t prefix_len TSRMLS_DC) { - char *key = NULL, *ekey, *newprefix, *p; - int arg_sep_len, ekey_len, key_type, newprefix_len; - uint key_len; - ulong idx; - zval **zdata = NULL, *copyzval; + char *key = NULL; + uint len = 0; + ulong idx = 0; + zval **data = NULL; - if (!ht || !formstr) { + if (!ht || !str) { http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid parameters"); return FAILURE; } - if (ht->nApplyCount > 0) { - /* Prevent recursion */ return SUCCESS; } - - if (!arg_sep || !strlen(arg_sep)) { - arg_sep = HTTP_URL_ARGSEP; - } - arg_sep_len = strlen(arg_sep); - - for (zend_hash_internal_pointer_reset(ht); - (key_type = zend_hash_get_current_key_ex(ht, &key, &key_len, &idx, 0, NULL)) != HASH_KEY_NON_EXISTANT; - zend_hash_move_forward(ht) - ) { - if (key_type == HASH_KEY_IS_STRING && key_len && key[key_len-1] == '\0') { - /* We don't want that trailing NULL */ - key_len -= 1; + + FOREACH_HASH_KEYLENVAL(ht, key, len, idx, data) { + char *encoded_key; + int encoded_len; + phpstr new_prefix; + + if (!data || !*data) { + return FAILURE; } - -#ifdef ZEND_ENGINE_2 - /* handling for private & protected object properties */ - if (key && *key == '\0' && type != NULL) { - char *tmp; - - zend_object *zobj = zend_objects_get_address(type TSRMLS_CC); - if (zend_check_property_access(zobj, key TSRMLS_CC) != SUCCESS) { - /* private or protected property access outside of the class */ - continue; + + if (key) { + if (len && key[len - 1] == '\0') { + --len; } - zend_unmangle_property_name(key, &tmp, &key); - key_len = strlen(key); + encoded_key = php_url_encode(key, len, &encoded_len); + key = NULL; + } else { + encoded_len = spprintf(&encoded_key, 0, "%ld", idx); } -#endif - - if (zend_hash_get_current_data_ex(ht, (void **)&zdata, NULL) == FAILURE || !zdata || !(*zdata)) { - http_error(HE_WARNING, HTTP_E_ENCODING, "Error traversing form data array."); - return FAILURE; + + { + phpstr_init(&new_prefix); + if (prefix && prefix_len) { + phpstr_append(&new_prefix, prefix, prefix_len); + phpstr_appends(&new_prefix, "["); + } + + phpstr_append(&new_prefix, encoded_key, encoded_len); + efree(encoded_key); + + if (prefix && prefix_len) { + phpstr_appends(&new_prefix, "]"); + } + phpstr_fix(&new_prefix); } - if (Z_TYPE_PP(zdata) == IS_ARRAY || Z_TYPE_PP(zdata) == IS_OBJECT) { - if (key_type == HASH_KEY_IS_STRING) { - ekey = php_url_encode(key, key_len, &ekey_len); - newprefix_len = key_suffix_len + ekey_len + key_prefix_len + 1; - newprefix = emalloc(newprefix_len + 1); - p = newprefix; - - if (key_prefix) { - memcpy(p, key_prefix, key_prefix_len); - p += key_prefix_len; - } - - memcpy(p, ekey, ekey_len); - p += ekey_len; - efree(ekey); - - if (key_suffix) { - memcpy(p, key_suffix, key_suffix_len); - p += key_suffix_len; - } - - *(p++) = '['; - *p = '\0'; - } else { - /* Is an integer key */ - ekey_len = spprintf(&ekey, 12, "%ld", idx); - newprefix_len = key_prefix_len + num_prefix_len + ekey_len + key_suffix_len + 1; - newprefix = emalloc(newprefix_len + 1); - p = newprefix; - - if (key_prefix) { - memcpy(p, key_prefix, key_prefix_len); - p += key_prefix_len; - } - - memcpy(p, num_prefix, num_prefix_len); - p += num_prefix_len; - - memcpy(p, ekey, ekey_len); - p += ekey_len; - efree(ekey); - - if (key_suffix) { - memcpy(p, key_suffix, key_suffix_len); - p += key_suffix_len; - } - *(p++) = '['; - *p = '\0'; + + if (Z_TYPE_PP(data) == IS_ARRAY) { + STATUS status; + ++ht->nApplyCount; + status = http_urlencode_hash_recursive(Z_ARRVAL_PP(data), str, arg_sep, arg_sep_len, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix)); + --ht->nApplyCount; + if (SUCCESS != status) { + phpstr_dtor(&new_prefix); + return FAILURE; } - ht->nApplyCount++; - http_urlencode_hash_implementation_ex(HASH_OF(*zdata), formstr, arg_sep, - NULL, 0, newprefix, newprefix_len, "]", 1, (Z_TYPE_PP(zdata) == IS_OBJECT ? *zdata : NULL)); - ht->nApplyCount--; - efree(newprefix); - } else if (Z_TYPE_PP(zdata) == IS_NULL || Z_TYPE_PP(zdata) == IS_RESOURCE) { - /* Skip these types */ - continue; } else { - if (formstr->used) { - phpstr_append(formstr, arg_sep, arg_sep_len); - } - /* Simple key=value */ - phpstr_append(formstr, key_prefix, key_prefix_len); - if (key_type == HASH_KEY_IS_STRING) { - ekey = php_url_encode(key, key_len, &ekey_len); - phpstr_append(formstr, ekey, ekey_len); - efree(ekey); - } else { - /* Numeric key */ - if (num_prefix) { - phpstr_append(formstr, num_prefix, num_prefix_len); - } - ekey_len = spprintf(&ekey, 12, "%ld", idx); - phpstr_append(formstr, ekey, ekey_len); - efree(ekey); + char *encoded_val; + int encoded_len; + zval *cpy, *val = convert_to_type_ex(IS_STRING, *data, &cpy); + + if (PHPSTR_LEN(str)) { + phpstr_append(str, arg_sep, arg_sep_len); } - phpstr_append(formstr, key_suffix, key_suffix_len); - phpstr_appends(formstr, "="); - switch (Z_TYPE_PP(zdata)) { - case IS_STRING: - ekey = php_url_encode(Z_STRVAL_PP(zdata), Z_STRLEN_PP(zdata), &ekey_len); - break; - case IS_LONG: - case IS_BOOL: - ekey_len = spprintf(&ekey, 12, "%ld", Z_LVAL_PP(zdata)); - break; - case IS_DOUBLE: - ekey_len = spprintf(&ekey, 48, "%.*G", (int) EG(precision), Z_DVAL_PP(zdata)); - break; - default: - /* fall back on convert to string */ - MAKE_STD_ZVAL(copyzval); - *copyzval = **zdata; - zval_copy_ctor(copyzval); - convert_to_string_ex(©zval); - ekey = php_url_encode(Z_STRVAL_P(copyzval), Z_STRLEN_P(copyzval), &ekey_len); - zval_ptr_dtor(©zval); + phpstr_append(str, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix)); + phpstr_appends(str, "="); + + encoded_val = php_url_encode(Z_STRVAL_P(val), Z_STRLEN_P(val), &encoded_len); + phpstr_append(str, encoded_val, encoded_len); + efree(encoded_val); + + if (cpy) { + zval_ptr_dtor(&cpy); } - phpstr_append(formstr, ekey, ekey_len); - efree(ekey); } + + phpstr_dtor(&new_prefix); } - return SUCCESS; } /* }}} */ diff --git a/php_http_std_defs.h b/php_http_std_defs.h index c7646b7..8960485 100644 --- a/php_http_std_defs.h +++ b/php_http_std_defs.h @@ -146,7 +146,14 @@ typedef int STATUS; for ( zend_hash_internal_pointer_reset(hash); \ zend_hash_get_current_key(hash, &strkey, &numkey, 0) != HASH_KEY_NON_EXISTANT && \ zend_hash_get_current_data(hash, (void **) &val) == SUCCESS; \ - zend_hash_move_forward(hash)) \ + zend_hash_move_forward(hash)) + +#define FOREACH_KEYLENVAL(array, strkey, keylen, numkey, val) FOREACH_HASH_KEYVAL(Z_ARRVAL_P(array), strkey, keylen, numkey, val) +#define FOREACH_HASH_KEYLENVAL(hash, strkey, keylen, numkey, val) \ + for ( zend_hash_internal_pointer_reset(hash); \ + zend_hash_get_current_key_ex(hash, &strkey, &keylen, &numkey, 0, NULL) != HASH_KEY_NON_EXISTANT && \ + zend_hash_get_current_data(hash, (void **) &val) == SUCCESS; \ + zend_hash_move_forward(hash)) #define array_copy(src, dst) zend_hash_copy(Z_ARRVAL_P(dst), Z_ARRVAL_P(src), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)) #define array_merge(src, dst) zend_hash_merge(Z_ARRVAL_P(dst), Z_ARRVAL_P(src), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *), 1) diff --git a/php_http_url_api.h b/php_http_url_api.h index a339440..4a4080f 100644 --- a/php_http_url_api.h +++ b/php_http_url_api.h @@ -27,17 +27,8 @@ PHP_HTTP_API char *_http_absolute_url_ex(const char *url, size_t url_len, const #define http_urlencode_hash_ex(h, o, p, pl, q, ql) _http_urlencode_hash_ex((h), (o), (p), (pl), (q), (ql) TSRMLS_CC) PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_argsep, char *pre_encoded_data, size_t pre_encoded_len, char **encoded_data, size_t *encoded_len TSRMLS_DC); -#define http_urlencode_hash_implementation(ht, formstr, argsep) \ - http_urlencode_hash_implementation_ex((ht), (formstr), (argsep), NULL, 0, NULL, 0, NULL, 0, NULL) -#define http_urlencode_hash_implementation_ex(ht, formstr, argsep, np, npl, kp, kpl, ks, ksl, type) \ - _http_urlencode_hash_implementation_ex((ht), (formstr), (argsep), (np), (npl), (kp), (kpl), (ks), (ksl), (type) TSRMLS_CC) -PHP_HTTP_API STATUS _http_urlencode_hash_implementation_ex( - HashTable *ht, phpstr *formstr, char *arg_sep, - const char *num_prefix, int num_prefix_len, - const char *key_prefix, int key_prefix_len, - const char *key_suffix, int key_suffix_len, - zval *type TSRMLS_DC); - +#define http_urlencode_hash_recursive(ht, s, as, al, pr, pl) _http_urlencode_hash_recursive((ht), (s), (as), (al), (pr), (pl) TSRMLS_CC) +PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, const char *arg_sep, size_t arg_sep_len, const char *prefix, size_t prefix_len TSRMLS_DC); #endif -- 2.30.2