mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Add internal URI handling API (#19073)
Part of https://github.com/php/php-src/pull/14461. Related to https://wiki.php.net/rfc/url_parsing_api.
This commit is contained in:
13
NEWS
13
NEWS
@@ -12,6 +12,14 @@ PHP NEWS
|
||||
error in PHP 9. (alexandre-daubois)
|
||||
. Fixed OSS-Fuzz #439125710 (Pipe cannot be used in write context).
|
||||
(nielsdos)
|
||||
. Added support for configuring the URI parser for the FTP/FTPS as well as
|
||||
the SSL/TLS stream wrappers as described in
|
||||
https://wiki.php.net/rfc/url_parsing_api#plugability. (kocsismate)
|
||||
|
||||
- Filter:
|
||||
. Added support for configuring the URI parser for FILTER_VALIDATE_URL
|
||||
as described in https://wiki.php.net/rfc/url_parsing_api#plugability.
|
||||
(kocsismate)
|
||||
|
||||
- ODBC:
|
||||
. Remove ODBCVER and assume ODBC 3.5. (Calvin Buckley)
|
||||
@@ -26,6 +34,11 @@ PHP NEWS
|
||||
- Session:
|
||||
. Added support for partitioned cookies. (nielsdos)
|
||||
|
||||
- SOAP:
|
||||
. Added support for configuring the URI parser for SoapClient::_doRequest()
|
||||
as described in https://wiki.php.net/rfc/url_parsing_api#plugability.
|
||||
(kocsismate)
|
||||
|
||||
- SPL:
|
||||
. Deprecate ArrayObject and ArrayIterator with objects. (Girgias)
|
||||
|
||||
|
||||
@@ -85,6 +85,9 @@ PHP 8.5 INTERNALS UPGRADE NOTES
|
||||
. ext/standard/php_smart_string.h and ext/standard/php_smart_string_public.h
|
||||
were removed. Use the corresponding headers in Zend/ instead.
|
||||
|
||||
- URI
|
||||
. Internal API for URI handling was added via the php_uri_*() functions.
|
||||
|
||||
========================
|
||||
2. Build system changes
|
||||
========================
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "zend_exceptions.h"
|
||||
#include "php_filter.h"
|
||||
#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,66 @@ 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);
|
||||
|
||||
if (url == NULL) {
|
||||
uri_handler_t *uri_handler = php_uri_get_handler(parser_name_set ? parser_name : NULL);
|
||||
if (uri_handler == NULL) {
|
||||
zend_value_error("%s(): \"uri_parser_class\" option has invalid value", get_active_function_name());
|
||||
RETURN_VALIDATION_FAILED
|
||||
}
|
||||
|
||||
if (url->scheme != NULL &&
|
||||
(zend_string_equals_literal_ci(url->scheme, "http") || zend_string_equals_literal_ci(url->scheme, "https"))) {
|
||||
/* Parse the URI - if it fails, we return NULL */
|
||||
php_uri *uri = php_uri_parse_to_struct(uri_handler, Z_STRVAL_P(value), Z_STRLEN_P(value), URI_COMPONENT_READ_RAW, true);
|
||||
if (uri == NULL) {
|
||||
RETURN_VALIDATION_FAILED
|
||||
}
|
||||
|
||||
if (url->host == NULL) {
|
||||
goto bad_url;
|
||||
if (uri->scheme != NULL &&
|
||||
(zend_string_equals_literal_ci(uri->scheme, "http") || zend_string_equals_literal_ci(uri->scheme, "https"))) {
|
||||
|
||||
if (uri->host == NULL) {
|
||||
php_uri_struct_free(uri);
|
||||
RETURN_VALIDATION_FAILED
|
||||
}
|
||||
|
||||
if (
|
||||
/* Skipping these checks is possible because the new URI implementations perform comprehensive validations. */
|
||||
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, URI_PARSER_PHP) == 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);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
184
ext/filter/tests/062.phpt
Normal file
184
ext/filter/tests/062.phpt
Normal file
@@ -0,0 +1,184 @@
|
||||
--TEST--
|
||||
filter_var() and FILTER_VALIDATE_URL with different URI parsers
|
||||
--EXTENSIONS--
|
||||
filter
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function validateUrls(string $parserName)
|
||||
{
|
||||
$values = [
|
||||
'http://example.com/index.html',
|
||||
'http://www.example.com/index.php',
|
||||
'http://www.example/img/test.png',
|
||||
'http://www.example/img/dir/',
|
||||
'http://www.example/img/dir',
|
||||
'http://www.thelongestdomainnameintheworldandthensomeandthensomemoreandmore.com/',
|
||||
'http://toolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolong.com',
|
||||
'http://eauBcFReEmjLcoZwI0RuONNnwU4H9r151juCaqTI5VeIP5jcYIqhx1lh5vV00l2rTs6y7hOp7rYw42QZiq6VIzjcYrRm8gFRMk9U9Wi1grL8Mr5kLVloYLthHgyA94QK3SaXCATklxgo6XvcbXIqAGG7U0KxTr8hJJU1p2ZQ2mXHmp4DhYP8N9SRuEKzaCPcSIcW7uj21jZqBigsLsNAXEzU8SPXZjmVQVtwQATPWeWyGW4GuJhjP4Q8o0.com',
|
||||
'http://kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.CQ1oT5Uq3jJt6Uhy3VH9u3Gi5YhfZCvZVKgLlaXNFhVKB1zJxvunR7SJa.com.',
|
||||
'http://kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58R.example.com',
|
||||
'http://[2001:0db8:0000:85a3:0000:0000:ac1f:8001]',
|
||||
'http://[2001:db8:0:85a3:0:0:ac1f:8001]:123/me.html',
|
||||
'http://[2001:db8:0:85a3::ac1f:8001]/',
|
||||
'http://[::1]',
|
||||
'http://cont-ains.h-yph-en-s.com',
|
||||
'http://..com',
|
||||
'http://a.-bc.com',
|
||||
'http://ab.cd-.com',
|
||||
'http://-.abc.com',
|
||||
'http://abc.-.abc.com',
|
||||
'http://underscore_.example.com',
|
||||
'http//www.example/wrong/url/',
|
||||
'http:/www.example',
|
||||
'file:///tmp/test.c',
|
||||
'ftp://ftp.example.com/tmp/',
|
||||
'/tmp/test.c',
|
||||
'/',
|
||||
'http://',
|
||||
'http:/',
|
||||
'http:',
|
||||
'http',
|
||||
'',
|
||||
-1,
|
||||
[],
|
||||
'mailto:foo@bar.com',
|
||||
'news:news.php.net',
|
||||
'file://foo/bar',
|
||||
"http://\r\n/bar",
|
||||
"http://example.com:qq",
|
||||
"http://example.com:-2",
|
||||
"http://example.com:65536",
|
||||
"http://example.com:65537",
|
||||
];
|
||||
|
||||
foreach ($values as $value) {
|
||||
var_dump(filter_var($value, FILTER_VALIDATE_URL, ["uri_parser_class" => $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/"
|
||||
bool(false)
|
||||
bool(false)
|
||||
string(261) "http://kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.CQ1oT5Uq3jJt6Uhy3VH9u3Gi5YhfZCvZVKgLlaXNFhVKB1zJxvunR7SJa.com."
|
||||
bool(false)
|
||||
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"
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
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"
|
||||
|
||||
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/"
|
||||
bool(false)
|
||||
bool(false)
|
||||
string(261) "http://kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.CQ1oT5Uq3jJt6Uhy3VH9u3Gi5YhfZCvZVKgLlaXNFhVKB1zJxvunR7SJa.com."
|
||||
bool(false)
|
||||
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"
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
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
|
||||
@@ -23,9 +23,10 @@
|
||||
|
||||
#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 "zend_exceptions.h"
|
||||
#include "php_openssl.h"
|
||||
#include "php_openssl_backend.h"
|
||||
#include "php_network.h"
|
||||
@@ -2627,23 +2628,29 @@ static zend_long php_openssl_get_crypto_method(
|
||||
/* }}} */
|
||||
|
||||
static char *php_openssl_get_url_name(const char *resourcename,
|
||||
size_t resourcenamelen, int is_persistent) /* {{{ */
|
||||
size_t resourcenamelen, int is_persistent, php_stream_context *context) /* {{{ */
|
||||
{
|
||||
php_url *url;
|
||||
|
||||
if (!resourcename) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
url = php_url_parse_ex(resourcename, resourcenamelen);
|
||||
if (!url) {
|
||||
uri_handler_t *uri_handler = php_stream_context_get_uri_handler("ssl", context);
|
||||
if (uri_handler == NULL) {
|
||||
zend_value_error("%s(): Provided stream context has invalid value for the \"uri_parser_class\" option", get_active_function_name());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (url->host) {
|
||||
const char * host = ZSTR_VAL(url->host);
|
||||
char * url_name = NULL;
|
||||
size_t len = ZSTR_LEN(url->host);
|
||||
uri_internal_t *internal_uri = php_uri_parse(uri_handler, resourcename, resourcenamelen, true);
|
||||
if (internal_uri == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * url_name = NULL;
|
||||
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);
|
||||
size_t len = Z_STRLEN(host_zv);
|
||||
|
||||
/* skip trailing dots */
|
||||
while (len && host[len-1] == '.') {
|
||||
@@ -2653,13 +2660,12 @@ static char *php_openssl_get_url_name(const char *resourcename,
|
||||
if (len) {
|
||||
url_name = pestrndup(host, len, is_persistent);
|
||||
}
|
||||
|
||||
php_url_free(url);
|
||||
return url_name;
|
||||
}
|
||||
|
||||
php_url_free(url);
|
||||
return NULL;
|
||||
php_uri_free(internal_uri);
|
||||
zval_ptr_dtor(&host_zv);
|
||||
|
||||
return url_name;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -2757,7 +2763,7 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen,
|
||||
#endif
|
||||
}
|
||||
|
||||
sslsock->url_name = php_openssl_get_url_name(resourcename, resourcenamelen, !!persistent_id);
|
||||
sslsock->url_name = php_openssl_get_url_name(resourcename, resourcenamelen, !!persistent_id, context);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ $standard = new ReflectionExtension('standard');
|
||||
var_dump($standard->getDependencies());
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(1) {
|
||||
array(%d) {
|
||||
["uri"]=>
|
||||
%s(8) "Required"
|
||||
["session"]=>
|
||||
%s(8) "Optional"
|
||||
}
|
||||
|
||||
@@ -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,15 @@ 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 +430,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, ZSTR_VAL(location), ZSTR_LEN(location), URI_COMPONENT_READ_RAW, true);
|
||||
}
|
||||
|
||||
tmp = Z_CLIENT_STREAM_CONTEXT_P(this_ptr);
|
||||
@@ -450,8 +453,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 +467,10 @@ try_again:
|
||||
}
|
||||
|
||||
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 +483,7 @@ try_again:
|
||||
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 +494,22 @@ try_again:
|
||||
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 +531,12 @@ try_again:
|
||||
}
|
||||
|
||||
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 +561,7 @@ try_again:
|
||||
|
||||
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 +574,24 @@ try_again:
|
||||
|
||||
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 +599,10 @@ try_again:
|
||||
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 +744,14 @@ try_again:
|
||||
|
||||
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 +792,18 @@ try_again:
|
||||
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 +870,10 @@ try_again:
|
||||
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 +1052,15 @@ try_again:
|
||||
}
|
||||
}
|
||||
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 +1148,46 @@ try_again:
|
||||
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) {
|
||||
efree(loc);
|
||||
zend_argument_value_error(6, "must be a valid URI parser name");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
php_uri *new_uri = php_uri_parse_to_struct(uri_handler, loc, strlen(loc), URI_COMPONENT_READ_RAW, true);
|
||||
efree(loc);
|
||||
|
||||
if (new_url != NULL) {
|
||||
if (new_uri != NULL) {
|
||||
zend_string_release_ex(http_headers, 0);
|
||||
zend_string_release_ex(http_body, 0);
|
||||
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 = new_uri->scheme ? zend_string_copy(new_uri->scheme) : NULL;
|
||||
new_uri->host = new_uri->host ? zend_string_copy(new_uri->host) : NULL;
|
||||
new_uri->port = new_uri->port;
|
||||
if (new_uri->path && ZSTR_VAL(new_uri->path)[0] != '/') {
|
||||
if (new_uri->path) {
|
||||
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 +1247,20 @@ try_again:
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -19,12 +19,10 @@
|
||||
#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 *buf, zend_string *location, char *soapaction,
|
||||
int soap_version, const zend_string *uri_parser_class, zval *return_value
|
||||
);
|
||||
|
||||
int proxy_authentication(zval* this_ptr, smart_str* soap_headers);
|
||||
int basic_authentication(zval* this_ptr, smart_str* soap_headers);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "zend_smart_str.h"
|
||||
#include "php_ini.h"
|
||||
#include "SAPI.h"
|
||||
#include "ext/uri/php_uri.h"
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/xpath.h>
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -2784,28 +2784,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;
|
||||
}
|
||||
|
||||
@@ -605,7 +605,7 @@ namespace {
|
||||
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 {}
|
||||
|
||||
3
ext/soap/soap_arginfo.h
generated
3
ext/soap/soap_arginfo.h
generated
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
|
||||
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
|
||||
|
||||
@@ -20,7 +20,7 @@ class LocalSoapClient extends SoapClient {
|
||||
$this->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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope
|
||||
|
||||
@@ -25,7 +25,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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -5,7 +5,7 @@ soap
|
||||
--FILE--
|
||||
<?php
|
||||
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 '';
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -5,7 +5,7 @@ soap
|
||||
--FILE--
|
||||
<?php
|
||||
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 {
|
||||
return <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<soapenv:Envelope
|
||||
|
||||
@@ -5,7 +5,7 @@ soap
|
||||
--FILE--
|
||||
<?php
|
||||
class TestSoapClient extends SoapClient {
|
||||
function __doRequest($request, $location, $action, $version, $one_way = 0): never {
|
||||
function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): never {
|
||||
echo "$request\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class LocalSoapClient extends SoapClient {
|
||||
$this->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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
class TestSoapClient extends SoapClient {
|
||||
function __doRequest($request, $location, $action, $version, $one_way = 0): never {
|
||||
function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): never {
|
||||
echo $request;
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,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";
|
||||
$this->server->handle($request);
|
||||
return $response;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -7,7 +7,7 @@ soap.wsdl_cache=3
|
||||
--FILE--
|
||||
<?php
|
||||
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 {
|
||||
return <<<EOF
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
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 <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope
|
||||
|
||||
@@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
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 <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -8,7 +8,7 @@ soap.wsdl_cache_enabled=0
|
||||
<?php
|
||||
class TestSoapClient extends SoapClient
|
||||
{
|
||||
public function __doRequest($req, $loc, $act, $ver, $one_way = 0): string
|
||||
public function __doRequest($req, $loc, $act, $ver, $one_way = 0, ?string $uriParserClass = null): string
|
||||
{
|
||||
return <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ soap
|
||||
<?php
|
||||
|
||||
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 {
|
||||
return <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<soapenv:Envelope
|
||||
|
||||
@@ -23,7 +23,7 @@ class LocalSoapClient extends SoapClient {
|
||||
$this->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();
|
||||
|
||||
@@ -5,7 +5,7 @@ soap
|
||||
--FILE--
|
||||
<?php
|
||||
class XSoapClient extends SoapClient {
|
||||
function __doRequest($request, $location, $action, $version, $one_way=false): never {
|
||||
function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): never {
|
||||
echo self::$crash;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ class TestSoapClient 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 <<<EOF
|
||||
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test.com/soap/v3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
|
||||
<SOAP-ENV:Body>
|
||||
|
||||
@@ -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='<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
|
||||
<SOAP-ENV:Body>
|
||||
|
||||
@@ -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 '';
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ soap
|
||||
--FILE--
|
||||
<?php
|
||||
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, PHP_EOL;
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ soap
|
||||
|
||||
#[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 '';
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ soap.wsdl_cache_enabled=0
|
||||
|
||||
class bug70875 extends SOAPClient
|
||||
{
|
||||
public function __doRequest($request, $location, $action, $version, $one_way = 0): never
|
||||
public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): never
|
||||
{
|
||||
die("no SIGSEGV");
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ soap
|
||||
<?php
|
||||
|
||||
$client = new class(null, [ 'location' => '', '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 '';
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ soap
|
||||
<?php
|
||||
|
||||
$client = new class(null, ['location' => '', '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 '';
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
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 <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:test.example.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:object.test.example.org"><soapenv:Body><queryResponse><result xsi:type="QueryResult"><done>true</done><queryLocator xsi:nil="true"/><records xsi:type="sf:genericObject"><sf:type>CampaignMember</sf:type><sf:Id>00vi0000011VMgeAAG</sf:Id><sf:Id>00vi0000011VMgeAAG</sf:Id><sf:CampaignId>701i0000001lreeAAA</sf:CampaignId><sf:Status>Sent</sf:Status><sf:ContactId xsi:nil="true"/><sf:LeadId>00Qi000001UrbYFEAZ</sf:LeadId><sf:Contact xsi:nil="true"/><sf:Lead xsi:type="sf:genericObject"><sf:type>Lead</sf:type><sf:Id xsi:nil="true"/><sf:Email>angela.lansbury@cbs.com</sf:Email></sf:Lead></records><size>1</size></result></queryResponse></soapenv:Body></soapenv:Envelope>
|
||||
EOF;
|
||||
|
||||
@@ -5,7 +5,7 @@ soap
|
||||
--FILE--
|
||||
<?php
|
||||
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 '';
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ $client = new class(__DIR__ . '/bug77410.wsdl', [
|
||||
'cache_wsdl' => 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 '';
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ YuanchengJiang
|
||||
$wsdl = __DIR__."/bug35142.wsdl";
|
||||
|
||||
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 {
|
||||
var_dump($request);
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ soap
|
||||
--FILE--
|
||||
<?php
|
||||
class TestSoapClient extends SoapClient {
|
||||
function __doRequest($request, $location, $action, $version, $one_way = false): string {
|
||||
function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string {
|
||||
return <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.nothing.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body>
|
||||
|
||||
@@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
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 {
|
||||
return <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.nothing.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
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 {
|
||||
return <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.nothing.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ class TestSoapClient extends SoapClient {
|
||||
$action,
|
||||
$version,
|
||||
$one_way = false,
|
||||
?string $uriParserClass = null,
|
||||
): ?string {
|
||||
die($request);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -8,7 +8,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
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 {
|
||||
return <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.nothing.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body>
|
||||
|
||||
@@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
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;
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
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 {
|
||||
return <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.nothing.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body>
|
||||
|
||||
@@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
class TestSoapClient extends SoapClient{
|
||||
function __doRequest($request, $location, $action, $version, $one_way = 0): never {
|
||||
function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): never {
|
||||
echo $request;
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
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 {
|
||||
return <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.nothing.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body>
|
||||
|
||||
@@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0
|
||||
--FILE--
|
||||
<?php
|
||||
class TestSoapClient extends SoapClient{
|
||||
function __doRequest($request, $location, $action, $version, $one_way = 0): never {
|
||||
function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): never {
|
||||
echo $request;
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ static void user_shutdown_function_dtor(zval *zv);
|
||||
static void user_tick_function_dtor(user_tick_function_entry *tick_function_entry);
|
||||
|
||||
static const zend_module_dep standard_deps[] = { /* {{{ */
|
||||
ZEND_MOD_REQUIRED("uri")
|
||||
ZEND_MOD_OPTIONAL("session")
|
||||
ZEND_MOD_END
|
||||
};
|
||||
@@ -304,6 +305,7 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */
|
||||
BASIC_MINIT_SUBMODULE(user_filters)
|
||||
BASIC_MINIT_SUBMODULE(password)
|
||||
BASIC_MINIT_SUBMODULE(image)
|
||||
BASIC_MINIT_SUBMODULE(url)
|
||||
|
||||
#ifdef ZTS
|
||||
BASIC_MINIT_SUBMODULE(localeconv)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "php_globals.h"
|
||||
#include "php_network.h"
|
||||
#include "php_ini.h"
|
||||
#include "zend_exceptions.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -38,6 +39,7 @@
|
||||
#endif
|
||||
|
||||
#include "php_standard.h"
|
||||
#include "ext/uri/php_uri.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
@@ -124,16 +126,22 @@ static int php_stream_ftp_stream_close(php_stream_wrapper *wrapper, php_stream *
|
||||
/* {{{ php_ftp_fopen_connect */
|
||||
static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char *path, const char *mode, int options,
|
||||
zend_string **opened_path, php_stream_context *context, php_stream **preuseid,
|
||||
php_url **presource, int *puse_ssl, int *puse_ssl_on_data)
|
||||
php_uri **presource, int *puse_ssl, int *puse_ssl_on_data)
|
||||
{
|
||||
php_stream *stream = NULL, *reuseid = NULL;
|
||||
php_url *resource = NULL;
|
||||
php_uri *resource = NULL;
|
||||
int result, use_ssl, use_ssl_on_data = 0;
|
||||
char tmp_line[512];
|
||||
char *transport;
|
||||
int transport_len;
|
||||
|
||||
resource = php_url_parse(path);
|
||||
uri_handler_t *uri_handler = php_stream_context_get_uri_handler("ftp", context);
|
||||
if (uri_handler == NULL) {
|
||||
zend_value_error("%s(): Provided stream context has invalid value for the \"uri_parser_class\" option", get_active_function_name());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
resource = php_uri_parse_to_struct(uri_handler, path, strlen(path), URI_COMPONENT_READ_RAW, true);
|
||||
if (resource == NULL || resource->path == NULL) {
|
||||
if (resource && presource) {
|
||||
*presource = resource;
|
||||
@@ -254,12 +262,12 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char
|
||||
if (result >= 300 && result <= 399) {
|
||||
php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, tmp_line, 0);
|
||||
|
||||
if (resource->pass != NULL) {
|
||||
ZSTR_LEN(resource->pass) = php_raw_url_decode(ZSTR_VAL(resource->pass), ZSTR_LEN(resource->pass));
|
||||
if (resource->password != NULL) {
|
||||
ZSTR_LEN(resource->password) = php_raw_url_decode(ZSTR_VAL(resource->password), ZSTR_LEN(resource->password));
|
||||
|
||||
PHP_FTP_CNTRL_CHK(ZSTR_VAL(resource->pass), ZSTR_LEN(resource->pass), "Invalid password %s")
|
||||
PHP_FTP_CNTRL_CHK(ZSTR_VAL(resource->password), ZSTR_LEN(resource->password), "Invalid password %s")
|
||||
|
||||
php_stream_printf(stream, "PASS %s\r\n", ZSTR_VAL(resource->pass));
|
||||
php_stream_printf(stream, "PASS %s\r\n", ZSTR_VAL(resource->password));
|
||||
} else {
|
||||
/* if the user has configured who they are,
|
||||
send that as the password */
|
||||
@@ -299,7 +307,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char
|
||||
return stream;
|
||||
|
||||
connect_errexit:
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
|
||||
if (stream) {
|
||||
php_stream_close(stream);
|
||||
@@ -404,7 +412,7 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa
|
||||
int options, zend_string **opened_path, php_stream_context *context STREAMS_DC)
|
||||
{
|
||||
php_stream *stream = NULL, *datastream = NULL;
|
||||
php_url *resource = NULL;
|
||||
php_uri *resource = NULL;
|
||||
char tmp_line[512];
|
||||
char ip[sizeof("123.123.123.123")];
|
||||
unsigned short portno;
|
||||
@@ -579,12 +587,12 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa
|
||||
/* remember control stream */
|
||||
datastream->wrapperthis = stream;
|
||||
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
return datastream;
|
||||
|
||||
errexit:
|
||||
if (resource) {
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
}
|
||||
if (stream) {
|
||||
php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result);
|
||||
@@ -683,7 +691,7 @@ static php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const ch
|
||||
{
|
||||
php_stream *stream, *reuseid, *datastream = NULL;
|
||||
php_ftp_dirstream_data *dirsdata;
|
||||
php_url *resource = NULL;
|
||||
php_uri *resource = NULL;
|
||||
int result = 0, use_ssl, use_ssl_on_data = 0;
|
||||
char *hoststart = NULL, tmp_line[512];
|
||||
char ip[sizeof("123.123.123.123")];
|
||||
@@ -745,7 +753,7 @@ static php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const ch
|
||||
goto opendir_errexit;
|
||||
}
|
||||
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
|
||||
dirsdata = emalloc(sizeof *dirsdata);
|
||||
dirsdata->datastream = datastream;
|
||||
@@ -756,7 +764,7 @@ static php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const ch
|
||||
|
||||
opendir_errexit:
|
||||
if (resource) {
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
}
|
||||
if (stream) {
|
||||
php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result);
|
||||
@@ -773,7 +781,7 @@ opendir_errexit:
|
||||
static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context)
|
||||
{
|
||||
php_stream *stream = NULL;
|
||||
php_url *resource = NULL;
|
||||
php_uri *resource = NULL;
|
||||
int result;
|
||||
char tmp_line[512];
|
||||
|
||||
@@ -877,12 +885,12 @@ mdtm_error:
|
||||
#endif
|
||||
#endif
|
||||
php_stream_close(stream);
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
return 0;
|
||||
|
||||
stat_errexit:
|
||||
if (resource) {
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
}
|
||||
if (stream) {
|
||||
php_stream_close(stream);
|
||||
@@ -895,7 +903,7 @@ stat_errexit:
|
||||
static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context)
|
||||
{
|
||||
php_stream *stream = NULL;
|
||||
php_url *resource = NULL;
|
||||
php_uri *resource = NULL;
|
||||
int result;
|
||||
char tmp_line[512];
|
||||
|
||||
@@ -925,13 +933,13 @@ static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, const char *url, i
|
||||
goto unlink_errexit;
|
||||
}
|
||||
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
php_stream_close(stream);
|
||||
return 1;
|
||||
|
||||
unlink_errexit:
|
||||
if (resource) {
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
}
|
||||
if (stream) {
|
||||
php_stream_close(stream);
|
||||
@@ -944,18 +952,30 @@ unlink_errexit:
|
||||
static int php_stream_ftp_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context)
|
||||
{
|
||||
php_stream *stream = NULL;
|
||||
php_url *resource_from = NULL, *resource_to = NULL;
|
||||
php_uri *resource_from = NULL, *resource_to = NULL;
|
||||
int result;
|
||||
char tmp_line[512];
|
||||
|
||||
resource_from = php_url_parse(url_from);
|
||||
resource_to = php_url_parse(url_to);
|
||||
uri_handler_t *uri_handler = php_stream_context_get_uri_handler("ftp", context);
|
||||
if (uri_handler == NULL) {
|
||||
zend_value_error("%s(): Provided stream context has invalid value for the \"uri_parser_class\" option", get_active_function_name());
|
||||
return 0;
|
||||
}
|
||||
|
||||
resource_from = php_uri_parse_to_struct(uri_handler, url_from, strlen(url_from), URI_COMPONENT_READ_RAW, true);
|
||||
if (!resource_from) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
resource_to = php_uri_parse_to_struct(uri_handler, url_to, strlen(url_to), URI_COMPONENT_READ_RAW, true);
|
||||
if (!resource_to) {
|
||||
goto rename_errexit;
|
||||
}
|
||||
|
||||
/* Must be same scheme (ftp/ftp or ftps/ftps), same host, and same port
|
||||
(or a 21/0 0/21 combination which is also "same")
|
||||
Also require paths to/from */
|
||||
if (!resource_from ||
|
||||
!resource_to ||
|
||||
!resource_from->scheme ||
|
||||
if (!resource_from->scheme ||
|
||||
!resource_to->scheme ||
|
||||
!zend_string_equals(resource_from->scheme, resource_to->scheme) ||
|
||||
!resource_from->host ||
|
||||
@@ -999,17 +1019,15 @@ static int php_stream_ftp_rename(php_stream_wrapper *wrapper, const char *url_fr
|
||||
goto rename_errexit;
|
||||
}
|
||||
|
||||
php_url_free(resource_from);
|
||||
php_url_free(resource_to);
|
||||
php_uri_struct_free(resource_from);
|
||||
php_uri_struct_free(resource_to);
|
||||
php_stream_close(stream);
|
||||
return 1;
|
||||
|
||||
rename_errexit:
|
||||
if (resource_from) {
|
||||
php_url_free(resource_from);
|
||||
}
|
||||
php_uri_struct_free(resource_from);
|
||||
if (resource_to) {
|
||||
php_url_free(resource_to);
|
||||
php_uri_struct_free(resource_to);
|
||||
}
|
||||
if (stream) {
|
||||
php_stream_close(stream);
|
||||
@@ -1022,7 +1040,7 @@ rename_errexit:
|
||||
static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, const char *url, int mode, int options, php_stream_context *context)
|
||||
{
|
||||
php_stream *stream = NULL;
|
||||
php_url *resource = NULL;
|
||||
php_uri *resource = NULL;
|
||||
int result, recursive = options & PHP_STREAM_MKDIR_RECURSIVE;
|
||||
char tmp_line[512];
|
||||
|
||||
@@ -1089,7 +1107,7 @@ static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, const char *url, in
|
||||
efree(buf);
|
||||
}
|
||||
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
php_stream_close(stream);
|
||||
|
||||
if (result < 200 || result > 299) {
|
||||
@@ -1101,7 +1119,7 @@ static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, const char *url, in
|
||||
|
||||
mkdir_errexit:
|
||||
if (resource) {
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
}
|
||||
if (stream) {
|
||||
php_stream_close(stream);
|
||||
@@ -1114,7 +1132,7 @@ mkdir_errexit:
|
||||
static int php_stream_ftp_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context)
|
||||
{
|
||||
php_stream *stream = NULL;
|
||||
php_url *resource = NULL;
|
||||
php_uri *resource = NULL;
|
||||
int result;
|
||||
char tmp_line[512];
|
||||
|
||||
@@ -1143,14 +1161,14 @@ static int php_stream_ftp_rmdir(php_stream_wrapper *wrapper, const char *url, in
|
||||
goto rmdir_errexit;
|
||||
}
|
||||
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
php_stream_close(stream);
|
||||
|
||||
return 1;
|
||||
|
||||
rmdir_errexit:
|
||||
if (resource) {
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
}
|
||||
if (stream) {
|
||||
php_stream_close(stream);
|
||||
|
||||
@@ -20,11 +20,13 @@
|
||||
|
||||
#include "php.h"
|
||||
#include "php_globals.h"
|
||||
#include "ext/uri/php_uri.h"
|
||||
#include "php_streams.h"
|
||||
#include "php_network.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/basic_functions.h"
|
||||
#include "zend_smart_str.h"
|
||||
#include "zend_exceptions.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -358,7 +360,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
|
||||
zval *response_header STREAMS_DC) /* {{{ */
|
||||
{
|
||||
php_stream *stream = NULL;
|
||||
php_url *resource = NULL;
|
||||
php_uri *resource = NULL;
|
||||
int use_ssl;
|
||||
int use_proxy = 0;
|
||||
zend_string *tmp = NULL;
|
||||
@@ -391,7 +393,12 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
resource = php_url_parse(path);
|
||||
uri_handler_t *uri_handler = php_stream_context_get_uri_handler("http", context);
|
||||
if (uri_handler == NULL) {
|
||||
zend_value_error("%s(): Provided stream context has invalid value for the \"uri_parser_class\" option", get_active_function_name());
|
||||
return NULL;
|
||||
}
|
||||
resource = php_uri_parse_to_struct(uri_handler, path, strlen(path), URI_COMPONENT_READ_RAW, true);
|
||||
if (resource == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -403,7 +410,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
|
||||
(tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "proxy")) == NULL ||
|
||||
Z_TYPE_P(tmpzval) != IS_STRING ||
|
||||
Z_STRLEN_P(tmpzval) == 0) {
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
return php_stream_open_wrapper_ex(path, mode, REPORT_ERRORS, NULL, context);
|
||||
}
|
||||
/* Called from a non-http wrapper with http proxying requested (i.e. ftp) */
|
||||
@@ -416,7 +423,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
|
||||
|
||||
if (strpbrk(mode, "awx+")) {
|
||||
php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper does not support writeable connections");
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -445,7 +452,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
|
||||
|
||||
if (request_fulluri && (strchr(path, '\n') != NULL || strchr(path, '\r') != NULL)) {
|
||||
php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper full URI path does not allow CR or LF characters");
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
zend_string_release(transport_string);
|
||||
return NULL;
|
||||
}
|
||||
@@ -461,7 +468,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
|
||||
if (d > timeoutmax) {
|
||||
php_stream_wrapper_log_error(wrapper, options, "timeout must be lower than " ZEND_ULONG_FMT, (zend_ulong)timeoutmax);
|
||||
zend_string_release(transport_string);
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
return NULL;
|
||||
}
|
||||
#ifndef PHP_WIN32
|
||||
@@ -742,33 +749,31 @@ finish:
|
||||
|
||||
/* auth header if it was specified */
|
||||
if (((have_header & HTTP_HEADER_AUTH) == 0) && resource->user) {
|
||||
/* make scratch large enough to hold the whole URL (over-estimate) */
|
||||
size_t scratch_len = strlen(path) + 1;
|
||||
char *scratch = emalloc(scratch_len);
|
||||
zend_string *stmp;
|
||||
smart_str scratch = {0};
|
||||
|
||||
/* decode the strings first */
|
||||
php_url_decode(ZSTR_VAL(resource->user), ZSTR_LEN(resource->user));
|
||||
|
||||
strcpy(scratch, ZSTR_VAL(resource->user));
|
||||
strcat(scratch, ":");
|
||||
smart_str_append(&scratch, resource->user);
|
||||
smart_str_appendc(&scratch, ':');
|
||||
|
||||
/* Note: password is optional! */
|
||||
if (resource->pass) {
|
||||
php_url_decode(ZSTR_VAL(resource->pass), ZSTR_LEN(resource->pass));
|
||||
strcat(scratch, ZSTR_VAL(resource->pass));
|
||||
if (resource->password) {
|
||||
php_url_decode(ZSTR_VAL(resource->password), ZSTR_LEN(resource->password));
|
||||
smart_str_append(&scratch, resource->password);
|
||||
}
|
||||
|
||||
stmp = php_base64_encode((unsigned char*)scratch, strlen(scratch));
|
||||
zend_string *scratch_str = smart_str_extract(&scratch);
|
||||
zend_string *stmp = php_base64_encode((unsigned char*)ZSTR_VAL(scratch_str), ZSTR_LEN(scratch_str));
|
||||
|
||||
smart_str_appends(&req_buf, "Authorization: Basic ");
|
||||
smart_str_appends(&req_buf, ZSTR_VAL(stmp));
|
||||
smart_str_append(&req_buf, stmp);
|
||||
smart_str_appends(&req_buf, "\r\n");
|
||||
|
||||
php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, NULL, 0);
|
||||
|
||||
zend_string_efree(scratch_str);
|
||||
zend_string_free(stmp);
|
||||
efree(scratch);
|
||||
}
|
||||
|
||||
/* if the user has configured who they are, send a From: line */
|
||||
@@ -1090,9 +1095,9 @@ finish:
|
||||
header_info.location = NULL;
|
||||
}
|
||||
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
/* check for invalid redirection URLs */
|
||||
if ((resource = php_url_parse(new_path)) == NULL) {
|
||||
if ((resource = php_uri_parse_to_struct(uri_handler, new_path, strlen(new_path), URI_COMPONENT_READ_RAW, true)) == NULL) {
|
||||
php_stream_wrapper_log_error(wrapper, options, "Invalid redirect URL! %s", new_path);
|
||||
efree(new_path);
|
||||
goto out;
|
||||
@@ -1116,7 +1121,7 @@ finish:
|
||||
/* check for control characters in login, password & path */
|
||||
if (strncasecmp(new_path, "http://", sizeof("http://") - 1) || strncasecmp(new_path, "https://", sizeof("https://") - 1)) {
|
||||
CHECK_FOR_CNTRL_CHARS(resource->user);
|
||||
CHECK_FOR_CNTRL_CHARS(resource->pass);
|
||||
CHECK_FOR_CNTRL_CHARS(resource->password);
|
||||
CHECK_FOR_CNTRL_CHARS(resource->path);
|
||||
}
|
||||
int new_flags = HTTP_WRAPPER_REDIRECTED;
|
||||
@@ -1147,7 +1152,7 @@ out:
|
||||
}
|
||||
|
||||
if (resource) {
|
||||
php_url_free(resource);
|
||||
php_uri_struct_free(resource);
|
||||
}
|
||||
|
||||
if (stream) {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
Test file_get_contents() function when a custom URI parser is configured
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
try {
|
||||
$context = stream_context_create([
|
||||
"http" => [
|
||||
"uri_parser_class" => "not-exists",
|
||||
],
|
||||
]);
|
||||
var_dump(file_get_contents("https://example.com", context: $context));
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
$context = stream_context_create([
|
||||
"http" => [
|
||||
"uri_parser_class" => null,
|
||||
],
|
||||
]);
|
||||
var_dump(file_get_contents("https:///example.com", context: $context)); // invalid for parse_url only, valid for the other handlers
|
||||
|
||||
$context = stream_context_create([
|
||||
"http" => [
|
||||
"uri_parser_class" => \Uri\Rfc3986\Uri::class,
|
||||
],
|
||||
]);
|
||||
var_dump(file_get_contents("https://éxamplé.com", context: $context)); // invalid for RFC 3986 only, valid for the other handlers
|
||||
|
||||
$context = stream_context_create([
|
||||
"http" => [
|
||||
"uri_parser_class" => \Uri\WhatWg\Url::class,
|
||||
],
|
||||
]);
|
||||
var_dump(file_get_contents("https://exa%23mple.org", context: $context)); // invalid for WHATWG only, valid for the other handlers
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
file_get_contents(): Provided stream context has invalid value for the "uri_parser_class" option
|
||||
|
||||
Warning: file_get_contents(https:///example.com): Failed to open stream: operation failed in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: file_get_contents(https://éxamplé.com): Failed to open stream: operation failed in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: file_get_contents(https://exa%23mple.org): Failed to open stream: operation failed in %s on line %d
|
||||
bool(false)
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "file.h"
|
||||
#include "zend_simd.h"
|
||||
#include "Zend/zend_smart_str.h"
|
||||
#include "Zend/zend_exceptions.h"
|
||||
#include "ext/uri/php_uri.h"
|
||||
|
||||
/* {{{ free_url */
|
||||
PHPAPI void php_url_free(php_url *theurl)
|
||||
@@ -47,6 +49,13 @@ PHPAPI void php_url_free(php_url *theurl)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void parse_url_free_uri(void *uri)
|
||||
{
|
||||
php_url *parse_url_uri = (php_url *) uri;
|
||||
|
||||
php_url_free(parse_url_uri);
|
||||
}
|
||||
|
||||
static void php_replace_controlchars(char *str, size_t len)
|
||||
{
|
||||
unsigned char *s = (unsigned char *)str;
|
||||
@@ -311,7 +320,166 @@ parse_host:
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void parse_url_decode_component(zval *zv, uri_component_read_mode_t read_mode)
|
||||
{
|
||||
if (Z_TYPE_P(zv) != IS_STRING) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (read_mode == URI_COMPONENT_READ_RAW) {
|
||||
return;
|
||||
}
|
||||
|
||||
php_raw_url_decode(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
|
||||
}
|
||||
|
||||
static zend_result parse_url_read_scheme(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
|
||||
{
|
||||
php_url *parse_url_uri = internal_uri->uri;
|
||||
|
||||
if (parse_url_uri->scheme) {
|
||||
ZVAL_STR_COPY(retval, parse_url_uri->scheme);
|
||||
parse_url_decode_component(retval, read_mode);
|
||||
} 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 = internal_uri->uri;
|
||||
|
||||
if (parse_url_uri->user) {
|
||||
ZVAL_STR_COPY(retval, parse_url_uri->user);
|
||||
parse_url_decode_component(retval, read_mode);
|
||||
} 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 = internal_uri->uri;
|
||||
|
||||
if (parse_url_uri->pass) {
|
||||
ZVAL_STR_COPY(retval, parse_url_uri->pass);
|
||||
parse_url_decode_component(retval, read_mode);
|
||||
} 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 = internal_uri->uri;
|
||||
|
||||
if (parse_url_uri->host) {
|
||||
ZVAL_STR_COPY(retval, parse_url_uri->host);
|
||||
parse_url_decode_component(retval, read_mode);
|
||||
} 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 = internal_uri->uri;
|
||||
|
||||
if (parse_url_uri->port) {
|
||||
ZVAL_LONG(retval, parse_url_uri->port);
|
||||
parse_url_decode_component(retval, read_mode);
|
||||
} 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 = internal_uri->uri;
|
||||
|
||||
if (parse_url_uri->path) {
|
||||
ZVAL_STR_COPY(retval, parse_url_uri->path);
|
||||
parse_url_decode_component(retval, read_mode);
|
||||
} 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 = internal_uri->uri;
|
||||
|
||||
if (parse_url_uri->query) {
|
||||
ZVAL_STR_COPY(retval, parse_url_uri->query);
|
||||
parse_url_decode_component(retval, read_mode);
|
||||
} 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 = internal_uri->uri;
|
||||
|
||||
if (parse_url_uri->fragment) {
|
||||
ZVAL_STR_COPY(retval, parse_url_uri->fragment);
|
||||
parse_url_decode_component(retval, read_mode);
|
||||
} else {
|
||||
ZVAL_NULL(retval);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static void throw_invalid_uri_exception(void)
|
||||
{
|
||||
zend_throw_exception(uri_invalid_uri_exception_ce, "The specified URI is malformed", 0);
|
||||
}
|
||||
|
||||
static void *parse_url_parse_uri(const char *uri_str, size_t uri_str_len, const void *base_url, zval *errors, bool silent)
|
||||
{
|
||||
bool has_port;
|
||||
|
||||
php_url *url = php_url_parse_ex2(uri_str, uri_str_len, &has_port);
|
||||
if (url == NULL && !silent) {
|
||||
throw_invalid_uri_exception();
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
const uri_handler_t parse_url_uri_handler = {
|
||||
.name = URI_PARSER_PHP,
|
||||
.parse_uri = parse_url_parse_uri,
|
||||
.clone_uri = NULL,
|
||||
.uri_to_string = NULL,
|
||||
.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 +921,8 @@ no_name_header:
|
||||
php_stream_close(stream);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHP_MINIT_FUNCTION(url)
|
||||
{
|
||||
return php_uri_handler_register(&parse_url_uri_handler);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef URL_H
|
||||
#define URL_H
|
||||
|
||||
PHP_MINIT_FUNCTION(url);
|
||||
|
||||
typedef struct php_url {
|
||||
zend_string *scheme;
|
||||
zend_string *user;
|
||||
|
||||
@@ -562,11 +562,11 @@ void lexbor_request_shutdown(void)
|
||||
lexbor_urls = 0;
|
||||
}
|
||||
|
||||
lxb_url_t *lexbor_parse_uri_ex(const zend_string *uri_str, const lxb_url_t *lexbor_base_url, zval *errors, bool silent)
|
||||
lxb_url_t *lexbor_parse_uri_ex(const char *uri_str, size_t uri_str_len, const lxb_url_t *lexbor_base_url, zval *errors, bool silent)
|
||||
{
|
||||
lexbor_cleanup_parser();
|
||||
|
||||
lxb_url_t *url = lxb_url_parse(&lexbor_parser, lexbor_base_url, (unsigned char *) ZSTR_VAL(uri_str), ZSTR_LEN(uri_str));
|
||||
lxb_url_t *url = lxb_url_parse(&lexbor_parser, lexbor_base_url, (unsigned char *) uri_str, uri_str_len);
|
||||
const char *reason = fill_errors(errors);
|
||||
|
||||
if (url == NULL && !silent) {
|
||||
@@ -577,9 +577,9 @@ lxb_url_t *lexbor_parse_uri_ex(const zend_string *uri_str, const lxb_url_t *lexb
|
||||
return url;
|
||||
}
|
||||
|
||||
static void *lexbor_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors, bool silent)
|
||||
static void *lexbor_parse_uri(const char *uri_str, size_t uri_str_len, const void *base_url, zval *errors, bool silent)
|
||||
{
|
||||
return lexbor_parse_uri_ex(uri_str, base_url, errors, silent);
|
||||
return lexbor_parse_uri_ex(uri_str, uri_str_len, base_url, errors, silent);
|
||||
}
|
||||
|
||||
static void *lexbor_clone_uri(void *uri)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
extern const uri_handler_t lexbor_uri_handler;
|
||||
|
||||
lxb_url_t *lexbor_parse_uri_ex(const zend_string *uri_str, const lxb_url_t *lexbor_base_url, zval *errors, bool silent);
|
||||
lxb_url_t *lexbor_parse_uri_ex(const char *uri_str, size_t uri_str_len, const lxb_url_t *lexbor_base_url, zval *errors, bool silent);
|
||||
|
||||
zend_result lexbor_request_init(void);
|
||||
void lexbor_request_shutdown(void);
|
||||
|
||||
@@ -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,205 @@ 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(URI_PARSER_PHP, sizeof(URI_PARSER_PHP) - 1);
|
||||
}
|
||||
|
||||
return uri_handler_by_name(ZSTR_VAL(uri_handler_name), ZSTR_LEN(uri_handler_name));
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI uri_internal_t *php_uri_parse(const uri_handler_t *uri_handler, const char *uri_str, size_t uri_str_len, bool silent)
|
||||
{
|
||||
uri_internal_t *internal_uri = emalloc(sizeof(*internal_uri));
|
||||
internal_uri->handler = uri_handler;
|
||||
internal_uri->uri = uri_handler->parse_uri(uri_str, uri_str_len, NULL, NULL, silent);
|
||||
|
||||
if (UNEXPECTED(internal_uri->uri == NULL)) {
|
||||
efree(internal_uri);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return internal_uri;
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL 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;
|
||||
}
|
||||
|
||||
zend_result result = property_handler->read_func(internal_uri, read_mode, zv);
|
||||
|
||||
ZEND_ASSERT(result == FAILURE || (Z_TYPE_P(zv) == IS_STRING && GC_REFCOUNT(Z_STR_P(zv)) == 2) || Z_TYPE_P(zv) == IS_NULL || Z_TYPE_P(zv) == IS_LONG);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL 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);
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL 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);
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL 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);
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL 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);
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL 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);
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL 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);
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL 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);
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL 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);
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL 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);
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI php_uri *php_uri_parse_to_struct(
|
||||
const uri_handler_t *uri_handler, const char *uri_str, size_t uri_str_len, uri_component_read_mode_t read_mode, bool silent
|
||||
) {
|
||||
uri_internal_t *uri_internal = php_uri_parse(uri_handler, uri_str, uri_str_len, silent);
|
||||
if (uri_internal == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
php_uri *uri = ecalloc(1, sizeof(*uri));
|
||||
zval tmp;
|
||||
zend_result result;
|
||||
|
||||
result = php_uri_get_scheme(uri_internal, read_mode, &tmp);
|
||||
if (result == FAILURE) {
|
||||
goto error;
|
||||
}
|
||||
if (Z_TYPE(tmp) == IS_STRING) {
|
||||
uri->scheme = Z_STR(tmp);
|
||||
}
|
||||
|
||||
result = php_uri_get_username(uri_internal, read_mode, &tmp);
|
||||
if (result == FAILURE) {
|
||||
goto error;
|
||||
}
|
||||
if (Z_TYPE(tmp) == IS_STRING) {
|
||||
uri->user = Z_STR(tmp);
|
||||
}
|
||||
|
||||
result = php_uri_get_password(uri_internal, read_mode, &tmp);
|
||||
if (result == FAILURE) {
|
||||
goto error;
|
||||
}
|
||||
if (Z_TYPE(tmp) == IS_STRING) {
|
||||
uri->password = Z_STR(tmp);
|
||||
}
|
||||
|
||||
result = php_uri_get_host(uri_internal, read_mode, &tmp);
|
||||
if (result == FAILURE) {
|
||||
goto error;
|
||||
}
|
||||
if (Z_TYPE(tmp) == IS_STRING) {
|
||||
uri->host = Z_STR(tmp);
|
||||
}
|
||||
|
||||
result = php_uri_get_port(uri_internal, read_mode, &tmp);
|
||||
if (result == FAILURE) {
|
||||
goto error;
|
||||
}
|
||||
if (Z_TYPE(tmp) == IS_LONG) {
|
||||
uri->port = Z_LVAL(tmp);
|
||||
}
|
||||
|
||||
result = php_uri_get_path(uri_internal, read_mode, &tmp);
|
||||
if (result == FAILURE) {
|
||||
goto error;
|
||||
}
|
||||
if (Z_TYPE(tmp) == IS_STRING) {
|
||||
uri->path = Z_STR(tmp);
|
||||
}
|
||||
|
||||
result = php_uri_get_query(uri_internal, read_mode, &tmp);
|
||||
if (result == FAILURE) {
|
||||
goto error;
|
||||
}
|
||||
if (Z_TYPE(tmp) == IS_STRING) {
|
||||
uri->query = Z_STR(tmp);
|
||||
}
|
||||
|
||||
result = php_uri_get_fragment(uri_internal, read_mode, &tmp);
|
||||
if (result == FAILURE) {
|
||||
goto error;
|
||||
}
|
||||
if (Z_TYPE(tmp) == IS_STRING) {
|
||||
uri->fragment = Z_STR(tmp);
|
||||
}
|
||||
|
||||
php_uri_free(uri_internal);
|
||||
|
||||
return uri;
|
||||
|
||||
error:
|
||||
php_uri_free(uri_internal);
|
||||
php_uri_struct_free(uri);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL 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.
|
||||
@@ -136,7 +335,7 @@ static zend_result pass_errors_by_ref_and_free(zval *errors_zv, zval *errors)
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHPAPI void php_uri_instantiate_uri(
|
||||
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) 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
|
||||
) {
|
||||
@@ -150,7 +349,7 @@ PHPAPI void php_uri_instantiate_uri(
|
||||
base_url = internal_base_url->uri;
|
||||
}
|
||||
|
||||
void *uri = handler->parse_uri(uri_str, base_url, should_throw || errors_zv != NULL ? &errors : NULL, !should_throw);
|
||||
void *uri = handler->parse_uri(ZSTR_VAL(uri_str), ZSTR_LEN(uri_str), base_url, should_throw || errors_zv != NULL ? &errors : NULL, !should_throw);
|
||||
if (UNEXPECTED(uri == NULL)) {
|
||||
if (should_throw) {
|
||||
zval_ptr_dtor(&errors);
|
||||
@@ -573,7 +772,7 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *handler_na
|
||||
if (internal_uri->uri != NULL) {
|
||||
internal_uri->handler->free_uri(internal_uri->uri);
|
||||
}
|
||||
internal_uri->uri = internal_uri->handler->parse_uri(Z_STR_P(uri_zv), NULL, NULL, true);
|
||||
internal_uri->uri = internal_uri->handler->parse_uri(Z_STRVAL_P(uri_zv), Z_STRLEN_P(uri_zv), NULL, NULL, true);
|
||||
if (internal_uri->uri == NULL) {
|
||||
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name));
|
||||
RETURN_THROWS();
|
||||
@@ -762,7 +961,7 @@ PHP_METHOD(Uri_WhatWg_Url, __debugInfo)
|
||||
|
||||
static zend_object *uri_create_object_handler(zend_class_entry *class_type)
|
||||
{
|
||||
uri_object_t *uri_object = zend_object_alloc(sizeof(uri_object_t), class_type);
|
||||
uri_object_t *uri_object = zend_object_alloc(sizeof(*uri_object), class_type);
|
||||
|
||||
zend_object_std_init(&uri_object->std, class_type);
|
||||
object_properties_init(&uri_object->std, class_type);
|
||||
@@ -806,7 +1005,7 @@ zend_object *uri_clone_obj_handler(zend_object *object)
|
||||
return &new_uri_object->std;
|
||||
}
|
||||
|
||||
PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers)
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers)
|
||||
{
|
||||
ce->create_object = uri_create_object_handler;
|
||||
ce->default_object_handlers = object_handlers;
|
||||
@@ -816,14 +1015,14 @@ PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zen
|
||||
object_handlers->clone_obj = uri_clone_obj_handler;
|
||||
}
|
||||
|
||||
zend_result uri_handler_register(const uri_handler_t *uri_handler)
|
||||
PHPAPI zend_result php_uri_handler_register(const uri_handler_t *uri_handler)
|
||||
{
|
||||
zend_string *key = zend_string_init_interned(uri_handler->name, strlen(uri_handler->name), 1);
|
||||
zend_string *key = zend_string_init_interned(uri_handler->name, strlen(uri_handler->name), true);
|
||||
|
||||
ZEND_ASSERT(uri_handler->name != NULL);
|
||||
ZEND_ASSERT(uri_handler->parse_uri != NULL);
|
||||
ZEND_ASSERT(uri_handler->clone_uri != NULL);
|
||||
ZEND_ASSERT(uri_handler->uri_to_string != NULL);
|
||||
ZEND_ASSERT(uri_handler->clone_uri != NULL || strcmp(uri_handler->name, URI_PARSER_PHP) == 0);
|
||||
ZEND_ASSERT(uri_handler->uri_to_string != NULL || strcmp(uri_handler->name, URI_PARSER_PHP) == 0);
|
||||
ZEND_ASSERT(uri_handler->free_uri != NULL);
|
||||
|
||||
zend_result result = zend_hash_add_ptr(&uri_handlers, key, (void *) uri_handler) != NULL ? SUCCESS : FAILURE;
|
||||
@@ -850,11 +1049,11 @@ static PHP_MINIT_FUNCTION(uri)
|
||||
|
||||
zend_hash_init(&uri_handlers, 4, NULL, NULL, true);
|
||||
|
||||
if (PHP_MINIT(uri_uriparser)(INIT_FUNC_ARGS_PASSTHRU) == FAILURE) {
|
||||
if (php_uri_handler_register(&uriparser_uri_handler) == FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (uri_handler_register(&lexbor_uri_handler) == FAILURE) {
|
||||
if (php_uri_handler_register(&lexbor_uri_handler) == FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,193 @@
|
||||
extern zend_module_entry uri_module_entry;
|
||||
#define phpext_uri_ptr &uri_module_entry
|
||||
|
||||
PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers);
|
||||
typedef struct php_uri {
|
||||
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;
|
||||
|
||||
/**
|
||||
* Registers a URI handler. The handler must have a unique name.
|
||||
*
|
||||
* @param uri_handler The URI handler
|
||||
* @return SUCCESS in case of success, FAILURE otherwise
|
||||
*/
|
||||
PHPAPI zend_result php_uri_handler_register(const uri_handler_t *uri_handler);
|
||||
|
||||
/**
|
||||
* Returns the registered URI handler based on uri_handler_name.
|
||||
*
|
||||
* @param uri_handler_name The URI handler name
|
||||
* @return The URI handler
|
||||
*/
|
||||
PHPAPI uri_handler_t *php_uri_get_handler(const zend_string *uri_handler_name);
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI uri_internal_t *php_uri_parse(const uri_handler_t *uri_handler, const char *uri_str, size_t uri_str_len, bool silent);
|
||||
|
||||
/**
|
||||
* Retrieves the scheme component based on the read_mode and passes it to the zv ZVAL in case of success.
|
||||
*
|
||||
* Read_mode can be one of the following:
|
||||
* - URI_COMPONENT_READ_RAW: Retrieves the raw, non-normalized variant of the URI component
|
||||
* - URI_COMPONENT_READ_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters
|
||||
* - URI_COMPONENT_READ_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints
|
||||
*
|
||||
* @param internal_uri The internal URI whose uri member is used to retrieve the component
|
||||
* @param read_mode The read mode
|
||||
* @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL).
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_scheme(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
|
||||
|
||||
/**
|
||||
* Retrieves the username component based on the read_mode and passes it to the zv ZVAL in case of success.
|
||||
*
|
||||
* Read_mode can be one of the following:
|
||||
* - URI_COMPONENT_READ_RAW: Retrieves the raw, non-normalized variant of the URI component
|
||||
* - URI_COMPONENT_READ_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters
|
||||
* - URI_COMPONENT_READ_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints
|
||||
*
|
||||
* @param internal_uri The internal URI whose uri member is used to retrieve the component
|
||||
* @param read_mode The read mode
|
||||
* @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL).
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_username(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
|
||||
|
||||
/**
|
||||
* Retrieves the password component based on the read_mode and passes it to the zv ZVAL in case of success.
|
||||
*
|
||||
* Read_mode can be one of the following:
|
||||
* - URI_COMPONENT_READ_RAW: Retrieves the raw, non-normalized variant of the URI component
|
||||
* - URI_COMPONENT_READ_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters
|
||||
* - URI_COMPONENT_READ_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints
|
||||
*
|
||||
* @param internal_uri The internal URI whose uri member is used to retrieve the component
|
||||
* @param read_mode The read mode
|
||||
* @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL).
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_password(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
|
||||
|
||||
/**
|
||||
* Retrieves the host component based on the read_mode and passes it to the zv ZVAL in case of success.
|
||||
*
|
||||
* Read_mode can be one of the following:
|
||||
* - URI_COMPONENT_READ_RAW: Retrieves the raw, non-normalized variant of the URI component
|
||||
* - URI_COMPONENT_READ_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters
|
||||
* - URI_COMPONENT_READ_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints
|
||||
*
|
||||
* @param internal_uri The internal URI whose uri member is used to retrieve the component
|
||||
* @param read_mode The read mode
|
||||
* @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL).
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_host(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
|
||||
|
||||
/**
|
||||
* Retrieves the port component based on the read_mode and passes it to the zv ZVAL in case of success.
|
||||
*
|
||||
* Read_mode can be one of the following:
|
||||
* - URI_COMPONENT_READ_RAW: Retrieves the raw, non-normalized variant of the URI component
|
||||
* - URI_COMPONENT_READ_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters
|
||||
* - URI_COMPONENT_READ_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints
|
||||
*
|
||||
* @param internal_uri The internal URI whose uri member is used to retrieve the component
|
||||
* @param read_mode The read mode
|
||||
* @param zv The output parameter containing the retrieved component as a ZVAL (either IS_LONG or IS_NULL).
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_port(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
|
||||
|
||||
/**
|
||||
* Retrieves the path component based on the read_mode and passes it to the zv ZVAL in case of success.
|
||||
*
|
||||
* Read_mode can be one of the following:
|
||||
* - URI_COMPONENT_READ_RAW: Retrieves the raw, non-normalized variant of the URI component
|
||||
* - URI_COMPONENT_READ_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters
|
||||
* - URI_COMPONENT_READ_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints
|
||||
*
|
||||
* @param internal_uri The internal URI whose uri member is used to retrieve the component
|
||||
* @param read_mode The read mode
|
||||
* @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL).
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_path(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
|
||||
|
||||
/**
|
||||
* Retrieves the query component based on the read_mode and passes it to the zv ZVAL in case of success.
|
||||
*
|
||||
* Read_mode can be one of the following:
|
||||
* - URI_COMPONENT_READ_RAW: Retrieves the raw, non-normalized variant of the URI component
|
||||
* - URI_COMPONENT_READ_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters
|
||||
* - URI_COMPONENT_READ_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints
|
||||
*
|
||||
* @param internal_uri The internal URI whose uri member is used to retrieve the component
|
||||
* @param read_mode The read mode
|
||||
* @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL).
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_query(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
|
||||
|
||||
/**
|
||||
* Retrieves the fragment component based on the read_mode and passes it to the zv ZVAL in case of success.
|
||||
*
|
||||
* Read_mode can be one of the following:
|
||||
* - URI_COMPONENT_READ_RAW: Retrieves the raw, non-normalized variant of the URI component
|
||||
* - URI_COMPONENT_READ_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters
|
||||
* - URI_COMPONENT_READ_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints
|
||||
*
|
||||
* @param internal_uri The internal URI whose uri member is used to retrieve the component
|
||||
* @param read_mode The read mode
|
||||
* @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL).
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_fragment(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
|
||||
|
||||
/**
|
||||
* Frees the uri member within the provided internal URI.
|
||||
*
|
||||
* @param internal_uri The internal URI
|
||||
*/
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_free(uri_internal_t *internal_uri);
|
||||
|
||||
/**
|
||||
* Creates a new php_uri struct containing all the URI components. The components are retrieved based on the read_mode parameter.
|
||||
*
|
||||
* Read_mode can be one of the following:
|
||||
* - URI_COMPONENT_READ_RAW: Retrieves the raw, non-normalized variant of the URI component
|
||||
* - URI_COMPONENT_READ_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters
|
||||
* - URI_COMPONENT_READ_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints
|
||||
*
|
||||
* @param uri_handler The URI handler whose parse_uri() handler is called
|
||||
* @param uri_str The input string that is going to be parsed
|
||||
* @param uri_str_len Length of the input string
|
||||
* @param read_mode The read mode based on which components are retrieved
|
||||
* @param silent Whether to throw a Uri\InvalidUriException in case of failure
|
||||
* @return The created php_uri struct in case of success, NULL otherwise
|
||||
*/
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI php_uri *php_uri_parse_to_struct(
|
||||
const uri_handler_t *uri_handler, const char *uri_str, size_t uri_str_len, uri_component_read_mode_t read_mode, bool silent
|
||||
);
|
||||
|
||||
/**
|
||||
* Frees the provided php_uri struct.
|
||||
*
|
||||
* @param uri The php_uri struct to free
|
||||
*/
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_struct_free(php_uri *uri);
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) 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
|
||||
);
|
||||
|
||||
ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -76,10 +76,13 @@ typedef struct uri_property_handlers_t {
|
||||
} uri_property_handlers_t;
|
||||
|
||||
typedef struct uri_handler_t {
|
||||
/**
|
||||
* Name (the FQCN) of the URI handler. The "" name is reserved for the handler of the legacy parse_url().
|
||||
*/
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* Parse a URI string into a URI.
|
||||
* Parses a URI string into a URI.
|
||||
*
|
||||
* If the URI string is valid, a URI is returned. In case of failure, NULL is
|
||||
* returned.
|
||||
@@ -93,10 +96,46 @@ typedef struct uri_handler_t {
|
||||
*
|
||||
* If the silent parameter is true, a Uri\InvalidUriException instance must be thrown.
|
||||
* If the parameter is false, the possible errors should be handled by the caller.
|
||||
*
|
||||
* @param uri_str The input string that is going to be parsed
|
||||
* @param uri_str_len Length of the input string
|
||||
* @param base_url The base URI if reference resolution should be performed, otherwise NULL
|
||||
* @param errors An out parameter that stores additional error information
|
||||
* @param silent Whether to throw a Uri\InvalidUriException in case of failure
|
||||
*/
|
||||
void *(*parse_uri)(const char *uri_str, size_t uri_str_len, const void *base_url, zval *errors, bool silent);
|
||||
|
||||
/**
|
||||
* Clones a URI to a new URI.
|
||||
*
|
||||
* A deep-clone must be performed that copies all pointer members to a new memory address.
|
||||
* @param uri The input URI
|
||||
* @return The cloned URI
|
||||
*/
|
||||
void *(*parse_uri)(const zend_string *uri_str, const void *base_url, zval *errors, bool silent);
|
||||
void *(*clone_uri)(void *uri);
|
||||
|
||||
/**
|
||||
* Recomposes a URI as a string according to the recomposition_mode and exclude_fragment parameters.
|
||||
* The returned zend_string must not be persistent.
|
||||
*
|
||||
* Recomposition_mode can be one of the following:
|
||||
* - URI_RECOMPOSITION_RAW_ASCII: Recomposes the raw, non-normalized variant of the URI as a string that must only contain ASCII characters
|
||||
* - URI_RECOMPOSITION_RAW_UNICODE: Recomposes the raw, non-normalized variant of the URI as a string that may contain Unicode codepoints
|
||||
* - URI_RECOMPOSITION_NORMALIZED_ASCII: Recomposes the normalized variant of the URI as a string that must only contain ASCII characters
|
||||
* - URI_RECOMPOSITION_NORMALIZED_UNICODE: Recomposes the normalized variant of the URI as a string that may contain Unicode codepoints
|
||||
*
|
||||
* @param uri The input URI
|
||||
* @param recomposition_mode The type of recomposition
|
||||
* @param exclude_fragment Whether the fragment component should be part of the recomposed URI
|
||||
* @return The recomposed URI as a non-persistent zend_string
|
||||
*/
|
||||
zend_string *(*uri_to_string)(void *uri, uri_recomposition_mode_t recomposition_mode, bool exclude_fragment);
|
||||
|
||||
/**
|
||||
* Frees the provided URI.
|
||||
*
|
||||
* @param uri The input URI
|
||||
*/
|
||||
void (*free_uri)(void *uri);
|
||||
|
||||
const uri_property_handlers_t property_handlers;
|
||||
@@ -125,9 +164,9 @@ 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);
|
||||
const uri_property_handler_t *uri_property_handler_from_internal_uri(const uri_internal_t *internal_uri, uri_property_name_t property_name);
|
||||
void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name, uri_component_read_mode_t component_read_mode);
|
||||
void uri_write_component_str(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name);
|
||||
|
||||
@@ -275,15 +275,6 @@ ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_fragment(const uri_inte
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_MINIT_FUNCTION(uri_uriparser)
|
||||
{
|
||||
if (uri_handler_register(&uriparser_uri_handler) == FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static uriparser_uris_t *uriparser_create_uris(void)
|
||||
{
|
||||
uriparser_uris_t *uriparser_uris = ecalloc(1, sizeof(*uriparser_uris));
|
||||
@@ -292,12 +283,12 @@ static uriparser_uris_t *uriparser_create_uris(void)
|
||||
return uriparser_uris;
|
||||
}
|
||||
|
||||
void *uriparser_parse_uri_ex(const zend_string *uri_str, const uriparser_uris_t *uriparser_base_urls, bool silent)
|
||||
void *uriparser_parse_uri_ex(const char *uri_str, size_t uri_str_len, const uriparser_uris_t *uriparser_base_urls, bool silent)
|
||||
{
|
||||
UriUriA uri = {0};
|
||||
|
||||
/* Parse the URI. */
|
||||
if (uriParseSingleUriExMmA(&uri, ZSTR_VAL(uri_str), ZSTR_VAL(uri_str) + ZSTR_LEN(uri_str), NULL, mm) != URI_SUCCESS) {
|
||||
if (uriParseSingleUriExMmA(&uri, uri_str, uri_str + uri_str_len, NULL, mm) != URI_SUCCESS) {
|
||||
if (!silent) {
|
||||
zend_throw_exception(uri_invalid_uri_exception_ce, "The specified URI is malformed", 0);
|
||||
}
|
||||
@@ -347,13 +338,12 @@ void *uriparser_parse_uri_ex(const zend_string *uri_str, const uriparser_uris_t
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *uriparser_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors, bool silent)
|
||||
void *uriparser_parse_uri(const char *uri_str, size_t uri_str_len, const void *base_url, zval *errors, bool silent)
|
||||
{
|
||||
return uriparser_parse_uri_ex(uri_str, base_url, silent);
|
||||
return uriparser_parse_uri_ex(uri_str, uri_str_len, base_url, silent);
|
||||
}
|
||||
|
||||
/* TODO make the clone handler accept a flag to distinguish between clone() calls and withers.
|
||||
* When calling a wither successfully, the normalized URI is surely invalidated, therefore
|
||||
/* When calling a wither successfully, the normalized URI is surely invalidated, therefore
|
||||
* it doesn't make sense to copy it. In case of failure, an exception is thrown, and the URI object
|
||||
* is discarded altogether. */
|
||||
ZEND_ATTRIBUTE_NONNULL static void *uriparser_clone_uri(void *uri)
|
||||
|
||||
@@ -28,10 +28,8 @@ typedef struct uriparser_uris_t {
|
||||
bool normalized_uri_initialized;
|
||||
} uriparser_uris_t;
|
||||
|
||||
PHP_MINIT_FUNCTION(uri_uriparser);
|
||||
|
||||
zend_result uriparser_read_userinfo(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval);
|
||||
|
||||
void *uriparser_parse_uri_ex(const zend_string *uri_str, const uriparser_uris_t *uriparser_base_url, bool silent);
|
||||
void *uriparser_parse_uri_ex(const char *uri_str, size_t uri_str_len, const uriparser_uris_t *uriparser_base_url, bool silent);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -65,6 +65,10 @@ PHPAPI void php_stream_context_set_option(php_stream_context *context,
|
||||
const char *wrappername, const char *optionname, zval *optionvalue);
|
||||
void php_stream_context_unset_option(php_stream_context *context,
|
||||
const char *wrappername, const char *optionname);
|
||||
|
||||
struct uri_handler_t;
|
||||
|
||||
PHPAPI struct uri_handler_t *php_stream_context_get_uri_handler(const char *wrappername, php_stream_context *context);
|
||||
PHPAPI php_stream_notifier *php_stream_notification_alloc(void);
|
||||
PHPAPI void php_stream_notification_free(php_stream_notifier *notifier);
|
||||
END_EXTERN_C()
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "ext/standard/file.h"
|
||||
#include "ext/standard/basic_functions.h" /* for BG(CurrentStatFile) */
|
||||
#include "ext/standard/php_string.h" /* for php_memnstr, used by php_stream_get_record() */
|
||||
#include "ext/uri/php_uri.h"
|
||||
#include <stddef.h>
|
||||
#include <fcntl.h>
|
||||
#include "php_streams_int.h"
|
||||
@@ -2457,6 +2458,24 @@ void php_stream_context_unset_option(php_stream_context *context,
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHPAPI struct uri_handler_t *php_stream_context_get_uri_handler(const char *wrappername, php_stream_context *context)
|
||||
{
|
||||
if (context == NULL) {
|
||||
return php_uri_get_handler(NULL);
|
||||
}
|
||||
|
||||
zval *uri_handler_name = php_stream_context_get_option(context, wrappername, "uri_parser_class");
|
||||
if (uri_handler_name == NULL || Z_TYPE_P(uri_handler_name) == IS_NULL) {
|
||||
return php_uri_get_handler(NULL);
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(uri_handler_name) != IS_STRING) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return php_uri_get_handler(Z_STR_P(uri_handler_name));
|
||||
}
|
||||
|
||||
/* {{{ php_stream_dirent_alphasort */
|
||||
PHPAPI int php_stream_dirent_alphasort(const zend_string **a, const zend_string **b)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user