- split off query strin API and use it in
authorMichael Wallner <mike@php.net>
Sat, 22 Apr 2006 21:04:37 +0000 (21:04 +0000)
committerMichael Wallner <mike@php.net>
Sat, 22 Apr 2006 21:04:37 +0000 (21:04 +0000)
  http_build_url() with HTTP_URL_JOIN_QUERY

config.m4
config.w32
docs/functions.html
http.dsp
http_functions.c
http_querystring_api.c [new file with mode: 0644]
http_querystring_object.c
http_url_api.c
package2.xml
php_http_querystring_api.h [new file with mode: 0644]
tests/build_url_004.phpt

index 6450d56..555bbc7 100644 (file)
--- a/config.m4
+++ b/config.m4
@@ -232,7 +232,8 @@ dnl ----
                http_headers_api.c http_message_api.c http_send_api.c http_url_api.c \
                http_info_api.c http_request_method_api.c http_encoding_api.c \
                http_filter_api.c http_request_body_api.c http_querystring_object.c \
-               http_deflatestream_object.c http_inflatestream_object.c http_cookie_api.c"
+               http_deflatestream_object.c http_inflatestream_object.c http_cookie_api.c \
+               http_querystring_api.c"
        PHP_NEW_EXTENSION([http], $PHP_HTTP_SOURCES, $ext_shared)
        PHP_ADD_BUILD_DIR($ext_builddir/phpstr, 1)
        PHP_SUBST([HTTP_SHARED_LIBADD])
@@ -244,7 +245,7 @@ dnl ----
                php_http_exception_object.h php_http_message_object.h php_http_request_object.h \
                php_http_requestpool_object.h php_http_response_object.h php_http_util_object.h \
                php_http_querystring_object.h php_http_deflatestream_object.h php_http_inflatestream_object.h \
