back to dev
[m6w6/ext-http] / php_http_url.c
index d95eb5aeae969459ae4cf23ec7622d1524778781..7c8077b6a31995208a8a16da0ed6789d68bd2878 100644 (file)
@@ -6,7 +6,7 @@
     | modification, are permitted provided that the conditions mentioned |
     | in the accompanying LICENSE file are met.                          |
     +--------------------------------------------------------------------+
-    | Copyright (c) 2004-2013, Michael Wallner <mike@php.net>            |
+    | Copyright (c) 2004-2014, Michael Wallner <mike@php.net>            |
     +--------------------------------------------------------------------+
 */
 
@@ -42,94 +42,6 @@ static inline char *localhostname(void)
        return estrndup("localhost", lenof("localhost"));
 }
 
-static inline unsigned port(const char *scheme)
-{
-       unsigned port = 80;
-
-#if defined(ZTS) && defined(HAVE_GETSERVBYPORT_R)
-       int rc;
-       size_t len = 0xff;
-       char *buf = NULL;
-       struct servent *se_res = NULL, se_buf = {0};
-
-       do {
-               buf = erealloc(buf, len);
-               rc = getservbyname_r(scheme, "tcp", &se_buf, buf, len, &se_res);
-               len *= 2;
-       } while (rc == ERANGE && len <= 0xfff);
-
-       if (!rc) {
-               port = ntohs(se_res->s_port);
-       }
-
-       efree(buf);
-#elif !defined(ZTS) && defined(HAVE_GETSERVBYPORT)
-       struct servent *se;
-
-       if ((se = getservbyname(scheme, "tcp")) && se->s_port) {
-               port = ntohs(se->s_port);
-       }
-#endif
-
-       return port;
-}
-static inline char *scheme(unsigned port)
-{
-       char *scheme;
-#if defined(ZTS) && defined(HAVE_GETSERVBYPORT_R)
-       int rc;
-       size_t len = 0xff;
-       char *buf = NULL;
-       struct servent *se_res = NULL, se_buf = {0};
-#elif !defined(ZTS) && defined(HAVE_GETSERVBYPORT)
-       struct servent *se;
-#endif
-
-       switch (port) {
-       case 443:
-               scheme = estrndup("https", lenof("https"));
-               break;
-
-#if defined(ZTS) && !defined(HAVE_GETSERVBYPORT_R)
-       default:
-#elif !defined(ZTS) && !defined(HAVE_GETSERVBYPORT)
-       default:
-#endif
-       case 80:
-       case 0:
-               scheme = estrndup("http", lenof("http"));
-               break;
-
-#if defined(ZTS) && defined(HAVE_GETSERVBYPORT_R)
-       default:
-               do {
-                       buf = erealloc(buf, len);
-                       rc = getservbyport_r(htons(port), "tcp", &se_buf, buf, len, &se_res);
-                       len *= 2;
-               } while (rc == ERANGE && len <= 0xfff);
-
-               if (!rc && se_res) {
-                       scheme = estrdup(se_res->s_name);
-               } else {
-                       scheme = estrndup("http", lenof("http"));
-               }
-
-               efree(buf);
-               break;
-
-#elif !defined(ZTS) && defined(HAVE_GETSERVBYPORT)
-       default:
-               if ((se = getservbyport(htons(port), "tcp")) && se->s_name) {
-                       scheme = estrdup(se->s_name);
-               } else {
-                       scheme = estrndup("http", lenof("http"));
-               }
-               break;
-#endif
-       }
-       return scheme;
-}
-
 static php_url *php_http_url_from_env(php_url *url TSRMLS_DC)
 {
        zval *https, *zhost, *zport;
@@ -150,7 +62,7 @@ static php_url *php_http_url_from_env(php_url *url TSRMLS_DC)
        if (https && !strcasecmp(Z_STRVAL_P(https), "ON")) {
                url->scheme = estrndup("https", lenof("https"));
        } else {
-               url->scheme = scheme(url->port);
+               url->scheme = estrndup("http", lenof("http"));
        }
 
        /* host */
@@ -183,7 +95,7 @@ static php_url *php_http_url_from_env(php_url *url TSRMLS_DC)
        return url;
 }
 
