- add HTTP_URL_STRIP_ALL constant
[m6w6/ext-http] / http_url_api.c
index cac64ec81ee880812cb10e186169363b50252855..827c7b6a2c5d6c1db62c459deb9af71ed7aaa011 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)
@@ -61,21 +62,28 @@ PHP_MINIT_FUNCTION(http_url)
        HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PATH", HTTP_URL_STRIP_PATH);
        HTTP_LONG_CONSTANT("HTTP_URL_STRIP_QUERY", HTTP_URL_STRIP_QUERY);
        HTTP_LONG_CONSTANT("HTTP_URL_STRIP_FRAGMENT", HTTP_URL_STRIP_FRAGMENT);
+       HTTP_LONG_CONSTANT("HTTP_URL_STRIP_ALL", HTTP_URL_STRIP_ALL);
        return SUCCESS;
 }
 
 PHP_HTTP_API char *_http_absolute_url(const char *url TSRMLS_DC)
 {
-       char *abs = estrdup(url);
-       php_url *purl = php_url_parse(abs);
+       char *abs = NULL;
+       php_url *purl = NULL;
        
-       STR_SET(abs, NULL);
+       if (url) {
+               purl = php_url_parse(abs = estrdup(url));
+               STR_SET(abs, NULL);
+               if (!purl) {
+                       http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", url);
+                       return NULL;
+               }
+       }
+       
+       http_build_url(0, purl, NULL, NULL, &abs, NULL);
        
        if (purl) {
-               http_build_url(0, purl, NULL, NULL, &abs, NULL);
                php_url_free(purl);
-       } else {
-               http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", url);
        }
        
        return abs;
@@ -125,10 +133,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);
                }
@@ -138,6 +157,10 @@ PHP_HTTP_API void _http_build_url(int flags, const php_url *old_url, const php_u
        }
        
        if (!url->scheme) {
+               zval *https = http_get_server_var("HTTPS");
+               if (https && !strcasecmp(Z_STRVAL_P(https), "ON")) {
+                       url->scheme = estrndup("https", lenof("https"));
+               } else
                switch (url->port)
                {
                        case 443:
@@ -175,7 +198,7 @@ PHP_HTTP_API void _http_build_url(int flags, const php_url *old_url, const php_u
        }
        
        if (!url->path) {
-               if (SG(request_info).request_uri && *SG(request_info).request_uri) {
+               if (SG(request_info).request_uri && SG(request_info).request_uri[0]) {
                        const char *q = strchr(SG(request_info).request_uri, '?');
                        
                        if (q) {
@@ -186,30 +209,23 @@ PHP_HTTP_API void _http_build_url(int flags, const php_url *old_url, const php_u
                } else {
                        url->path = estrndup("/", 1);
                }
-       } else if (*url->path != '/') {
-               if (SG(request_info).request_uri && *SG(request_info).request_uri) {
-                       const char *q = strchr(SG(request_info).request_uri, '?');
-                       char *uri, *path;
-                       size_t len;
-                       
-                       if (q) {
-                               uri = estrndup(SG(request_info).request_uri, len = q - SG(request_info).request_uri);
-                       } else {
-                               uri = estrndup(SG(request_info).request_uri, len = strlen(SG(request_info).request_uri));
-                       }
-                       
-                       php_dirname(uri, len);
-                       spprintf(&path, 0, "%s/%s", uri, url->path);
-                       efree(uri);
-                       STR_SET(url->path, path);
-               } else {
-                       char *uri;
-                       
-                       spprintf(&uri, 0, "/%s", url->path);
-                       STR_SET(url->path, uri);
+       } else if (url->path[0] != '/' && SG(request_info).request_uri && SG(request_info).request_uri[0]) {
+               size_t ulen = strlen(SG(request_info).request_uri);
+               size_t plen = strlen(url->path);
+               char *path;
+               
+               if (SG(request_info).request_uri[ulen-1] != '/') {
+                       for (--ulen; ulen && SG(request_info).request_uri[ulen - 1] != '/'; --ulen);
                }
+               
+               path = emalloc(ulen + plen + 1);
+               memcpy(path, SG(request_info).request_uri, ulen);
+               memcpy(path + ulen, url->path, plen);
+               path[ulen + plen] = '\0';
+               STR_SET(url->path, path);
        }
-       if (url->path) {
+       /* replace directory references if path is not a single slash */
+       if (url->path[0] && (url->path[0] != '/' || url->path[1])) {
                char *ptr, *end = url->path + strlen(url->path) + 1;
                        
                for (ptr = strstr(url->path, "/."); ptr; ptr = strstr(ptr, "/.")) {
@@ -385,14 +401,14 @@ PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, c
                        phpstr_init(&new_prefix);
                        if (prefix && prefix_len) {
                                phpstr_append(&new_prefix, prefix, prefix_len);
-                               phpstr_appends(&new_prefix, "[");
+                               phpstr_appends(&new_prefix, "%5B");
                        }
                        
                        phpstr_append(&new_prefix, encoded_key, encoded_len);
                        efree(encoded_key);
                        
                        if (prefix && prefix_len) {
-                               phpstr_appends(&new_prefix, "]");
+                               phpstr_appends(&new_prefix, "%5D");
                        }
                        phpstr_fix(&new_prefix);
                }