-               php_http_cookie_api.h"
+               php_http_cookie_api.h php_http_querystring_api.h"
        ifdef([PHP_INSTALL_HEADERS], [
                PHP_INSTALL_HEADERS(ext/http, $PHP_HTTP_HEADERS)
        ], [
index e0a8af8..c82eca4 100644 (file)
@@ -56,7 +56,7 @@ if (PHP_HTTP != "no") {
                "http_info_api.c http_request_method_api.c http_encoding_api.c "+
                "http_filter_api.c http_request_body_api.c http_querystring_object.c "+
                "http_deflatestream_object.c http_inflatestream_object.c "+
-               "http_cookie_api.c",
+               "http_cookie_api.c http_querystring_api.c",
                null,
                "/I\"" + configure_module_dirname + "/phpstr\"");
        ADD_SOURCES(configure_module_dirname + "/phpstr", "phpstr.c", "http");
index e0d1e1c..7139f2a 100644 (file)
@@ -74,7 +74,7 @@
 looking like: "Wed, 22 Dec 2004 11:34:47 GMT"</p>
 <p>Accepts an optional unix timestamp as parameter.</p>
 <p>Returns the HTTP date as string.</p>
-<h2 id="http_build_url">string http_build_url(mixed url[, mixed parts[, int flags = HTTP_URL_REPLACE[, array &new_url]]])</h2>
+<h2 id="http_build_url">string http_build_url([mixed url[, mixed parts[, int flags = HTTP_URL_REPLACE[, array &new_url]]]])</h2>
 <p>Build an URL.</p>
 <p>Expexts (part(s) of) an URL as first parameter in form of a string or assoziative array<br />
 like parse_url() returns.  Accepts an optional second parameter in the same way as the<br />
@@ -84,7 +84,7 @@ with the results as associative array like parse_url() would return.</p>
 <p>The parts of the second URL will be merged into the first according to the flags argument.<br />
 The following flags are recognized:</p><pre>   - HTTP_URL_REPLACE:        (default) set parts of the second url will replace the parts in the first<br />
        - HTTP_URL_JOIN_PATH:      the path of the second url will be merged into the one of the first<br />
-       - HTTP_URL_JOIN_QUERY:     the two querystrings will be merged naivly; no replacements are done<br />
+       - HTTP_URL_JOIN_QUERY:     the two querystrings will be merged recursively<br />
        - HTTP_URL_STRIP_USER:     the user part will not appear in the result<br />
        - HTTP_URL_STRIP_PASS:     the password part will not appear in the result<br />
        - HTTP_URL_STRIP_AUTH:     neither the user nor the password part will appear in the result<br />
@@ -476,6 +476,9 @@ all supported features.</p>
 <hr noshade>
 <h1 id="http_inflatestream_object.c">http_inflatestream_object.c</h1>
 <h2 id="HttpInflateStream" class="o">HttpInflateStream</h2>
+<h3 id="HttpInflateStream___construct">void HttpInflateStream::__construct([int flags = 0])</h3>
+<p>Creates a new HttpInflateStream object instance.</p>
+<p>Accepts an optional int parameter specifying how to initialize the inflate stream.</p>
 <h3 id="HttpInflateStream_update">string HttpInflateStream::update(string data)</h3>
 <p>Passes more data through the inflate stream.</p>
 <p>Expects a string parameter containing (a part of) the data to inflate.</p>
@@ -1245,6 +1248,7 @@ http.cache_log is set.</p>
 </li>
 <li><a class="tocfile" href="#http_inflatestream_object.c">http_inflatestream_object.c</a>
 <ul>
+<li><a href="#HttpInflateStream___construct">HttpInflateStream::__construct()</a></li>
 <li><a href="#HttpInflateStream_update">HttpInflateStream::update()</a></li>
 <li><a href="#HttpInflateStream_flush">HttpInflateStream::flush()</a></li>
 <li><a href="#HttpInflateStream_finish">HttpInflateStream::finish()</a></li>
@@ -1415,7 +1419,7 @@ http.cache_log is set.</p>
 </li>
 </ul>
 </div>
-    <p><b>Generated at: Thu, 13 Apr 2006 17:25:58 +0200</b></p>
+    <p><b>Generated at: Sat, 22 Apr 2006 23:03:59 +0200</b></p>
 </body>
 </html>
 
index 587cf27..9609ef9 100644 (file)
--- a/http.dsp
+++ b/http.dsp
@@ -150,6 +150,10 @@ SOURCE=.\http_url_api.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\http_querystring_api.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\http_info_api.c\r
 # End Source File\r
 # Begin Source File\r
@@ -214,6 +218,10 @@ SOURCE=.\php_http_url_api.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\php_http_querystring_api.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\php_http_info_api.h\r
 # End Source File\r
 # Begin Source File\r
index 113db97..9b42801 100644 (file)
@@ -77,7 +77,7 @@ PHP_FUNCTION(http_date)
  * <pre>
  *     - HTTP_URL_REPLACE:        (default) set parts of the second url will replace the parts in the first
  *     - HTTP_URL_JOIN_PATH:      the path of the second url will be merged into the one of the first
- *     - HTTP_URL_JOIN_QUERY:     the two querystrings will be merged naivly; no replacements are done
+ *     - HTTP_URL_JOIN_QUERY:     the two querystrings will be merged recursively
  *     - HTTP_URL_STRIP_USER:     the user part will not appear in the result
  *     - HTTP_URL_STRIP_PASS:     the password part will not appear in the result
  *     - HTTP_URL_STRIP_AUTH:     neither the user nor the password part will appear in the result
diff --git a/http_querystring_api.c b/http_querystring_api.c
new file mode 100644 (file)
index 0000000..a15a0db
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+    +--------------------------------------------------------------------+
+    | PECL :: http                                                       |
+    +--------------------------------------------------------------------+
+    | Redistribution and use in source and binary forms, with or without |
+    | modification, are permitted provided that the conditions mentioned |
+    | in the accompanying LICENSE file are met.                          |
+    +--------------------------------------------------------------------+
+    | Copyright (c) 2004-2006, Michael Wallner <mike@php.net>            |
+    +--------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#define HTTP_WANT_SAPI
+#include "php_http.h"
+
+#include "php_variables.h"
+#ifdef HAVE_ICONV
+#      undef PHP_ATOM_INC
+#      include "ext/iconv/php_iconv.h"
+#      include "ext/standard/url.h"
+#endif
+
+#include "php_http_api.h"
+#include "php_http_url_api.h"
+#include "php_http_querystring_api.h"
+
+#ifdef ZEND_ENGINE_2
+#define OBJ_PROP_CE http_querystring_object_ce
+extern zend_class_entry *http_querystring_object_ce;
+#endif
+
+#ifdef HAVE_ICONV
+PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC)
+{
+       HashPosition pos;
+       zval **entry = NULL;
+       char *xlate_str = NULL, *xkey, *kstr = NULL;
+       size_t xlate_len = 0, xlen;
+       uint klen = 0;
+       ulong kidx = 0;
+       
+       FOREACH_KEYLENVAL(pos, param, kstr, klen, kidx, entry) {
+               if (kstr) {
+                       if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(kstr, klen-1, &xkey, &xlen, oe, ie)) {
+                               http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", klen-1, kstr, ie, oe);
+                               return FAILURE;
+                       }
+               }
+               
+               if (Z_TYPE_PP(entry) == IS_STRING) {
+                       if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), &xlate_str, &xlate_len, oe, ie)) {
+                               if (kstr) {
+                                       efree(xkey);
+                               }
+                               http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", Z_STRLEN_PP(entry), Z_STRVAL_PP(entry), ie, oe);
+                               return FAILURE;
+                       }
+                       if (kstr) {
+                               add_assoc_stringl_ex(array, xkey, xlen+1, xlate_str, xlate_len, 0);
+                       } else {
+                               add_index_stringl(array, kidx, xlate_str, xlate_len, 0);
+                       }
+               } else if (Z_TYPE_PP(entry) == IS_ARRAY) {
+                       zval *subarray;
+                       
+                       MAKE_STD_ZVAL(subarray);
+                       array_init(subarray);
+                       if (kstr) {
+                               add_assoc_zval_ex(array, xkey, xlen+1, subarray);
+                       } else {
+                               add_index_zval(array, kidx, subarray);
+                       }
+                       if (SUCCESS != http_querystring_xlate(subarray, *entry, ie, oe)) {
+                               if (kstr) {
+                                       efree(xkey);
+                               }
+                               return FAILURE;
+                       }
+               }
+               
+               if (kstr) {
+                       kstr = NULL;
+                       efree(xkey);
+               }
+       }
+       return SUCCESS;
+}
+#endif /* HAVE_ICONV */
+
+PHP_HTTP_API void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC)
+{
+       char *s = NULL;
+       size_t l = 0;
+       
+       if (Z_TYPE_P(qarray) != IS_ARRAY) {
+               convert_to_array(qarray);
+       }
+       if (SUCCESS == http_urlencode_hash_ex(Z_ARRVAL_P(qarray), 0, NULL, 0, &s, &l)) {
+               zval_dtor(qstring);
+               ZVAL_STRINGL(qstring, s, l, 0);
+       } else {
+               http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to update query string");
+       }
+}
+
+PHP_HTTP_API int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC)
+{
+       zval **qarray_entry;
+       
+       /* delete */
+       if (Z_TYPE_P(params_entry) == IS_NULL) {
+               if (key_type == HASH_KEY_IS_STRING) {
+                       return (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), key, keylen));
+               } else {
+                       return (SUCCESS == zend_hash_index_del(Z_ARRVAL_P(qarray), idx));
+               }
+       }
+       
+       /* update */
+       if (    ((key_type == HASH_KEY_IS_STRING) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), key, keylen, (void *) &qarray_entry))) ||
+                       ((key_type == HASH_KEY_IS_LONG) && (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(qarray), idx, (void *) &qarray_entry)))) {
+               zval equal;
+               
+               /* recursive */
+               if (Z_TYPE_P(params_entry) == IS_ARRAY) {
+                       return http_querystring_modify_array(*qarray_entry, params_entry);
+               }
+               /* equal */
+               if ((SUCCESS == is_equal_function(&equal, *qarray_entry, params_entry TSRMLS_CC)) && Z_BVAL(equal)) {
+                       return 0;
+               }
+       }
+       
+       /* add */
+       ZVAL_ADDREF(params_entry);
+       if (key_type == HASH_KEY_IS_STRING) {
+               add_assoc_zval_ex(qarray, key, keylen, params_entry);
+       } else {
+               add_index_zval(qarray, idx, params_entry);
+       }
+       return 1;
+}
+
+PHP_HTTP_API int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC)
+{
+       int rv = 0;
+       char *key = NULL;
+       uint keylen = 0;
+       ulong idx = 0;
+       HashPosition pos;
+       zval **params_entry = NULL;
+       
+       FOREACH_KEYLENVAL(pos, params, key, keylen, idx, params_entry) {
+               if (http_querystring_modify_array_ex(qarray, key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG, key, keylen, idx, *params_entry)) {
+                       rv = 1;
+               }
+               key = NULL;
+       }
+       
+       return rv;
+}
+
+PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC)
+{
+       if (Z_TYPE_P(params) == IS_ARRAY) {
+               return http_querystring_modify_array(qarray, params);
+       } else if (Z_TYPE_P(params) == IS_OBJECT) {
+#ifdef ZEND_ENGINE_2
+               if (!instanceof_function(Z_OBJCE_P(params), http_querystring_object_ce TSRMLS_CC)) {
+#endif
+                       zval temp_array;
+                       INIT_ZARR(temp_array, HASH_OF(params));
+                       return http_querystring_modify_array(qarray, &temp_array);
+#ifdef ZEND_ENGINE_2
+               }
+               return http_querystring_modify_array(qarray, GET_PROP_EX(params, queryArray));
+#endif
+       } else {
+               int rv;
+               zval array;
+               
+               INIT_PZVAL(&array);
+               array_init(&array);
+               
+               ZVAL_ADDREF(params);
+               convert_to_string_ex(&params);
+               sapi_module.treat_data(PARSE_STRING, estrdup(Z_STRVAL_P(params)), &array TSRMLS_CC);
+               zval_ptr_dtor(&params);
+               rv = http_querystring_modify_array(qarray, &array);
+               zval_dtor(&array);
+               return rv;
+       }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
index 70c68cf..6f452b9 100644 (file)
 #include "php_variables.h"
 #include "zend_interfaces.h"
 
-#ifdef HAVE_ICONV
-#      undef PHP_ATOM_INC
-#      include "ext/iconv/php_iconv.h"
-#      include "ext/standard/url.h"
-#endif
-
 #include "php_http_api.h"
-#include "php_http_url_api.h"
+#include "php_http_querystring_api.h"
 #include "php_http_querystring_object.h"
 #include "php_http_exception_object.h"
 
@@ -183,74 +177,6 @@ void _http_querystring_object_free(zend_object *object TSRMLS_DC)
 }
 
 /* {{{ querystring helpers */