-PHP_HTTP_API void php_http_url(int flags, const php_url *old_url, const php_url *new_url, php_url **url_ptr, char **url_str, size_t *url_len TSRMLS_DC)
+void php_http_url(int flags, const php_url *old_url, const php_url *new_url, php_url **url_ptr, char **url_str, size_t *url_len TSRMLS_DC)
 {
        php_url *url, *tmp_url = NULL;
 
@@ -339,7 +251,6 @@ PHP_HTTP_API void php_http_url(int flags, const php_url *old_url, const php_url
        if (url->port) {
                if (    ((url->port == 80) && !strcmp(url->scheme, "http"))
                        ||      ((url->port ==443) && !strcmp(url->scheme, "https"))
-                       ||      ( url->port == port(url->scheme))
                ) {
                        url->port = 0;
                }
@@ -356,7 +267,7 @@ PHP_HTTP_API void php_http_url(int flags, const php_url *old_url, const php_url
        }
 }
 
-PHP_HTTP_API STATUS php_http_url_encode_hash(HashTable *hash, const char *pre_encoded_str, size_t pre_encoded_len, char **encoded_str, size_t *encoded_len TSRMLS_DC)
+STATUS php_http_url_encode_hash(HashTable *hash, const char *pre_encoded_str, size_t pre_encoded_len, char **encoded_str, size_t *encoded_len TSRMLS_DC)
 {
        const char *arg_sep_str;
        size_t arg_sep_len;
@@ -375,7 +286,7 @@ PHP_HTTP_API STATUS php_http_url_encode_hash(HashTable *hash, const char *pre_en
        return SUCCESS;
 }
 
-PHP_HTTP_API STATUS php_http_url_encode_hash_ex(HashTable *hash, php_http_buffer_t *qstr, const char *arg_sep_str, size_t arg_sep_len, const char *val_sep_str, size_t val_sep_len, const char *pre_encoded_str, size_t pre_encoded_len TSRMLS_DC)
+STATUS php_http_url_encode_hash_ex(HashTable *hash, php_http_buffer_t *qstr, const char *arg_sep_str, size_t arg_sep_len, const char *val_sep_str, size_t val_sep_len, const char *pre_encoded_str, size_t pre_encoded_len TSRMLS_DC)
 {
        if (pre_encoded_len && pre_encoded_str) {
                php_http_buffer_append(qstr, pre_encoded_str, pre_encoded_len);
@@ -395,67 +306,70 @@ ZEND_BEGIN_ARG_INFO_EX(ai_HttpUrl___construct, 0, 0, 0)
 ZEND_END_ARG_INFO();
 PHP_METHOD(HttpUrl, __construct)
 {
-       with_error_handling(EH_THROW, php_http_exception_class_entry) {
-               zval *new_url = NULL, *old_url = NULL;
-               long flags = PHP_HTTP_URL_FROM_ENV;
-
-               if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!z!l", &old_url, &new_url, &flags)) {
-                       with_error_handling(EH_THROW, php_http_exception_class_entry) {
-                               php_url *res_purl, *new_purl = NULL, *old_purl = NULL;
-
-                               if (new_url) {
-                                       switch (Z_TYPE_P(new_url)) {
-                                               case IS_OBJECT:
-                                               case IS_ARRAY:
-                                                       new_purl = php_http_url_from_struct(NULL, HASH_OF(new_url) TSRMLS_CC);
-                                                       break;
-                                               default: {
-                                                       zval *cpy = php_http_ztyp(IS_STRING, new_url);
+       zval *new_url = NULL, *old_url = NULL;
+       long flags = PHP_HTTP_URL_FROM_ENV;
+       zend_error_handling zeh;
 
-                                                       new_purl = php_url_parse(Z_STRVAL_P(cpy));
-                                                       zval_ptr_dtor(&cpy);
-                                                       break;
-                                               }
-                                       }
-                                       if (!new_purl) {
-                                               return;
-                                       }
-                               }
-                               if (old_url) {
-                                       switch (Z_TYPE_P(old_url)) {
-                                               case IS_OBJECT:
-                                               case IS_ARRAY:
-                                                       old_purl = php_http_url_from_struct(NULL, HASH_OF(old_url) TSRMLS_CC);
-                                                       break;
-                                               default: {
-                                                       zval *cpy = php_http_ztyp(IS_STRING, old_url);
+       php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!z!l", &old_url, &new_url, &flags), invalid_arg, return);
 
-                                                       old_purl = php_url_parse(Z_STRVAL_P(cpy));
-                                                       zval_ptr_dtor(&cpy);
-                                                       break;
-                                               }
-                                       }
-                                       if (!old_purl) {
-                                               if (new_purl) {
-                                                       php_url_free(new_purl);
-                                               }
-                                               return;
-                                       }
-                               }
+       zend_replace_error_handling(EH_THROW, php_http_exception_bad_url_class_entry, &zeh TSRMLS_CC);
+       {
+               php_url *res_purl, *new_purl = NULL, *old_purl = NULL;
 
-                               php_http_url(flags, old_purl, new_purl, &res_purl, NULL, NULL TSRMLS_CC);
-                               php_http_url_to_struct(res_purl, getThis() TSRMLS_CC);
+               if (new_url) {
+                       switch (Z_TYPE_P(new_url)) {
+                               case IS_OBJECT:
+                               case IS_ARRAY:
+                                       new_purl = php_http_url_from_struct(NULL, HASH_OF(new_url) TSRMLS_CC);
+                                       break;
+                               default: {
+                                       zval *cpy = php_http_ztyp(IS_STRING, new_url);
 
-                               php_url_free(res_purl);
-                               if (old_purl) {
-                                       php_url_free(old_purl);
+                                       new_purl = php_url_parse(Z_STRVAL_P(cpy));
+                                       zval_ptr_dtor(&cpy);
+                                       break;
                                }
+                       }
+                       if (!new_purl) {
+                               zend_restore_error_handling(&zeh TSRMLS_CC);
+                               return;
+                       }
+               }
+               if (old_url) {
+                       switch (Z_TYPE_P(old_url)) {
+                               case IS_OBJECT:
+                               case IS_ARRAY:
+                                       old_purl = php_http_url_from_struct(NULL, HASH_OF(old_url) TSRMLS_CC);
+                                       break;
+                               default: {
+                                       zval *cpy = php_http_ztyp(IS_STRING, old_url);
+
+                                       old_purl = php_url_parse(Z_STRVAL_P(cpy));
+                                       zval_ptr_dtor(&cpy);
+                                       break;
+                               }
+                       }
+                       if (!old_purl) {
                                if (new_purl) {
                                        php_url_free(new_purl);
                                }
-                       } end_error_handling();
+                               zend_restore_error_handling(&zeh TSRMLS_CC);
+                               return;
+                       }
                }
-       } end_error_handling();
+
+               php_http_url(flags, old_purl, new_purl, &res_purl, NULL, NULL TSRMLS_CC);
+               php_http_url_to_struct(res_purl, getThis() TSRMLS_CC);
+
+               php_url_free(res_purl);
+               if (old_purl) {
+                       php_url_free(old_purl);
+               }
+               if (new_purl) {
+                       php_url_free(new_purl);
+               }
+       }
+       zend_restore_error_handling(&zeh TSRMLS_CC);
 }
 
 ZEND_BEGIN_ARG_INFO_EX(ai_HttpUrl_mod, 0, 0, 1)
@@ -466,8 +380,12 @@ PHP_METHOD(HttpUrl, mod)
 {
        zval *new_url = NULL;
        long flags = PHP_HTTP_URL_JOIN_PATH | PHP_HTTP_URL_JOIN_QUERY;
+       zend_error_handling zeh;
+
+       php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!|l", &new_url, &flags), invalid_arg, return);
 
-       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!|l", &new_url, &flags)) {
+       zend_replace_error_handling(EH_THROW, php_http_exception_bad_url_class_entry, &zeh TSRMLS_CC);
+       {
                php_url *new_purl = NULL, *old_purl = NULL;
 
                if (new_url) {
@@ -485,6 +403,7 @@ PHP_METHOD(HttpUrl, mod)
                                }
                        }
                        if (!new_purl) {
+                               zend_restore_error_handling(&zeh TSRMLS_CC);
                                return;
                        }
                }
@@ -504,6 +423,7 @@ PHP_METHOD(HttpUrl, mod)
                        php_url_free(new_purl);
                }
        }
+       zend_restore_error_handling(&zeh TSRMLS_CC);
 }
 
 ZEND_BEGIN_ARG_INFO_EX(ai_HttpUrl_toString, 0, 0, 0)
@@ -529,11 +449,16 @@ ZEND_BEGIN_ARG_INFO_EX(ai_HttpUrl_toArray, 0, 0, 0)
 ZEND_END_ARG_INFO();
 PHP_METHOD(HttpUrl, toArray)
 {
+       php_url *purl;
+
        if (SUCCESS != zend_parse_parameters_none()) {
-               RETURN_FALSE;
+               return;
        }
-       array_init(return_value);
-       array_copy(HASH_OF(getThis()), HASH_OF(return_value));
+
+       /* strip any non-URL properties */
+       purl = php_http_url_from_struct(NULL, HASH_OF(getThis()) TSRMLS_CC);
+       php_http_url_to_struct(purl, return_value TSRMLS_CC);
+       php_url_free(purl);
 }
 
 static zend_function_entry php_http_url_methods[] = {
@@ -552,7 +477,7 @@ PHP_MINIT_FUNCTION(http_url)
        zend_class_entry ce = {0};
 
        INIT_NS_CLASS_ENTRY(ce, "http", "Url", php_http_url_methods);
-       php_http_url_class_entry = zend_register_internal_class_ex(&ce, php_http_object_class_entry, NULL TSRMLS_CC);
+       php_http_url_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 
        zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("scheme"), ZEND_ACC_PUBLIC TSRMLS_CC);
        zend_declare_property_null(php_http_url_class_entry, ZEND_STRL("user"), ZEND_ACC_PUBLIC TSRMLS_CC);