- own, simpler hash urlencoder
authorMichael Wallner <mike@php.net>
Tue, 1 Nov 2005 11:08:58 +0000 (11:08 +0000)
committerMichael Wallner <mike@php.net>
Tue, 1 Nov 2005 11:08:58 +0000 (11:08 +0000)
LICENSE
http_functions.c
http_url_api.c
php_http_std_defs.h
php_http_url_api.h

diff --git a/LICENSE b/LICENSE
index c274794c7209cec406ecfb1c1ff59c274d97620c..a54036efdd8e8ab8e174ef6260dececfa7dcdd78 100644 (file)
--- 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.
 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
-     <http://www.php.net/>".
-
-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.
-
index 5ff5e33a7eff753d79771b9ade894f1a98c3dde0..7d82438ef6e059f52465c1343dac139d46545ca0 100644 (file)
@@ -1381,21 +1381,17 @@ PHP_FUNCTION(http_build_query)
        int prefix_len = 0, arg_sep_len = strlen(arg_sep);
        phpstr *formstr;
 
        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;
                RETURN_FALSE;
        }
 
        if (!arg_sep_len) {
                arg_sep = HTTP_URL_ARGSEP;
+               arg_sep_len = lenof(HTTP_URL_ARGSEP);
        }
 
        formstr = phpstr_new();
        }
 
        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;
        }
                phpstr_free(&formstr);
                RETURN_FALSE;
        }
index 2cde7bc71364938f94b4d73e06f25a3e97d137ec..aa0c1f37c835692631866bd1083565604c39a6d6 100644 (file)
@@ -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;
        char **encoded_data, size_t *encoded_len TSRMLS_DC)
 {
        char *arg_sep;
+       size_t arg_sep_len;
        phpstr *qstr = phpstr_new();
 
        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 = 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 (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;
        }
                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 <pollita@php.net> */
-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;
        }
                http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid parameters");
                return FAILURE;
        }
-
        if (ht->nApplyCount > 0) {
        if (ht->nApplyCount > 0) {
-               /* Prevent recursion */
                return SUCCESS;
        }
                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 {
                } 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(&copyzval);
-                                       ekey = php_url_encode(Z_STRVAL_P(copyzval), Z_STRLEN_P(copyzval), &ekey_len);
-                                       zval_ptr_dtor(&copyzval);
+                       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;
 }
 /* }}} */
        return SUCCESS;
 }
 /* }}} */
index c7646b7cd857e6d30158fc7ed163d5e9db78ebd3..896048537a49bac390ed8b126bab22297a503700 100644 (file)
@@ -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; \
        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)
 
 #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)
index a3394406e4db10f5b42463cd4bff1c0e2de76862..4a4080f61acc890581505a759db03c921f0fd2c1 100644 (file)
@@ -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_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
 
 
 #endif