-#define http_querystring_update(qa, qs) _http_querystring_update((qa), (qs) TSRMLS_CC)
-static inline void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC);
-#define http_querystring_modify_array_ex(q, k, kl, pe) _http_querystring_modify_array_ex((q), (k), (kl), (pe) TSRMLS_CC)
-static inline int _http_querystring_modify_array_ex(zval *qarray, char *key, int keylen, zval *params_entry TSRMLS_DC);
-#define http_querystring_modify_array(q, p) _http_querystring_modify_array((q), (p) TSRMLS_CC)
-static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC);
-#define http_querystring_modify(q, p) _http_querystring_modify((q), (p) TSRMLS_CC)
-static inline int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC);
-#define http_querystring_get(o, t, n, l, def, del, r) _http_querystring_get((o), (t), (n), (l), (def), (del), (r) TSRMLS_CC)
-static inline void _http_querystring_get(zval *this_ptr, int type, char *name, uint name_len, zval *defval, zend_bool del, zval *return_value TSRMLS_DC);
-#ifdef HAVE_ICONV
-#define http_querystring_xlate(a, p, ie, oe) _http_querystring_xlate((a), (p), (ie), (oe) TSRMLS_CC)
-static inline int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC)
-{
-       HashPosition pos;
-       zval **entry = NULL;
-       char *xlate_str = NULL, *xkey, *kstr = NULL;
-       size_t xlate_len = 0, xlen;
-       uint klen = 0;
-       ulong kidx = 0;
-       
-       FOREACH_KEYLENVAL(pos, param, kstr, klen, kidx, entry) {
-               if (kstr) {
-                       if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(kstr, klen-1, &xkey, &xlen, oe, ie)) {
-                               http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", klen-1, kstr, ie, oe);
-                               return FAILURE;
-                       }
-               }
-               
-               if (Z_TYPE_PP(entry) == IS_STRING) {
-                       if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), &xlate_str, &xlate_len, oe, ie)) {
-                               if (kstr) {
-                                       efree(xkey);
-                               }
-                               http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", Z_STRLEN_PP(entry), Z_STRVAL_PP(entry), ie, oe);
-                               return FAILURE;
-                       }
-                       if (kstr) {
-                               add_assoc_stringl_ex(array, xkey, xlen+1, xlate_str, xlate_len, 0);
-                       } else {
-                               add_index_stringl(array, kidx, xlate_str, xlate_len, 0);
-                       }
-               } else if (Z_TYPE_PP(entry) == IS_ARRAY) {
-                       zval *subarray;
-                       
-                       MAKE_STD_ZVAL(subarray);
-                       array_init(subarray);
-                       if (kstr) {
-                               add_assoc_zval_ex(array, xkey, xlen+1, subarray);
-                       } else {
-                               add_index_zval(array, kidx, subarray);
-                       }
-                       if (SUCCESS != http_querystring_xlate(subarray, *entry, ie, oe)) {
-                               if (kstr) {
-                                       efree(xkey);
-                               }
-                               return FAILURE;
-                       }
-               }
-               
-               if (kstr) {
-                       kstr = NULL;
-                       efree(xkey);
-               }
-       }
-       return SUCCESS;
-}
-#endif /* HAVE_ICONV */
 #ifndef WONKY
 #define http_querystring_instantiate(g) _http_querystring_instantiate((g) TSRMLS_CC)
 static inline zval *_http_querystring_instantiate(zend_bool global TSRMLS_DC)
