From d2c1e8d8bbc48ffddc33ac1cfc210a71eba2542f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 8 Jul 2025 20:44:44 +0200 Subject: [PATCH] Add internal URI handling API --- ext/filter/logical_filters.c | 65 ++++-- ext/filter/tests/062.phpt | 184 +++++++++++++++ ext/openssl/xp_ssl.c | 27 ++- ext/soap/php_http.c | 194 ++++++++------- ext/soap/php_http.h | 13 +- ext/soap/php_soap.h | 3 +- ext/soap/soap.c | 22 +- ext/soap/soap.stub.php | 2 +- ext/soap/soap_arginfo.h | 3 +- .../tests/SoapServer/__getLastResponse.phpt | 2 +- ext/soap/tests/any.phpt | 2 +- ext/soap/tests/bugs/bug28969.phpt | 2 +- ext/soap/tests/bugs/bug29795.phpt | 2 +- ext/soap/tests/bugs/bug29839.phpt | 2 +- ext/soap/tests/bugs/bug29844.phpt | 2 +- ext/soap/tests/bugs/bug30045.phpt | 2 +- ext/soap/tests/bugs/bug30106.phpt | 2 +- ext/soap/tests/bugs/bug30175.phpt | 2 +- ext/soap/tests/bugs/bug30928.phpt | 2 +- ext/soap/tests/bugs/bug31695.phpt | 2 +- ext/soap/tests/bugs/bug31755.phpt | 2 +- ext/soap/tests/bugs/bug32776.phpt | 2 +- ext/soap/tests/bugs/bug32941.phpt | 2 +- ext/soap/tests/bugs/bug34449.phpt | 2 +- ext/soap/tests/bugs/bug34453.phpt | 2 +- ext/soap/tests/bugs/bug34643.phpt | 2 +- ext/soap/tests/bugs/bug35142.phpt | 2 +- ext/soap/tests/bugs/bug35273.phpt | 2 +- ext/soap/tests/bugs/bug36226-2.phpt | 2 +- ext/soap/tests/bugs/bug36226.phpt | 2 +- ext/soap/tests/bugs/bug36999.phpt | 2 +- ext/soap/tests/bugs/bug37083.phpt | 2 +- ext/soap/tests/bugs/bug38004.phpt | 2 +- ext/soap/tests/bugs/bug38005.phpt | 2 +- ext/soap/tests/bugs/bug38055.phpt | 2 +- ext/soap/tests/bugs/bug38067.phpt | 2 +- ext/soap/tests/bugs/bug38536.phpt | 2 +- ext/soap/tests/bugs/bug39121.phpt | 2 +- ext/soap/tests/bugs/bug39815.phpt | 2 +- ext/soap/tests/bugs/bug42692.phpt | 2 +- ext/soap/tests/bugs/bug43045.phpt | 2 +- ext/soap/tests/bugs/bug44882.phpt | 2 +- ext/soap/tests/bugs/bug46419.phpt | 2 +- ext/soap/tests/bugs/bug47021.phpt | 4 +- ext/soap/tests/bugs/bug50675.phpt | 2 +- ext/soap/tests/bugs/bug50762.phpt | 2 +- ext/soap/tests/bugs/bug54911.phpt | 2 +- ext/soap/tests/bugs/bug55323.phpt | 2 +- ext/soap/tests/bugs/bug66049.phpt | 2 +- ext/soap/tests/bugs/bug69085.phpt | 2 +- ext/soap/tests/bugs/bug69668.phpt | 2 +- ext/soap/tests/bugs/bug70388.phpt | 2 +- ext/soap/tests/bugs/bug70875.phpt | 2 +- ext/soap/tests/bugs/bug71711.phpt | 2 +- ext/soap/tests/bugs/bug71996.phpt | 2 +- ext/soap/tests/bugs/bug73237.phpt | 2 +- ext/soap/tests/bugs/bug77141.phpt | 2 +- ext/soap/tests/bugs/bug77410.phpt | 2 +- .../tests/bugs/segfault_assertion_props.phpt | 2 +- ext/soap/tests/classmap002.phpt | 2 +- ext/soap/tests/classmap003.phpt | 2 +- ext/soap/tests/classmap004.phpt | 2 +- ext/soap/tests/classmap005.phpt | 2 +- ext/soap/tests/classmap006.phpt | 2 +- ext/soap/tests/classmap007.phpt | 2 +- ext/soap/tests/gh15711.phpt | 2 +- ext/soap/tests/gh16318.phpt | 2 +- ext/soap/tests/soap_qname_crash.phpt | 1 + ext/soap/tests/transport001.phpt | 2 +- ext/soap/tests/typemap003.phpt | 2 +- ext/soap/tests/typemap004.phpt | 2 +- ext/soap/tests/typemap007.phpt | 2 +- ext/soap/tests/typemap008.phpt | 2 +- ext/soap/tests/typemap011.phpt | 2 +- ext/soap/tests/typemap012.phpt | 2 +- ext/standard/basic_functions.c | 2 + ext/standard/url.c | 173 +++++++++++++- ext/standard/url.h | 2 + ext/uri/php_uri.c | 220 +++++++++++++++++- ext/uri/php_uri.h | 29 +++ ext/uri/php_uri_common.h | 1 + 81 files changed, 865 insertions(+), 208 deletions(-) create mode 100644 ext/filter/tests/062.phpt diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 0dd307122345c..10db36865a1a4 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -20,6 +20,7 @@ #include "filter_private.h" #include "ext/standard/url.h" #include "ext/pcre/php_pcre.h" +#include "ext/uri/php_uri.h" #include "zend_multiply.h" @@ -89,6 +90,8 @@ #define FORMAT_IPV4 4 #define FORMAT_IPV6 6 +#define URL_OPTION_URI_PARSER_CLASS "uri_parser_class" + static bool _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]); static bool php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) { /* {{{ */ @@ -591,7 +594,6 @@ static bool php_filter_is_valid_ipv6_hostname(const zend_string *s) void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { - php_url *url; size_t old_len = Z_STRLEN_P(value); php_filter_url(value, flags, option_array, charset); @@ -600,52 +602,69 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ RETURN_VALIDATION_FAILED } - /* Use parse_url - if it returns false, we return NULL */ - url = php_url_parse_ex(Z_STRVAL_P(value), Z_STRLEN_P(value)); + /* Parse options */ + zval *option_val; + zend_string *parser_name; + int parser_name_set; + FETCH_STR_OPTION(parser_name, URL_OPTION_URI_PARSER_CLASS); + + uri_handler_t *uri_handler = php_uri_get_handler(parser_name_set ? parser_name : NULL); + if (uri_handler == NULL) { + zend_throw_error(NULL, "Invalid URI parser used"); + RETURN_VALIDATION_FAILED + } - if (url == NULL) { + /* Parse the URI - if it fails, we return NULL */ + php_uri *uri = php_uri_parse_to_struct(uri_handler, Z_STR_P(value), URI_COMPONENT_READ_NORMALIZED_ASCII, true); + if (uri == NULL) { RETURN_VALIDATION_FAILED } - if (url->scheme != NULL && - (zend_string_equals_literal_ci(url->scheme, "http") || zend_string_equals_literal_ci(url->scheme, "https"))) { + if (uri->scheme != NULL && + (zend_string_equals_literal_ci(uri->scheme, "http") || zend_string_equals_literal_ci(uri->scheme, "https"))) { - if (url->host == NULL) { - goto bad_url; + if (uri->host == NULL) { + php_uri_struct_free(uri); + RETURN_VALIDATION_FAILED } if ( + /* @todo Find a better solution than hardcoding the uri handler name. Skipping these checks is needed because + * both uriparser and lexbor performs comprehensive validations. Also, the [] pair is removed by these + * libraries in case of ipv6 URIs, therefore php_filter_is_valid_ipv6_hostname() would case false positive + * failures. */ + strcmp(uri_handler->name, URI_PARSER_PHP) == 0 && /* An IPv6 enclosed by square brackets is a valid hostname.*/ - !php_filter_is_valid_ipv6_hostname(url->host) && + !php_filter_is_valid_ipv6_hostname(uri->host) && /* Validate domain. * This includes a loose check for an IPv4 address. */ - !php_filter_validate_domain_ex(url->host, FILTER_FLAG_HOSTNAME) + !php_filter_validate_domain_ex(uri->host, FILTER_FLAG_HOSTNAME) ) { - php_url_free(url); + php_uri_struct_free(uri); RETURN_VALIDATION_FAILED } } - if ( - url->scheme == NULL || - /* some schemas allow the host to be empty */ - (url->host == NULL && (!zend_string_equals_literal(url->scheme, "mailto") && !zend_string_equals_literal(url->scheme, "news") && !zend_string_equals_literal(url->scheme, "file"))) || - ((flags & FILTER_FLAG_PATH_REQUIRED) && url->path == NULL) || ((flags & FILTER_FLAG_QUERY_REQUIRED) && url->query == NULL) + if (uri->scheme == NULL || + /* some schemes allow the host to be empty */ + (uri->host == NULL && (!zend_string_equals_literal(uri->scheme, "mailto") && !zend_string_equals_literal(uri->scheme, "news") && !zend_string_equals_literal(uri->scheme, "file"))) || + ((flags & FILTER_FLAG_PATH_REQUIRED) && uri->path == NULL) || ((flags & FILTER_FLAG_QUERY_REQUIRED) && uri->query == NULL) ) { -bad_url: - php_url_free(url); + php_uri_struct_free(uri); RETURN_VALIDATION_FAILED } - if ((url->user != NULL && !is_userinfo_valid(url->user)) - || (url->pass != NULL && !is_userinfo_valid(url->pass)) + if (strcmp(uri_handler->name, "parse_url") == 0 && + ( + (uri->user != NULL && !is_userinfo_valid(uri->user)) || + (uri->password != NULL && !is_userinfo_valid(uri->password)) + ) ) { - php_url_free(url); + php_uri_struct_free(uri); RETURN_VALIDATION_FAILED - } - php_url_free(url); + php_uri_struct_free(uri); } /* }}} */ diff --git a/ext/filter/tests/062.phpt b/ext/filter/tests/062.phpt new file mode 100644 index 0000000000000..905bee62f857d --- /dev/null +++ b/ext/filter/tests/062.phpt @@ -0,0 +1,184 @@ +--TEST-- +filter_var() and FILTER_VALIDATE_URL with different URI parsers +--EXTENSIONS-- +filter +--FILE-- + $parserName])); + } + + var_dump(filter_var("qwe", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName])); + var_dump(filter_var("http://qwe", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName])); + var_dump(filter_var("http://", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName])); + var_dump(filter_var("/tmp/test", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName])); + var_dump(filter_var("http://www.example.com", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName])); + var_dump(filter_var("http://www.example.com", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName, "flags" => FILTER_FLAG_PATH_REQUIRED])); + var_dump(filter_var("http://www.example.com/path/at/the/server/", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName, "flags" => FILTER_FLAG_PATH_REQUIRED])); + var_dump(filter_var("http://www.example.com/index.html", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName, "flags" => FILTER_FLAG_QUERY_REQUIRED])); + var_dump(filter_var("http://www.example.com/index.php?a=b&c=d", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName, "flags" => FILTER_FLAG_QUERY_REQUIRED])); +} + +echo "RFC3986:\n"; +validateUrls(Uri\Rfc3986Uri::class); + +echo "\nWHATWG:\n"; +validateUrls(Uri\WhatWgUri::class); + +echo "Done\n"; +?> +--EXPECT-- +RFC3986: +string(29) "http://example.com/index.html" +string(32) "http://www.example.com/index.php" +string(31) "http://www.example/img/test.png" +string(27) "http://www.example/img/dir/" +string(26) "http://www.example/img/dir" +string(79) "http://www.thelongestdomainnameintheworldandthensomeandthensomemoreandmore.com/" +string(81) "http://toolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolong.com" +string(261) "http://eauBcFReEmjLcoZwI0RuONNnwU4H9r151juCaqTI5VeIP5jcYIqhx1lh5vV00l2rTs6y7hOp7rYw42QZiq6VIzjcYrRm8gFRMk9U9Wi1grL8Mr5kLVloYLthHgyA94QK3SaXCATklxgo6XvcbXIqAGG7U0KxTr8hJJU1p2ZQ2mXHmp4DhYP8N9SRuEKzaCPcSIcW7uj21jZqBigsLsNAXEzU8SPXZjmVQVtwQATPWeWyGW4GuJhjP4Q8o0.com" +string(261) "http://kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.CQ1oT5Uq3jJt6Uhy3VH9u3Gi5YhfZCvZVKgLlaXNFhVKB1zJxvunR7SJa.com." +string(83) "http://kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58R.example.com" +string(48) "http://[2001:0db8:0000:85a3:0000:0000:ac1f:8001]" +string(50) "http://[2001:db8:0:85a3:0:0:ac1f:8001]:123/me.html" +string(36) "http://[2001:db8:0:85a3::ac1f:8001]/" +string(12) "http://[::1]" +string(31) "http://cont-ains.h-yph-en-s.com" +string(12) "http://..com" +string(16) "http://a.-bc.com" +string(17) "http://ab.cd-.com" +string(16) "http://-.abc.com" +string(20) "http://abc.-.abc.com" +string(30) "http://underscore_.example.com" +bool(false) +bool(false) +string(18) "file:///tmp/test.c" +string(26) "ftp://ftp.example.com/tmp/" +bool(false) +bool(false) +string(7) "http://" +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +string(18) "mailto:foo@bar.com" +string(17) "news:news.php.net" +string(14) "file://foo/bar" +bool(false) +bool(false) +bool(false) +string(24) "http://example.com:65536" +string(24) "http://example.com:65537" +bool(false) +string(10) "http://qwe" +string(7) "http://" +bool(false) +string(22) "http://www.example.com" +bool(false) +string(42) "http://www.example.com/path/at/the/server/" +bool(false) +string(40) "http://www.example.com/index.php?a=b&c=d" + +WHATWG: +string(29) "http://example.com/index.html" +string(32) "http://www.example.com/index.php" +string(31) "http://www.example/img/test.png" +string(27) "http://www.example/img/dir/" +string(26) "http://www.example/img/dir" +string(79) "http://www.thelongestdomainnameintheworldandthensomeandthensomemoreandmore.com/" +string(81) "http://toolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolong.com" +string(261) "http://eauBcFReEmjLcoZwI0RuONNnwU4H9r151juCaqTI5VeIP5jcYIqhx1lh5vV00l2rTs6y7hOp7rYw42QZiq6VIzjcYrRm8gFRMk9U9Wi1grL8Mr5kLVloYLthHgyA94QK3SaXCATklxgo6XvcbXIqAGG7U0KxTr8hJJU1p2ZQ2mXHmp4DhYP8N9SRuEKzaCPcSIcW7uj21jZqBigsLsNAXEzU8SPXZjmVQVtwQATPWeWyGW4GuJhjP4Q8o0.com" +string(261) "http://kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.CQ1oT5Uq3jJt6Uhy3VH9u3Gi5YhfZCvZVKgLlaXNFhVKB1zJxvunR7SJa.com." +string(83) "http://kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58R.example.com" +string(48) "http://[2001:0db8:0000:85a3:0000:0000:ac1f:8001]" +string(50) "http://[2001:db8:0:85a3:0:0:ac1f:8001]:123/me.html" +string(36) "http://[2001:db8:0:85a3::ac1f:8001]/" +string(12) "http://[::1]" +string(31) "http://cont-ains.h-yph-en-s.com" +string(12) "http://..com" +string(16) "http://a.-bc.com" +string(17) "http://ab.cd-.com" +string(16) "http://-.abc.com" +string(20) "http://abc.-.abc.com" +string(30) "http://underscore_.example.com" +bool(false) +string(17) "http:/www.example" +string(18) "file:///tmp/test.c" +string(26) "ftp://ftp.example.com/tmp/" +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +string(18) "mailto:foo@bar.com" +string(17) "news:news.php.net" +string(14) "file://foo/bar" +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +string(10) "http://qwe" +bool(false) +bool(false) +string(22) "http://www.example.com" +bool(false) +string(42) "http://www.example.com/path/at/the/server/" +bool(false) +string(40) "http://www.example.com/index.php?a=b&c=d" +Done diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index e728f647a3528..786406693291c 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -24,6 +24,7 @@ #include "php.h" #include "ext/standard/file.h" #include "ext/standard/url.h" +#include "ext/uri/php_uri.h" #include "streams/php_streams_int.h" #include "zend_smart_str.h" #include "php_openssl.h" @@ -2612,21 +2613,25 @@ static zend_long php_openssl_get_crypto_method( static char *php_openssl_get_url_name(const char *resourcename, size_t resourcenamelen, int is_persistent) /* {{{ */ { - php_url *url; - if (!resourcename) { return NULL; } - url = php_url_parse_ex(resourcename, resourcenamelen); - if (!url) { + uri_handler_t *uri_handler = php_uri_get_handler(NULL); + + zend_string *resource = zend_string_init(resourcename, resourcenamelen, false); + uri_internal_t *internal_uri = php_uri_parse(uri_handler, resource, NULL); + if (internal_uri == NULL) { + zend_string_release(resource); return NULL; } - if (url->host) { - const char * host = ZSTR_VAL(url->host); + zval host_zv; + zend_result result = php_uri_get_host(internal_uri, URI_COMPONENT_READ_RAW, &host_zv); + if (result == SUCCESS && Z_TYPE(host_zv) == IS_STRING) { + const char * host = Z_STRVAL(host_zv); char * url_name = NULL; - size_t len = ZSTR_LEN(url->host); + size_t len = Z_STRLEN(host_zv); /* skip trailing dots */ while (len && host[len-1] == '.') { @@ -2637,11 +2642,15 @@ static char *php_openssl_get_url_name(const char *resourcename, url_name = pestrndup(host, len, is_persistent); } - php_url_free(url); + zend_string_release(resource); + php_uri_free(internal_uri); + zval_ptr_dtor(&host_zv); return url_name; } - php_url_free(url); + zend_string_release(resource); + php_uri_free(internal_uri); + zval_ptr_dtor(&host_zv); return NULL; } /* }}} */ diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 2d6ed207efbdd..31f7eb8865992 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -18,6 +18,7 @@ #include "php_soap.h" #include "ext/hash/php_hash.h" /* For php_hash_bin2hex() */ +#include "ext/uri/php_uri.h" static char *get_http_header_value_nodup(char *headers, char *type, size_t *len); static char *get_http_header_value(char *headers, char *type); @@ -162,7 +163,7 @@ void http_context_headers(php_stream_context* context, } } -static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, php_stream_context *context, int *use_proxy) +static php_stream* http_connect(zval* this_ptr, php_uri *uri, int use_ssl, php_stream_context *context, int *use_proxy) { php_stream *stream; zval *tmp, ssl_proxy_peer_name; @@ -182,8 +183,8 @@ static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, ph port = Z_LVAL_P(proxy_port); *use_proxy = 1; } else { - host = ZSTR_VAL(phpurl->host); - port = phpurl->port; + host = ZSTR_VAL(uri->host); + port = uri->port; } tmp = Z_CLIENT_CONNECTION_TIMEOUT_P(this_ptr); @@ -247,21 +248,21 @@ static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, ph /* Set peer_name or name verification will try to use the proxy server name */ if (!context || (tmp = php_stream_context_get_option(context, "ssl", "peer_name")) == NULL) { - ZVAL_STR_COPY(&ssl_proxy_peer_name, phpurl->host); + ZVAL_STR_COPY(&ssl_proxy_peer_name, uri->host); php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_name", &ssl_proxy_peer_name); zval_ptr_dtor(&ssl_proxy_peer_name); } smart_str_append_const(&soap_headers, "CONNECT "); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->host)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->host)); smart_str_appendc(&soap_headers, ':'); - smart_str_append_unsigned(&soap_headers, phpurl->port); + smart_str_append_unsigned(&soap_headers, uri->port); smart_str_append_const(&soap_headers, " HTTP/1.1\r\n"); smart_str_append_const(&soap_headers, "Host: "); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->host)); - if (phpurl->port != 80) { + smart_str_appends(&soap_headers, ZSTR_VAL(uri->host)); + if (uri->port != 80) { smart_str_appendc(&soap_headers, ':'); - smart_str_append_unsigned(&soap_headers, phpurl->port); + smart_str_append_unsigned(&soap_headers, uri->port); } smart_str_append_const(&soap_headers, "\r\n"); proxy_authentication(this_ptr, &soap_headers); @@ -335,18 +336,19 @@ static bool in_domain(const zend_string *host, const zend_string *domain) } } -int make_http_soap_request(zval *this_ptr, - zend_string *buf, - char *location, - char *soapaction, - int soap_version, - zval *return_value) +int make_http_soap_request(zval *this_ptr, + zend_string *buf, + zend_string *location, + char *soapaction, + int soap_version, + const zend_string *uri_parser_class, + zval *return_value) { zend_string *request; smart_str soap_headers = {0}; smart_str soap_headers_z = {0}; size_t err; - php_url *phpurl = NULL; + php_uri *uri = NULL; php_stream *stream; zval *tmp; int use_proxy = 0; @@ -432,8 +434,13 @@ int make_http_soap_request(zval *this_ptr, stream = NULL; } - if (location != NULL && location[0] != '\000') { - phpurl = php_url_parse(location); + if (location != NULL && ZSTR_VAL(location)[0] != '\000') { + uri_handler_t *uri_handler = php_uri_get_handler(uri_parser_class); + if (uri_handler == NULL) { + zend_argument_value_error(6, "must be a valid URI parser name"); + return FALSE; + } + uri = php_uri_parse_to_struct(uri_handler, location, URI_COMPONENT_READ_NORMALIZED_ASCII, true); } tmp = Z_CLIENT_STREAM_CONTEXT_P(this_ptr); @@ -450,8 +457,10 @@ int make_http_soap_request(zval *this_ptr, } try_again: - if (phpurl == NULL || phpurl->host == NULL) { - if (phpurl != NULL) {php_url_free(phpurl);} + if (uri == NULL || uri->host == NULL) { + if (uri != NULL) { + php_uri_struct_free(uri); + } if (request != buf) { zend_string_release_ex(request, 0); } @@ -462,10 +471,10 @@ int make_http_soap_request(zval *this_ptr, } use_ssl = 0; - if (phpurl->scheme != NULL && zend_string_equals_literal(phpurl->scheme, "https")) { + if (uri->scheme != NULL && zend_string_equals_literal(uri->scheme, "https")) { use_ssl = 1; - } else if (phpurl->scheme == NULL || !zend_string_equals_literal(phpurl->scheme, "http")) { - php_url_free(phpurl); + } else if (uri->scheme == NULL || !zend_string_equals_literal(uri->scheme, "http")) { + php_uri_struct_free(uri); if (request != buf) { zend_string_release_ex(request, 0); } @@ -478,7 +487,7 @@ int make_http_soap_request(zval *this_ptr, old_allow_url_fopen = PG(allow_url_fopen); PG(allow_url_fopen) = 1; if (use_ssl && php_stream_locate_url_wrapper("https://", NULL, STREAM_LOCATE_WRAPPERS_ONLY) == NULL) { - php_url_free(phpurl); + php_uri_struct_free(uri); if (request != buf) { zend_string_release_ex(request, 0); } @@ -489,22 +498,22 @@ int make_http_soap_request(zval *this_ptr, return FALSE; } - if (phpurl->port == 0) { - phpurl->port = use_ssl ? 443 : 80; + if (uri->port == 0) { + uri->port = use_ssl ? 443 : 80; } /* Check if request to the same host */ if (stream != NULL) { - php_url *orig; + php_uri *orig; tmp = Z_CLIENT_HTTPURL_P(this_ptr); if (Z_TYPE_P(tmp) == IS_OBJECT && instanceof_function(Z_OBJCE_P(tmp), soap_url_class_entry) && - (orig = Z_SOAP_URL_P(tmp)->url) != NULL && + (orig = Z_SOAP_URL_P(tmp)->uri) != NULL && ((use_proxy && !use_ssl) || (((use_ssl && orig->scheme != NULL && zend_string_equals_literal(orig->scheme, "https")) || (!use_ssl && orig->scheme == NULL) || (!use_ssl && !zend_string_equals_literal(orig->scheme, "https"))) && - zend_string_equals(orig->host, phpurl->host) && - orig->port == phpurl->port))) { + zend_string_equals(orig->host, uri->host) && + orig->port == uri->port))) { } else { ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr)); php_stream_close(stream); @@ -526,12 +535,12 @@ int make_http_soap_request(zval *this_ptr, } if (!stream) { - stream = http_connect(this_ptr, phpurl, use_ssl, context, &use_proxy); + stream = http_connect(this_ptr, uri, use_ssl, context, &use_proxy); if (stream) { php_stream_to_zval(stream, Z_CLIENT_HTTPSOCKET_P(this_ptr)); ZVAL_LONG(Z_CLIENT_USE_PROXY_P(this_ptr), use_proxy); } else { - php_url_free(phpurl); + php_uri_struct_free(uri); if (request != buf) { zend_string_release_ex(request, 0); } @@ -556,7 +565,7 @@ int make_http_soap_request(zval *this_ptr, object_init_ex(url_zval, soap_url_class_entry); soap_url_object *url_obj = Z_SOAP_URL_P(url_zval); - url_obj->url = phpurl; + url_obj->uri = uri; if (context && (tmp = php_stream_context_get_option(context, "http", "protocol_version")) != NULL && @@ -569,24 +578,24 @@ int make_http_soap_request(zval *this_ptr, smart_str_append_const(&soap_headers, "POST "); if (use_proxy && !use_ssl) { - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->scheme)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->scheme)); smart_str_append_const(&soap_headers, "://"); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->host)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->host)); smart_str_appendc(&soap_headers, ':'); - smart_str_append_unsigned(&soap_headers, phpurl->port); + smart_str_append_unsigned(&soap_headers, uri->port); } - if (phpurl->path) { - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->path)); + if (uri->path) { + smart_str_appends(&soap_headers, ZSTR_VAL(uri->path)); } else { smart_str_appendc(&soap_headers, '/'); } - if (phpurl->query) { + if (uri->query) { smart_str_appendc(&soap_headers, '?'); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->query)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->query)); } - if (phpurl->fragment) { + if (uri->fragment) { smart_str_appendc(&soap_headers, '#'); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->fragment)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->fragment)); } if (http_1_1) { smart_str_append_const(&soap_headers, " HTTP/1.1\r\n"); @@ -594,10 +603,10 @@ int make_http_soap_request(zval *this_ptr, smart_str_append_const(&soap_headers, " HTTP/1.0\r\n"); } smart_str_append_const(&soap_headers, "Host: "); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->host)); - if (phpurl->port != (use_ssl?443:80)) { + smart_str_appends(&soap_headers, ZSTR_VAL(uri->host)); + if (uri->port != (use_ssl?443:80)) { smart_str_appendc(&soap_headers, ':'); - smart_str_append_unsigned(&soap_headers, phpurl->port); + smart_str_append_unsigned(&soap_headers, uri->port); } if (!http_1_1 || Z_TYPE_P(Z_CLIENT_KEEP_ALIVE_P(this_ptr)) == IS_FALSE) { smart_str_append_const(&soap_headers, "\r\n" @@ -739,14 +748,14 @@ int make_http_soap_request(zval *this_ptr, PHP_MD5Init(&md5ctx); PHP_MD5Update(&md5ctx, (unsigned char*)"POST:", sizeof("POST:")-1); - if (phpurl->path) { - PHP_MD5Update(&md5ctx, (unsigned char*)ZSTR_VAL(phpurl->path), ZSTR_LEN(phpurl->path)); + if (uri->path) { + PHP_MD5Update(&md5ctx, (unsigned char*)ZSTR_VAL(uri->path), ZSTR_LEN(uri->path)); } else { PHP_MD5Update(&md5ctx, (unsigned char*)"/", 1); } - if (phpurl->query) { + if (uri->query) { PHP_MD5Update(&md5ctx, (unsigned char*)"?", 1); - PHP_MD5Update(&md5ctx, (unsigned char*)ZSTR_VAL(phpurl->query), ZSTR_LEN(phpurl->query)); + PHP_MD5Update(&md5ctx, (unsigned char*)ZSTR_VAL(uri->query), ZSTR_LEN(uri->query)); } PHP_MD5Final(hash, &md5ctx); @@ -787,18 +796,18 @@ int make_http_soap_request(zval *this_ptr, smart_str_appendl(&soap_headers, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); } smart_str_append_const(&soap_headers, "\", uri=\""); - if (phpurl->path) { - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->path)); + if (uri->path) { + smart_str_appends(&soap_headers, ZSTR_VAL(uri->path)); } else { smart_str_appendc(&soap_headers, '/'); } - if (phpurl->query) { + if (uri->query) { smart_str_appendc(&soap_headers, '?'); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->query)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->query)); } - if (phpurl->fragment) { + if (uri->fragment) { smart_str_appendc(&soap_headers, '#'); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->fragment)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->fragment)); } if ((tmp = zend_hash_str_find(Z_ARRVAL_P(digest), "qop", sizeof("qop")-1)) != NULL && Z_TYPE_P(tmp) == IS_STRING) { @@ -865,10 +874,10 @@ int make_http_soap_request(zval *this_ptr, zval *tmp; if (((tmp = zend_hash_index_find(Z_ARRVAL_P(data), 1)) == NULL || Z_TYPE_P(tmp) != IS_STRING || - strncmp(phpurl->path?ZSTR_VAL(phpurl->path):"/",Z_STRVAL_P(tmp),Z_STRLEN_P(tmp)) == 0) && + strncmp(uri->path?ZSTR_VAL(uri->path):"/",Z_STRVAL_P(tmp),Z_STRLEN_P(tmp)) == 0) && ((tmp = zend_hash_index_find(Z_ARRVAL_P(data), 2)) == NULL || Z_TYPE_P(tmp) != IS_STRING || - in_domain(phpurl->host, Z_STR_P(tmp))) && + in_domain(uri->host, Z_STR_P(tmp))) && (use_ssl || (tmp = zend_hash_index_find(Z_ARRVAL_P(data), 3)) == NULL)) { if (!first_cookie) { smart_str_appends(&soap_headers, "; "); @@ -1047,15 +1056,15 @@ int make_http_soap_request(zval *this_ptr, } } if (!zend_hash_index_exists(Z_ARRVAL(zcookie), 1)) { - char *t = phpurl->path?ZSTR_VAL(phpurl->path):"/"; + char *t = uri->path?ZSTR_VAL(uri->path):"/"; char *c = strrchr(t, '/'); if (c) { add_index_stringl(&zcookie, 1, t, c-t); } } if (!zend_hash_index_exists(Z_ARRVAL(zcookie), 2)) { - add_index_str(&zcookie, 2, phpurl->host); - GC_ADDREF(phpurl->host); + add_index_str(&zcookie, 2, uri->host); + GC_ADDREF(uri->host); } zend_symtable_update(Z_ARRVAL_P(cookies), name.s, &zcookie); @@ -1143,39 +1152,48 @@ int make_http_soap_request(zval *this_ptr, char *loc; if ((loc = get_http_header_value(ZSTR_VAL(http_headers), "Location:")) != NULL) { - php_url *new_url = php_url_parse(loc); + uri_handler_t *uri_handler = php_uri_get_handler(uri_parser_class); + if (uri_handler == NULL) { + zend_argument_value_error(6, "must be a valid URI parser name"); + return FALSE; + } + + zend_string *loc_str = zend_string_init(loc, strlen(loc), false); + php_uri *new_uri = php_uri_parse_to_struct(uri_handler, loc_str, URI_COMPONENT_READ_NORMALIZED_ASCII, true); + zend_string_release(loc_str); - if (new_url != NULL) { + if (new_uri != NULL) { zend_string_release_ex(http_headers, 0); zend_string_release_ex(http_body, 0); efree(loc); - if (new_url->scheme == NULL && new_url->path != NULL) { - new_url->scheme = phpurl->scheme ? zend_string_copy(phpurl->scheme) : NULL; - new_url->host = phpurl->host ? zend_string_copy(phpurl->host) : NULL; - new_url->port = phpurl->port; - if (new_url->path && ZSTR_VAL(new_url->path)[0] != '/') { - if (phpurl->path) { - char *t = ZSTR_VAL(phpurl->path); + + if (new_uri->scheme == NULL && new_uri->path != NULL) { + new_uri->scheme = uri->scheme ? zend_string_copy(uri->scheme) : NULL; + new_uri->host = uri->host ? zend_string_copy(uri->host) : NULL; + new_uri->port = uri->port; + if (new_uri->path != NULL && ZSTR_VAL(new_uri->path)[0] != '/') { // TODO new API doesn't return '/' as first char + if (new_uri->path != NULL) { + char *t = ZSTR_VAL(new_uri->path); char *p = strrchr(t, '/'); if (p) { - zend_string *s = zend_string_alloc((p - t) + ZSTR_LEN(new_url->path) + 2, 0); + zend_string *s = zend_string_alloc((p - t) + ZSTR_LEN(new_uri->path) + 2, 0); strncpy(ZSTR_VAL(s), t, (p - t) + 1); ZSTR_VAL(s)[(p - t) + 1] = 0; - strcat(ZSTR_VAL(s), ZSTR_VAL(new_url->path)); - zend_string_release_ex(new_url->path, 0); - new_url->path = s; + strcat(ZSTR_VAL(s), ZSTR_VAL(new_uri->path)); + zend_string_release_ex(new_uri->path, 0); + new_uri->path = s; } } else { - zend_string *s = zend_string_alloc(ZSTR_LEN(new_url->path) + 2, 0); + zend_string *s = zend_string_alloc(ZSTR_LEN(new_uri->path) + 2, 0); ZSTR_VAL(s)[0] = '/'; ZSTR_VAL(s)[1] = 0; - strcat(ZSTR_VAL(s), ZSTR_VAL(new_url->path)); - zend_string_release_ex(new_url->path, 0); - new_url->path = s; + strcat(ZSTR_VAL(s), ZSTR_VAL(new_uri->path)); + zend_string_release_ex(new_uri->path, 0); + new_uri->path = s; } } } - phpurl = new_url; + uri = new_uri; if (--redirect_max < 1) { add_soap_fault(this_ptr, "HTTP", "Redirection limit reached, aborting", NULL, NULL, SOAP_GLOBAL(lang_en)); @@ -1235,20 +1253,20 @@ int make_http_soap_request(zval *this_ptr, } if (Z_TYPE(digest) != IS_UNDEF) { - php_url *new_url = emalloc(sizeof(php_url)); + php_uri *new_uri = emalloc(sizeof(php_uri)); zval_ptr_dtor(Z_CLIENT_DIGEST_P(this_ptr)); ZVAL_COPY_VALUE(Z_CLIENT_DIGEST_P(this_ptr), &digest); - *new_url = *phpurl; - if (phpurl->scheme) phpurl->scheme = zend_string_copy(phpurl->scheme); - if (phpurl->user) phpurl->user = zend_string_copy(phpurl->user); - if (phpurl->pass) phpurl->pass = zend_string_copy(phpurl->pass); - if (phpurl->host) phpurl->host = zend_string_copy(phpurl->host); - if (phpurl->path) phpurl->path = zend_string_copy(phpurl->path); - if (phpurl->query) phpurl->query = zend_string_copy(phpurl->query); - if (phpurl->fragment) phpurl->fragment = zend_string_copy(phpurl->fragment); - phpurl = new_url; + *new_uri = *uri; + if (uri->scheme) uri->scheme = zend_string_copy(uri->scheme); + if (uri->user) uri->user = zend_string_copy(uri->user); + if (uri->password) uri->password = zend_string_copy(uri->password); + if (uri->host) uri->host = zend_string_copy(uri->host); + if (uri->path) uri->path = zend_string_copy(uri->path); + if (uri->query) uri->query = zend_string_copy(uri->query); + if (uri->fragment) uri->fragment = zend_string_copy(uri->fragment); + uri = new_uri; efree(auth); zend_string_release_ex(http_headers, 0); diff --git a/ext/soap/php_http.h b/ext/soap/php_http.h index df24c0d26fa84..bb35d1ca3fbb0 100644 --- a/ext/soap/php_http.h +++ b/ext/soap/php_http.h @@ -19,12 +19,13 @@ #ifndef PHP_HTTP_H #define PHP_HTTP_H -int make_http_soap_request(zval *this_ptr, - zend_string *request, - char *location, - char *soapaction, - int soap_version, - zval *response); +int make_http_soap_request(zval *this_ptr, + zend_string *request, + zend_string *location, + char *soapaction, + int soap_version, + const zend_string *uri_parser_class, + zval *response); int proxy_authentication(zval* this_ptr, smart_str* soap_headers); int basic_authentication(zval* this_ptr, smart_str* soap_headers); diff --git a/ext/soap/php_soap.h b/ext/soap/php_soap.h index 1eea30c62e905..48f8fb50591cb 100644 --- a/ext/soap/php_soap.h +++ b/ext/soap/php_soap.h @@ -27,6 +27,7 @@ #include "zend_smart_str.h" #include "php_ini.h" #include "SAPI.h" +#include "ext/uri/php_uri.h" #include #include @@ -255,7 +256,7 @@ static zend_always_inline zval *php_soap_deref(zval *zv) { #define Z_CLIENT_LAST_RESPONSE_HEADERS_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 35) typedef struct soap_url_object { - php_url *url; + php_uri *uri; zend_object std; } soap_url_object; diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 0786ac811059e..d061f6ae925e0 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -233,9 +233,9 @@ static void soap_url_object_free(zend_object *obj) { soap_url_object *url_obj = soap_url_object_fetch(obj); - if (url_obj->url) { - php_url_free(url_obj->url); - url_obj->url = NULL; + if (url_obj->uri) { + php_uri_struct_free(url_obj->uri); + url_obj->uri = NULL; } zend_object_std_dtor(&url_obj->std); @@ -2783,28 +2783,28 @@ PHP_METHOD(SoapClient, __getLastResponseHeaders) /* {{{ SoapClient::__doRequest() */ PHP_METHOD(SoapClient, __doRequest) { - zend_string *buf; - char *location, *action; - size_t location_size, action_size; + zend_string *buf, *location, *uri_parser_class = NULL; + char *action; + size_t action_size; zend_long version; bool one_way = 0; zval *this_ptr = ZEND_THIS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sssl|b", + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSsl|bS!", &buf, - &location, &location_size, + &location, &action, &action_size, - &version, &one_way) == FAILURE) { + &version, &one_way, &uri_parser_class) == FAILURE) { RETURN_THROWS(); } if (SOAP_GLOBAL(features) & SOAP_WAIT_ONE_WAY_CALLS) { one_way = 0; } if (one_way) { - if (make_http_soap_request(this_ptr, buf, location, action, version, NULL)) { + if (make_http_soap_request(this_ptr, buf, location, action, version, uri_parser_class, NULL)) { RETURN_EMPTY_STRING(); } - } else if (make_http_soap_request(this_ptr, buf, location, action, version, + } else if (make_http_soap_request(this_ptr, buf, location, action, version, uri_parser_class, return_value)) { return; } diff --git a/ext/soap/soap.stub.php b/ext/soap/soap.stub.php index 15d4ef1e6bd3e..851b32042bd19 100644 --- a/ext/soap/soap.stub.php +++ b/ext/soap/soap.stub.php @@ -605,7 +605,7 @@ public function __getLastRequestHeaders(): ?string {} public function __getLastResponseHeaders(): ?string {} /** @tentative-return-type */ - public function __doRequest(string $request, string $location, string $action, int $version, bool $oneWay = false): ?string {} + public function __doRequest(string $request, string $location, string $action, int $version, bool $oneWay = false, ?string $uriParserClass = null): ?string {} /** @tentative-return-type */ public function __setCookie(string $name, ?string $value = null): void {} diff --git a/ext/soap/soap_arginfo.h b/ext/soap/soap_arginfo.h index 8aff24f75cbef..746c6e29a2ad2 100644 --- a/ext/soap/soap_arginfo.h +++ b/ext/soap/soap_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 4277993645a3f560c7a9971466fabf2d451bc92d */ + * Stub hash: 24e266bf0933d5622f2a341db5b694ecb1740f13 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_use_soap_error_handler, 0, 0, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, enable, _IS_BOOL, 0, "true") @@ -124,6 +124,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SoapClient___doR ZEND_ARG_TYPE_INFO(0, action, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, version, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, oneWay, _IS_BOOL, 0, "false") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, uriParserClass, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SoapClient___setCookie, 0, 1, IS_VOID, 0) diff --git a/ext/soap/tests/SoapServer/__getLastResponse.phpt b/ext/soap/tests/SoapServer/__getLastResponse.phpt index 83c20d3c3a49c..900a880359731 100644 --- a/ext/soap/tests/SoapServer/__getLastResponse.phpt +++ b/ext/soap/tests/SoapServer/__getLastResponse.phpt @@ -18,7 +18,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("f"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/any.phpt b/ext/soap/tests/any.phpt index 6b08e395c2b1a..c25748997aba5 100644 --- a/ext/soap/tests/any.phpt +++ b/ext/soap/tests/any.phpt @@ -33,7 +33,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('echoAnyElement'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug28969.phpt b/ext/soap/tests/bugs/bug28969.phpt index 71de59939f8de..661e1fc82277d 100644 --- a/ext/soap/tests/bugs/bug28969.phpt +++ b/ext/soap/tests/bugs/bug28969.phpt @@ -18,7 +18,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug29795.phpt b/ext/soap/tests/bugs/bug29795.phpt index 1db3226ab171f..395d3b6c7ec61 100644 --- a/ext/soap/tests/bugs/bug29795.phpt +++ b/ext/soap/tests/bugs/bug29795.phpt @@ -12,7 +12,7 @@ class LocalSoapClient extends SoapClient { parent::__construct($wsdl, $options); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { return <<server->addFunction('EchoString'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug29844.phpt b/ext/soap/tests/bugs/bug29844.phpt index 7f5178ec6db7a..c98c3041bbb6a 100644 --- a/ext/soap/tests/bugs/bug29844.phpt +++ b/ext/soap/tests/bugs/bug29844.phpt @@ -22,7 +22,7 @@ class LocalSoapClient extends SoapClient { $this->server->setClass('hello_world'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug30045.phpt b/ext/soap/tests/bugs/bug30045.phpt index a84b73a7830f8..7dac3d0266311 100644 --- a/ext/soap/tests/bugs/bug30045.phpt +++ b/ext/soap/tests/bugs/bug30045.phpt @@ -21,7 +21,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('foo'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { $xml = simplexml_load_string($request); echo $xml->children("http://schemas.xmlsoap.org/soap/envelope/")->Body->children("http://test-uri")->children()->param1->asXML(),"\n"; unset($xml); diff --git a/ext/soap/tests/bugs/bug30106.phpt b/ext/soap/tests/bugs/bug30106.phpt index d924a5bb8b32a..0a891b4cb59dd 100644 --- a/ext/soap/tests/bugs/bug30106.phpt +++ b/ext/soap/tests/bugs/bug30106.phpt @@ -21,7 +21,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("getContinentList"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo $request; ob_start(); $this->server->handle($request); diff --git a/ext/soap/tests/bugs/bug30175.phpt b/ext/soap/tests/bugs/bug30175.phpt index ab0ab5cc11c7f..9f17f60162dd8 100644 --- a/ext/soap/tests/bugs/bug30175.phpt +++ b/ext/soap/tests/bugs/bug30175.phpt @@ -9,7 +9,7 @@ soap.wsdl_cache_enabled=0 class LocalSoapClient extends SoapClient { - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { return << server->addFunction('test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug31695.phpt b/ext/soap/tests/bugs/bug31695.phpt index ba8a6ae000618..0d95cc6cfe67c 100644 --- a/ext/soap/tests/bugs/bug31695.phpt +++ b/ext/soap/tests/bugs/bug31695.phpt @@ -19,7 +19,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("Test"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo "$location\n"; ob_start(); $this->server->handle($request); diff --git a/ext/soap/tests/bugs/bug31755.phpt b/ext/soap/tests/bugs/bug31755.phpt index cf8987db3ee13..c4b2c622b6af1 100644 --- a/ext/soap/tests/bugs/bug31755.phpt +++ b/ext/soap/tests/bugs/bug31755.phpt @@ -5,7 +5,7 @@ soap --FILE-- server->addFunction('test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug32941.phpt b/ext/soap/tests/bugs/bug32941.phpt index 0b4ac3ab30efd..85f4434f06592 100644 --- a/ext/soap/tests/bugs/bug32941.phpt +++ b/ext/soap/tests/bugs/bug32941.phpt @@ -5,7 +5,7 @@ soap --FILE-- server->addFunction('EchoString'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug34643.phpt b/ext/soap/tests/bugs/bug34643.phpt index 5c23cbd7c7b37..27542c2c2870a 100644 --- a/ext/soap/tests/bugs/bug34643.phpt +++ b/ext/soap/tests/bugs/bug34643.phpt @@ -23,7 +23,7 @@ class LocalSoapClient extends SoapClient { $this->server->setClass('fp'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug35142.phpt b/ext/soap/tests/bugs/bug35142.phpt index 5f46bbf84113c..d596c5eb54432 100644 --- a/ext/soap/tests/bugs/bug35142.phpt +++ b/ext/soap/tests/bugs/bug35142.phpt @@ -25,7 +25,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('PostEvents'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo "$request\n"; ob_start(); $this->server->handle($request); diff --git a/ext/soap/tests/bugs/bug35273.phpt b/ext/soap/tests/bugs/bug35273.phpt index 93e54626c5266..c35d545851feb 100644 --- a/ext/soap/tests/bugs/bug35273.phpt +++ b/ext/soap/tests/bugs/bug35273.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- server->addFunction('PostEvents'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo "$request\n"; $this->server->handle($request); return $response; diff --git a/ext/soap/tests/bugs/bug36226.phpt b/ext/soap/tests/bugs/bug36226.phpt index 38ece5d0b87a0..c1d86ce4b3d92 100644 --- a/ext/soap/tests/bugs/bug36226.phpt +++ b/ext/soap/tests/bugs/bug36226.phpt @@ -25,7 +25,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('PostEvents'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo "$request\n"; ob_start(); $this->server->handle($request); diff --git a/ext/soap/tests/bugs/bug36999.phpt b/ext/soap/tests/bugs/bug36999.phpt index 04673649da232..d4ed65621e2a0 100644 --- a/ext/soap/tests/bugs/bug36999.phpt +++ b/ext/soap/tests/bugs/bug36999.phpt @@ -20,7 +20,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('echoLong'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug37083.phpt b/ext/soap/tests/bugs/bug37083.phpt index 441b51022b8a6..8e5326e03439f 100644 --- a/ext/soap/tests/bugs/bug37083.phpt +++ b/ext/soap/tests/bugs/bug37083.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache=3 --FILE-- diff --git a/ext/soap/tests/bugs/bug38004.phpt b/ext/soap/tests/bugs/bug38004.phpt index 7953487ab1ece..3ca5aeda814f8 100644 --- a/ext/soap/tests/bugs/bug38004.phpt +++ b/ext/soap/tests/bugs/bug38004.phpt @@ -21,7 +21,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('Test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug38005.phpt b/ext/soap/tests/bugs/bug38005.phpt index ca3944ebc3db3..67837861ea5eb 100644 --- a/ext/soap/tests/bugs/bug38005.phpt +++ b/ext/soap/tests/bugs/bug38005.phpt @@ -19,7 +19,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('Test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug38055.phpt b/ext/soap/tests/bugs/bug38055.phpt index b066bf892e37a..ad951b537f238 100644 --- a/ext/soap/tests/bugs/bug38055.phpt +++ b/ext/soap/tests/bugs/bug38055.phpt @@ -22,7 +22,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('Test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug38067.phpt b/ext/soap/tests/bugs/bug38067.phpt index 2f25a87a1cf37..962e0c29d253f 100644 --- a/ext/soap/tests/bugs/bug38067.phpt +++ b/ext/soap/tests/bugs/bug38067.phpt @@ -21,7 +21,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('Test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = 0, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug38536.phpt b/ext/soap/tests/bugs/bug38536.phpt index 5865e6a904ab9..c64772ccbc734 100644 --- a/ext/soap/tests/bugs/bug38536.phpt +++ b/ext/soap/tests/bugs/bug38536.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/bugs/bug39815.phpt b/ext/soap/tests/bugs/bug39815.phpt index 51178e40e5b89..0eeb18cf416fb 100644 --- a/ext/soap/tests/bugs/bug39815.phpt +++ b/ext/soap/tests/bugs/bug39815.phpt @@ -23,7 +23,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug42692.phpt b/ext/soap/tests/bugs/bug42692.phpt index 5ed9254b51726..fe4840d9268de 100644 --- a/ext/soap/tests/bugs/bug42692.phpt +++ b/ext/soap/tests/bugs/bug42692.phpt @@ -19,7 +19,7 @@ class TestSoap extends SoapClient { $this->server->addFunction("checkAuth"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug43045.phpt b/ext/soap/tests/bugs/bug43045.phpt index f1e3af7765b67..79a746e1692f9 100644 --- a/ext/soap/tests/bugs/bug43045.phpt +++ b/ext/soap/tests/bugs/bug43045.phpt @@ -16,7 +16,7 @@ class TestSoapClient extends SoapClient { $this->server = new SoapServer($wsdl, $options); $this->server->addFunction('test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug44882.phpt b/ext/soap/tests/bugs/bug44882.phpt index 73049602aaf9c..93857fd3b27ba 100644 --- a/ext/soap/tests/bugs/bug44882.phpt +++ b/ext/soap/tests/bugs/bug44882.phpt @@ -8,7 +8,7 @@ soap.wsdl_cache_enabled=0 diff --git a/ext/soap/tests/bugs/bug46419.phpt b/ext/soap/tests/bugs/bug46419.phpt index e12adfb08f20c..090f4e08a5b8a 100644 --- a/ext/soap/tests/bugs/bug46419.phpt +++ b/ext/soap/tests/bugs/bug46419.phpt @@ -17,7 +17,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('bar'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug47021.phpt b/ext/soap/tests/bugs/bug47021.phpt index af12d7c4c39c5..19b034b9eed23 100644 --- a/ext/soap/tests/bugs/bug47021.phpt +++ b/ext/soap/tests/bugs/bug47021.phpt @@ -57,9 +57,9 @@ $options = [ class BugSoapClient extends SoapClient { - public function __doRequest($request, $location, $action, $version, $one_way = null): string + public function __doRequest($request, $location, $action, $version, $one_way = null, ?string $uriParserClass = null): string { - $response = parent::__doRequest($request, $location, $action, $version, $one_way); + $response = parent::__doRequest($request, $location, $action, $version, $one_way, $uriParserClass); var_dump(strlen($response)); diff --git a/ext/soap/tests/bugs/bug50675.phpt b/ext/soap/tests/bugs/bug50675.phpt index e4bad4ffdfacf..bc6a47577e2b7 100644 --- a/ext/soap/tests/bugs/bug50675.phpt +++ b/ext/soap/tests/bugs/bug50675.phpt @@ -6,7 +6,7 @@ soap server->setObject(new testSoap()); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug54911.phpt b/ext/soap/tests/bugs/bug54911.phpt index 3247563dba496..0b1daec31345c 100644 --- a/ext/soap/tests/bugs/bug54911.phpt +++ b/ext/soap/tests/bugs/bug54911.phpt @@ -5,7 +5,7 @@ soap --FILE-- diff --git a/ext/soap/tests/bugs/bug66049.phpt b/ext/soap/tests/bugs/bug66049.phpt index e48845a8a142b..c31d0d7bcccdf 100644 --- a/ext/soap/tests/bugs/bug66049.phpt +++ b/ext/soap/tests/bugs/bug66049.phpt @@ -15,7 +15,7 @@ function soap_string_from_xml($str) } class TestSoapClient extends SoapClient { - function __doRequest($request, $location, $action, $version, $one_way = 0): ?string { + function __doRequest($request, $location, $action, $version, $one_way = 0, ?string $uriParserClass = null): ?string { $res=' diff --git a/ext/soap/tests/bugs/bug69085.phpt b/ext/soap/tests/bugs/bug69085.phpt index 3572efa5e381d..5974ce425319a 100644 --- a/ext/soap/tests/bugs/bug69085.phpt +++ b/ext/soap/tests/bugs/bug69085.phpt @@ -9,7 +9,7 @@ soap.wsdl_cache_enabled=0 #[AllowDynamicProperties] class MySoapClient extends SoapClient { - public function __doRequest($request, $location, $action, $version, $one_way = 0): string { + public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo $request, "\n"; return ''; } diff --git a/ext/soap/tests/bugs/bug69668.phpt b/ext/soap/tests/bugs/bug69668.phpt index b93163c164de1..75fe05d5c2ed1 100644 --- a/ext/soap/tests/bugs/bug69668.phpt +++ b/ext/soap/tests/bugs/bug69668.phpt @@ -5,7 +5,7 @@ soap --FILE-- '', 'uri' => 'http://example.org']) extends SoapClient { - public function __doRequest($request, $location, $action, $version, $one_way = 0): string { + public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo $request; return ''; } diff --git a/ext/soap/tests/bugs/bug71996.phpt b/ext/soap/tests/bugs/bug71996.phpt index a6b2a71765b54..d78661ad3273e 100644 --- a/ext/soap/tests/bugs/bug71996.phpt +++ b/ext/soap/tests/bugs/bug71996.phpt @@ -6,7 +6,7 @@ soap '', 'uri' => 'http://example.org']) extends SoapClient { - public function __doRequest($request, $location, $action, $version, $one_way = 0): string { + public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo $request, "\n"; return ''; } diff --git a/ext/soap/tests/bugs/bug73237.phpt b/ext/soap/tests/bugs/bug73237.phpt index 643c99a8c22a3..32ee055706354 100644 --- a/ext/soap/tests/bugs/bug73237.phpt +++ b/ext/soap/tests/bugs/bug73237.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- trueCampaignMember00vi0000011VMgeAAG00vi0000011VMgeAAG701i0000001lreeAAASent00Qi000001UrbYFEAZLeadangela.lansbury@cbs.com1 EOF; diff --git a/ext/soap/tests/bugs/bug77141.phpt b/ext/soap/tests/bugs/bug77141.phpt index 4a86b6af902b4..67b07d598650a 100644 --- a/ext/soap/tests/bugs/bug77141.phpt +++ b/ext/soap/tests/bugs/bug77141.phpt @@ -5,7 +5,7 @@ soap --FILE-- WSDL_CACHE_NONE, 'trace' => 1, ]) extends SoapClient { - public function __doRequest($request, $location, $action, $version, $one_way = 0): string { + public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo $request, "\n"; return ''; } diff --git a/ext/soap/tests/bugs/segfault_assertion_props.phpt b/ext/soap/tests/bugs/segfault_assertion_props.phpt index 75cefa57642e0..f11ea61f7cd3f 100644 --- a/ext/soap/tests/bugs/segfault_assertion_props.phpt +++ b/ext/soap/tests/bugs/segfault_assertion_props.phpt @@ -7,7 +7,7 @@ soap --FILE-- diff --git a/ext/soap/tests/classmap002.phpt b/ext/soap/tests/classmap002.phpt index 626b9f8ff66b5..13c82c1b53838 100644 --- a/ext/soap/tests/classmap002.phpt +++ b/ext/soap/tests/classmap002.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/classmap003.phpt b/ext/soap/tests/classmap003.phpt index 322445fa16af6..31839f841f8f3 100644 --- a/ext/soap/tests/classmap003.phpt +++ b/ext/soap/tests/classmap003.phpt @@ -34,7 +34,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("f"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/classmap004.phpt b/ext/soap/tests/classmap004.phpt index 1fbf4c6ccad3d..172a6db7b4483 100644 --- a/ext/soap/tests/classmap004.phpt +++ b/ext/soap/tests/classmap004.phpt @@ -42,7 +42,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("f"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/classmap005.phpt b/ext/soap/tests/classmap005.phpt index ce4aa2b66bb85..a39adfa85033a 100644 --- a/ext/soap/tests/classmap005.phpt +++ b/ext/soap/tests/classmap005.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/classmap006.phpt b/ext/soap/tests/classmap006.phpt index 817a3a883c7eb..c56f876148a1c 100644 --- a/ext/soap/tests/classmap006.phpt +++ b/ext/soap/tests/classmap006.phpt @@ -39,7 +39,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("f"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/classmap007.phpt b/ext/soap/tests/classmap007.phpt index b6fe394eaeecb..9a59e647bc96e 100644 --- a/ext/soap/tests/classmap007.phpt +++ b/ext/soap/tests/classmap007.phpt @@ -39,7 +39,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("f"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/gh15711.phpt b/ext/soap/tests/gh15711.phpt index b72251cc6f95b..17ff051698fdb 100644 --- a/ext/soap/tests/gh15711.phpt +++ b/ext/soap/tests/gh15711.phpt @@ -28,7 +28,7 @@ enum NonBackedEnum } class TestSoapClient extends SoapClient { - function __doRequest($request, $location, $action, $version, $one_way = 0): ?string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): ?string { echo $request; } } diff --git a/ext/soap/tests/gh16318.phpt b/ext/soap/tests/gh16318.phpt index a0a4c925df051..0c38b6fc8de30 100644 --- a/ext/soap/tests/gh16318.phpt +++ b/ext/soap/tests/gh16318.phpt @@ -15,7 +15,7 @@ $test2["a"] = "a"; $test2[] =& $test2; class TestSoapClient extends SoapClient { - public function __doRequest(string $request, string $location, string $action, int $version, bool $oneWay = false): ?string + public function __doRequest(string $request, string $location, string $action, int $version, bool $oneWay = false, ?string $uriParserClass = null): ?string { die($request); } diff --git a/ext/soap/tests/soap_qname_crash.phpt b/ext/soap/tests/soap_qname_crash.phpt index bcf01d574fab4..53d6904db1c95 100644 --- a/ext/soap/tests/soap_qname_crash.phpt +++ b/ext/soap/tests/soap_qname_crash.phpt @@ -18,6 +18,7 @@ class TestSoapClient extends SoapClient { $action, $version, $one_way = false, + ?string $uriParserClass = null, ): ?string { die($request); } diff --git a/ext/soap/tests/transport001.phpt b/ext/soap/tests/transport001.phpt index 297d0e1288e7e..c735b2e139d76 100644 --- a/ext/soap/tests/transport001.phpt +++ b/ext/soap/tests/transport001.phpt @@ -17,7 +17,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('Add'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/typemap003.phpt b/ext/soap/tests/typemap003.phpt index a7b83b6348bba..3f4960f8d5d6b 100644 --- a/ext/soap/tests/typemap003.phpt +++ b/ext/soap/tests/typemap003.phpt @@ -8,7 +8,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/typemap004.phpt b/ext/soap/tests/typemap004.phpt index 61b62867205fc..c0feb6b4ebbc8 100644 --- a/ext/soap/tests/typemap004.phpt +++ b/ext/soap/tests/typemap004.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/typemap008.phpt b/ext/soap/tests/typemap008.phpt index 8abd8039f8d59..7e7012b6ad5ca 100644 --- a/ext/soap/tests/typemap008.phpt +++ b/ext/soap/tests/typemap008.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/typemap012.phpt b/ext/soap/tests/typemap012.phpt index e31d3ffa0ac48..13bb0c8984796 100644 --- a/ext/soap/tests/typemap012.phpt +++ b/ext/soap/tests/typemap012.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- uri; + + if (parse_url_uri->scheme) { + ZVAL_STR_COPY(retval, parse_url_uri->scheme); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result parse_url_read_username(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) +{ + php_url *parse_url_uri = (php_url *) internal_uri->uri; + + if (parse_url_uri->user) { + ZVAL_STR_COPY(retval, parse_url_uri->user); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result parse_url_read_password(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) +{ + php_url *parse_url_uri = (php_url *) internal_uri->uri; + + if (parse_url_uri->pass) { + ZVAL_STR_COPY(retval, parse_url_uri->pass); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result parse_url_read_host(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) +{ + php_url *parse_url_uri = (php_url *) internal_uri->uri; + + if (parse_url_uri->host) { + ZVAL_STR_COPY(retval, parse_url_uri->host); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result parse_url_read_port(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) +{ + php_url *parse_url_uri = (php_url *) internal_uri->uri; + + if (parse_url_uri->port) { + ZVAL_LONG(retval, parse_url_uri->port); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result parse_url_read_path(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) +{ + php_url *parse_url_uri = (php_url *) internal_uri->uri; + + if (parse_url_uri->path) { + ZVAL_STR_COPY(retval, parse_url_uri->path); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result parse_url_read_query(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) +{ + php_url *parse_url_uri = (php_url *) internal_uri->uri; + + if (parse_url_uri->query) { + ZVAL_STR_COPY(retval, parse_url_uri->query); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static zend_result parse_url_read_fragment(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) +{ + php_url *parse_url_uri = (php_url *) internal_uri->uri; + + if (parse_url_uri->fragment) { + ZVAL_STR_COPY(retval, parse_url_uri->fragment); + } else { + ZVAL_NULL(retval); + } + + return SUCCESS; +} + +static void *parse_url_clone_uri(void *uri) +{ + ZEND_UNREACHABLE(); +} + +static void throw_invalid_uri_exception(void) +{ + zval exception; + + object_init_ex(&exception, uri_invalid_uri_exception_ce); + + zval value; + ZVAL_STRING(&value, "URL parsing failed"); + zend_update_property_ex(uri_whatwg_invalid_url_exception_ce, Z_OBJ(exception), ZSTR_KNOWN(ZEND_STR_MESSAGE), &value); + zval_ptr_dtor_str(&value); + + zend_throw_exception_object(&exception); +} + +static void *parse_url_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors, bool silent) +{ + bool has_port; + + php_url *url = php_url_parse_ex2(ZSTR_VAL(uri_str), ZSTR_LEN(uri_str), &has_port); + if (url == NULL && !silent) { + throw_invalid_uri_exception(); + } + + return url; +} + +static zend_string *parse_url_uri_to_string(void *uri, uri_recomposition_mode_t recomposition_mode, bool exclude_fragment) +{ + ZEND_UNREACHABLE(); +} + +const uri_handler_t parse_url_uri_handler = { + .name = URI_PARSER_PHP, + .parse_uri = parse_url_parse_uri, + .clone_uri = parse_url_clone_uri, + .uri_to_string = parse_url_uri_to_string, + .free_uri = parse_url_free_uri, + { + .scheme = {.read_func = parse_url_read_scheme, .write_func = NULL}, + .username = {.read_func = parse_url_read_username, .write_func = NULL}, + .password = {.read_func = parse_url_read_password, .write_func = NULL}, + .host = {.read_func = parse_url_read_host, .write_func = NULL}, + .port = {.read_func = parse_url_read_port, .write_func = NULL}, + .path = {.read_func = parse_url_read_path, .write_func = NULL}, + .query = {.read_func = parse_url_read_query, .write_func = NULL}, + .fragment = {.read_func = parse_url_read_fragment, .write_func = NULL}, + } +}; /* {{{ Parse a URL and return its components */ PHP_FUNCTION(parse_url) @@ -753,3 +919,8 @@ PHP_FUNCTION(get_headers) php_stream_close(stream); } /* }}} */ + +PHP_MINIT_FUNCTION(url) +{ + return uri_handler_register(&parse_url_uri_handler); +} diff --git a/ext/standard/url.h b/ext/standard/url.h index 3885ecece5780..aefc362744cfd 100644 --- a/ext/standard/url.h +++ b/ext/standard/url.h @@ -17,6 +17,8 @@ #ifndef URL_H #define URL_H +PHP_MINIT_FUNCTION(url); + typedef struct php_url { zend_string *scheme; zend_string *user; diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index f5a5b160bba06..695602451dc73 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -25,7 +25,7 @@ #include "Zend/zend_enum.h" #include "ext/standard/info.h" -#include "php_uri_common.h" +#include "php_uri.h" #include "php_lexbor.h" #include "php_uriparser.h" #include "php_uri_arginfo.h" @@ -106,6 +106,224 @@ static HashTable *uri_get_debug_properties(zend_object *object) return result; } +PHPAPI uri_handler_t *php_uri_get_handler(const zend_string *uri_handler_name) +{ + if (uri_handler_name == NULL) { + return uri_handler_by_name("parse_url", sizeof("parse_url") - 1); + } + + return uri_handler_by_name(ZSTR_VAL(uri_handler_name), ZSTR_LEN(uri_handler_name)); +} + +PHPAPI uri_internal_t *php_uri_parse(const uri_handler_t *uri_handler, zend_string *uri_str, bool silent) +{ + ZEND_ASSERT(uri_handler != NULL); + + if (ZSTR_LEN(uri_str) == 0) { + return NULL; + } + + uri_internal_t *internal_uri = emalloc(sizeof(uri_internal_t)); + internal_uri->handler = uri_handler; + internal_uri->uri = uri_handler->parse_uri(uri_str, NULL, NULL, silent); + + if (UNEXPECTED(internal_uri->uri == NULL)) { + efree(internal_uri); + return NULL; + } + + return internal_uri; +} + +static zend_result php_uri_get_property(const uri_internal_t *internal_uri, uri_property_name_t property_name, uri_component_read_mode_t read_mode, zval *zv) +{ + const uri_property_handler_t *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); + if (property_handler == NULL) { + return FAILURE; + } + + return property_handler->read_func(internal_uri, read_mode, zv); +} + +PHPAPI zend_result php_uri_get_scheme(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv) +{ + return php_uri_get_property(internal_uri, URI_PROPERTY_NAME_SCHEME, read_mode, zv); +} + +PHPAPI zend_result php_uri_get_username(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv) +{ + return php_uri_get_property(internal_uri, URI_PROPERTY_NAME_USERNAME, read_mode, zv); +} + +PHPAPI zend_result php_uri_get_password(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv) +{ + return php_uri_get_property(internal_uri, URI_PROPERTY_NAME_PASSWORD, read_mode, zv); +} + +PHPAPI zend_result php_uri_get_host(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv) +{ + return php_uri_get_property(internal_uri, URI_PROPERTY_NAME_HOST, read_mode, zv); +} + +PHPAPI zend_result php_uri_get_port(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv) +{ + return php_uri_get_property(internal_uri, URI_PROPERTY_NAME_PORT, read_mode, zv); +} + +PHPAPI zend_result php_uri_get_path(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv) +{ + return php_uri_get_property(internal_uri, URI_PROPERTY_NAME_PATH, read_mode, zv); +} + +PHPAPI zend_result php_uri_get_query(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv) +{ + return php_uri_get_property(internal_uri, URI_PROPERTY_NAME_QUERY, read_mode, zv); +} + +PHPAPI zend_result php_uri_get_fragment(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv) +{ + return php_uri_get_property(internal_uri, URI_PROPERTY_NAME_FRAGMENT, read_mode, zv); +} + +PHPAPI void php_uri_free(uri_internal_t *internal_uri) +{ + internal_uri->handler->free_uri(internal_uri->uri); + internal_uri->uri = NULL; + internal_uri->handler = NULL; + efree(internal_uri); +} + +PHPAPI php_uri *php_uri_parse_to_struct(const uri_handler_t *uri_handler, zend_string *uri_str, uri_component_read_mode_t read_mode, bool silent) +{ + uri_internal_t *uri_internal = php_uri_parse(uri_handler, uri_str, silent); + if (uri_internal == NULL) { + return NULL; + } + + php_uri *uri = ecalloc(1, sizeof(php_uri)); + zval tmp; + ZVAL_UNDEF(&tmp); + zend_result result; + + result = php_uri_get_scheme(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + php_uri_free(uri_internal); + php_uri_struct_free(uri); + return NULL; + } + if (Z_TYPE(tmp) == IS_STRING && Z_STRLEN(tmp) > 0) { + uri->scheme = zend_string_copy(Z_STR(tmp)); + zval_ptr_dtor(&tmp); + } + + result = php_uri_get_username(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + php_uri_free(uri_internal); + php_uri_struct_free(uri); + return NULL; + } + if (Z_TYPE(tmp) == IS_STRING && Z_STRLEN(tmp) > 0) { + uri->user = zend_string_copy(Z_STR(tmp)); + zval_ptr_dtor(&tmp); + } + + result = php_uri_get_password(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + php_uri_free(uri_internal); + php_uri_struct_free(uri); + return NULL; + } + if (Z_TYPE(tmp) == IS_STRING && Z_STRLEN(tmp) > 0) { + uri->password = zend_string_copy(Z_STR(tmp)); + zval_ptr_dtor(&tmp); + } + + result = php_uri_get_host(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + php_uri_free(uri_internal); + php_uri_struct_free(uri); + return NULL; + } + if (Z_TYPE(tmp) == IS_STRING && Z_STRLEN(tmp) > 0) { + uri->host = zend_string_copy(Z_STR(tmp)); + zval_ptr_dtor(&tmp); + } + + result = php_uri_get_port(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + php_uri_free(uri_internal); + php_uri_struct_free(uri); + return NULL; + } + if (Z_TYPE(tmp) == IS_LONG && Z_LVAL(tmp) >= 0) { + uri->port = Z_LVAL(tmp); + } + + result = php_uri_get_path(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + php_uri_free(uri_internal); + php_uri_struct_free(uri); + return NULL; + } + if (Z_TYPE(tmp) == IS_STRING && Z_STRLEN(tmp) > 0) { + uri->path = zend_string_copy(Z_STR(tmp)); + zval_ptr_dtor(&tmp); + } + + result = php_uri_get_query(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + php_uri_free(uri_internal); + php_uri_struct_free(uri); + return NULL; + } + if (Z_TYPE(tmp) == IS_STRING && Z_STRLEN(tmp) > 0) { + uri->query = zend_string_copy(Z_STR(tmp)); + zval_ptr_dtor(&tmp); + } + + result = php_uri_get_fragment(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + php_uri_free(uri_internal); + php_uri_struct_free(uri); + return NULL; + } + if (Z_TYPE(tmp) == IS_STRING && Z_STRLEN(tmp) > 0) { + uri->fragment = zend_string_copy(Z_STR(tmp)); + zval_ptr_dtor(&tmp); + } + + php_uri_free(uri_internal); + + return uri; +} + +PHPAPI void php_uri_struct_free(php_uri *uri) +{ + if (uri->scheme) { + zend_string_release(uri->scheme); + } + if (uri->user) { + zend_string_release(uri->user); + } + if (uri->password) { + zend_string_release(uri->password); + } + if (uri->host) { + zend_string_release(uri->host); + } + if (uri->path) { + zend_string_release(uri->path); + } + if (uri->query) { + zend_string_release(uri->query); + } + if (uri->fragment) { + zend_string_release(uri->fragment); + } + + efree(uri); +} + /** * Pass the errors parameter by ref to errors_zv for userland, and frees it if * it is not not needed anymore. diff --git a/ext/uri/php_uri.h b/ext/uri/php_uri.h index 9e22c227cbf83..8ac7f24f69395 100644 --- a/ext/uri/php_uri.h +++ b/ext/uri/php_uri.h @@ -22,6 +22,35 @@ extern zend_module_entry uri_module_entry; #define phpext_uri_ptr &uri_module_entry +typedef struct { + zend_string *scheme; + zend_string *user; + zend_string *password; + zend_string *host; + unsigned short port; + zend_string *path; + zend_string *query; + zend_string *fragment; +} php_uri; + +PHPAPI uri_handler_t *php_uri_get_handler(const zend_string *uri_handler_name); +PHPAPI uri_internal_t *php_uri_parse(const uri_handler_t *uri_handler, zend_string *uri_str, bool silent); +PHPAPI zend_result php_uri_get_scheme(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv); +PHPAPI zend_result php_uri_get_username(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv); +PHPAPI zend_result php_uri_get_password(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv); +PHPAPI zend_result php_uri_get_host(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv); +PHPAPI zend_result php_uri_get_port(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv); +PHPAPI zend_result php_uri_get_path(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv); +PHPAPI zend_result php_uri_get_query(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv); +PHPAPI zend_result php_uri_get_fragment(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv); +PHPAPI void php_uri_free(uri_internal_t *internal_uri); +PHPAPI php_uri *php_uri_parse_to_struct(const uri_handler_t *uri_handler, zend_string *uri_str, uri_component_read_mode_t read_mode, bool silent); +PHPAPI void php_uri_struct_free(php_uri *uri); + +PHPAPI void php_uri_instantiate_uri( + INTERNAL_FUNCTION_PARAMETERS, const uri_handler_t *handler, const zend_string *uri_str, const zend_object *base_url_object, + bool should_throw, bool should_update_this_object, zval *errors_zv +); PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers); #endif diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index 8e5b0c2d2279f..0bee8a0ba5413 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -125,6 +125,7 @@ static inline uri_internal_t *uri_internal_from_obj(const zend_object *object) { #define URI_PARSER_RFC3986 "Uri\\Rfc3986\\Uri" #define URI_PARSER_WHATWG "Uri\\WhatWg\\Url" +#define URI_PARSER_PHP "parse_url" #define URI_SERIALIZED_PROPERTY_NAME "uri" zend_result uri_handler_register(const uri_handler_t *uri_handler);