@@ -270,102 +196,8 @@ static inline zval *_http_querystring_instantiate(zend_bool global TSRMLS_DC)
        return zobj;
 }
 #endif /* WONKY */
-static inline void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC)
-{
-       char *s = NULL;
-       size_t l = 0;
-       
-       if (Z_TYPE_P(qarray) != IS_ARRAY) {
-               convert_to_array(qarray);
-       }
-       if (SUCCESS == http_urlencode_hash_ex(Z_ARRVAL_P(qarray), 0, NULL, 0, &s, &l)) {
-               zval_dtor(qstring);
-               ZVAL_STRINGL(qstring, s, l, 0);
-       } else {
-               http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to update query string");
-       }
-}
-static inline int _http_querystring_modify_array_ex(zval *qarray, char *key, int keylen, zval *params_entry TSRMLS_DC)
-{
-       zval **qarray_entry;
-       
-       /* delete */
-       if (Z_TYPE_P(params_entry) == IS_NULL) {
-               return (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), key, keylen));
-       }
-       
-       /* update */
-       if (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), key, keylen, (void *) &qarray_entry)) {
-               zval equal;
-               
-               /* recursive */
-               if (Z_TYPE_P(params_entry) == IS_ARRAY) {
-                        return http_querystring_modify_array(*qarray_entry, params_entry);
-               }
-               /* equal */
-               if ((SUCCESS == is_equal_function(&equal, *qarray_entry, params_entry TSRMLS_CC)) && Z_BVAL(equal)) {
-                       return 0;
-               }
-       }
-       
-       /* add */
-       ZVAL_ADDREF(params_entry);
-       add_assoc_zval_ex(qarray, key, keylen, params_entry);
-       return 1;
-}
-static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC)
-{
-       int rv = 0;
-       char *key;
-       uint keylen;
-       ulong idx;
-       HashPosition pos;
-       zval **params_entry;
-       
-       FOREACH_KEYLENVAL(pos, params, key, keylen, idx, params_entry) {
-               if (key) {
-                       if (http_querystring_modify_array_ex(qarray, key, keylen, *params_entry)) {
-                               rv = 1;
-                       }
-               } else {
-                       keylen = spprintf(&key, 0, "%lu", idx);
-                       if (http_querystring_modify_array_ex(qarray, key, keylen, *params_entry)) {
-                               rv = 1;
-                       }
-                       efree(key);
-               }
-               key = NULL;
-       }
-       
-       return rv;
-}
-static inline int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC)
-{
-       if (Z_TYPE_P(params) == IS_ARRAY) {
-               return http_querystring_modify_array(qarray, params);
-       } else if (Z_TYPE_P(params) == IS_OBJECT) {
-               if (!instanceof_function(Z_OBJCE_P(params), http_querystring_object_ce TSRMLS_CC)) {
-                       zval temp_array;
-                       INIT_ZARR(temp_array, HASH_OF(params));
-                       return http_querystring_modify_array(qarray, &temp_array);
-               }
-               return http_querystring_modify_array(qarray, GET_PROP_EX(params, queryArray));
-       } else {
-               int rv;
-               zval array;
-               
-               INIT_PZVAL(&array);
-               array_init(&array);
-               
-               ZVAL_ADDREF(params);
-               convert_to_string_ex(&params);
-               sapi_module.treat_data(PARSE_STRING, estrdup(Z_STRVAL_P(params)), &array TSRMLS_CC);
-               zval_ptr_dtor(&params);
-               rv = http_querystring_modify_array(qarray, &array);
-               zval_dtor(&array);
-               return rv;
-       }
-}
+
+#define http_querystring_get(o, t, n, l, def, del, r) _http_querystring_get((o), (t), (n), (l), (def), (del), (r) TSRMLS_CC)
 static inline void _http_querystring_get(zval *this_ptr, int type, char *name, uint name_len, zval *defval, zend_bool del, zval *return_value TSRMLS_DC)
 {
        zval **arrval, *qarray = GET_PROP(queryArray);
index bdda911..1ccd4db 100644 (file)
@@ -21,6 +21,7 @@
 #include "ext/standard/php_string.h"
 
 #include "php_http_api.h"
+#include "php_http_querystring_api.h"
 #include "php_http_url_api.h"
 
 static inline char *localhostname(void)
@@ -131,10 +132,21 @@ PHP_HTTP_API void _http_build_url(int flags, const php_url *old_url, const php_u
        }
        if (!(flags & HTTP_URL_STRIP_QUERY)) {
                if ((flags & HTTP_URL_JOIN_QUERY) && __URLSET(new_url, query) && __URLSET(old_url, query)) {
-                       url->query = ecalloc(1, strlen(new_url->query) + strlen(old_url->query) + 1 + 1);
-                       strcat(url->query, old_url->query);
-                       strcat(url->query, "&");
-                       strcat(url->query, new_url->query);
+                       zval qarr, qstr;
+                       
+                       INIT_PZVAL(&qstr);
+                       INIT_PZVAL(&qarr);
+                       array_init(&qarr);
+                       
+                       ZVAL_STRING(&qstr, old_url->query, 0);
+                       http_querystring_modify(&qarr, &qstr);
+                       ZVAL_STRING(&qstr, new_url->query, 0);
+                       http_querystring_modify(&qarr, &qstr);
+                       
+                       ZVAL_NULL(&qstr);
+                       http_querystring_update(&qarr, &qstr);
+                       url->query = Z_STRVAL(qstr);
+                       zval_dtor(&qarr);
                } else {
                        __URLCPY(query);
                }
index 9dbcddc..a840438 100644 (file)
@@ -48,6 +48,7 @@ HttpResponse
  <notes><![CDATA[
 * Fixed possible crash in progress/onfinish request callbacks
 * Fixed http_redirect() and http_build_url() without arguments
+* Enabled recursive query string merging in http_build_url() with HTTP_URL_JOIN_QUERY
 ]]></notes>
  <contents>
   <dir name="/">
diff --git a/php_http_querystring_api.h b/php_http_querystring_api.h
new file mode 100644 (file)
index 0000000..05bcbcb
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+    +--------------------------------------------------------------------+
+    | PECL :: http                                                       |
+    +--------------------------------------------------------------------+
+    | Redistribution and use in source and binary forms, with or without |
+    | modification, are permitted provided that the conditions mentioned |
+    | in the accompanying LICENSE file are met.                          |
+    +--------------------------------------------------------------------+
+    | Copyright (c) 2004-2006, Michael Wallner <mike@php.net>            |
+    +--------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef PHP_HTTP_QUERYSTRING_API_H
+#define PHP_HTTP_QUERYSTRING_API_H
+
+#ifdef HAVE_ICONV
+#define http_querystring_xlate(a, p, ie, oe) _http_querystring_xlate((a), (p), (ie), (oe) TSRMLS_CC)
+PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC);
+#endif
+
+#define http_querystring_update(qa, qs) _http_querystring_update((qa), (qs) TSRMLS_CC)
+PHP_HTTP_API void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC);
+
+#define http_querystring_modify_array_ex(q, t, k, kl, i, pe) _http_querystring_modify_array_ex((q), (t), (k), (kl), (i), (pe) TSRMLS_CC)
+PHP_HTTP_API int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC);
+
+#define http_querystring_modify_array(q, p) _http_querystring_modify_array((q), (p) TSRMLS_CC)
+PHP_HTTP_API int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC);
+
+#define http_querystring_modify(q, p) _http_querystring_modify((q), (p) TSRMLS_CC)
+PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC);
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
index 118ca7e..10ce955 100644 (file)
@@ -10,7 +10,7 @@ echo "-TEST\n";
 echo http_build_url("http://mike@www.example.com/foo/bar", "./baz", HTTP_URL_STRIP_AUTH|HTTP_URL_JOIN_PATH), "\n";
 echo http_build_url("http://mike@www.example.com/foo/bar/", "../baz", HTTP_URL_STRIP_USER|HTTP_URL_JOIN_PATH), "\n";
 echo http_build_url("http://mike:1234@www.example.com/foo/bar/", "./../baz", HTTP_URL_STRIP_PASS|HTTP_URL_JOIN_PATH), "\n";
-echo http_build_url("http://www.example.com:8080/foo?a=b#frag", "?b=c", HTTP_URL_JOIN_QUERY|HTTP_URL_STRIP_PORT|HTTP_URL_STRIP_FRAGMENT|HTTP_URL_STRIP_PATH), "\n";
+echo http_build_url("http://www.example.com:8080/foo?a[0]=b#frag", "?a[0]=1&b=c&a[1]=b", HTTP_URL_JOIN_QUERY|HTTP_URL_STRIP_PORT|HTTP_URL_STRIP_FRAGMENT|HTTP_URL_STRIP_PATH), "\n";
 echo "Done\n";
 ?>
 --EXPECTF--
@@ -18,5 +18,5 @@ echo "Done\n";
 http://www.example.com/foo/baz
 http://www.example.com/foo/baz
 http://mike@www.example.com/foo/baz
-http://www.example.com/?a=b&b=c
+http://www.example.com/?a%5B0%5D=1&a%5B1%5D=b&b=c
 Done
\ No newline at end of file