1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Add the Uri\Rfc3986\Uri class to ext/uri without wither support (#18836)

Relates to #14461 and https://wiki.php.net/rfc/url_parsing_api

Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Co-authored-by: Tim Düsterhus <tim@tideways-gmbh.com>
This commit is contained in:
Máté Kocsis
2025-07-05 10:00:20 +02:00
committed by GitHub
parent 4560f7037d
commit 5a9f5a6514
45 changed files with 1828 additions and 142 deletions

View File

@@ -5,6 +5,7 @@ PHP_INSTALL_HEADERS([ext/uri], m4_normalize([
php_lexbor.h
php_uri.h
php_uri_common.h
php_uriparser.h
]))
AC_DEFINE([URI_ENABLE_ANSI], [1], [Define to 1 for enabling ANSI support of uriparser.])
@@ -17,6 +18,6 @@ $URIPARSER_DIR/src/UriMemory.c $URIPARSER_DIR/src/UriNormalize.c $URIPARSER_DIR/
$URIPARSER_DIR/src/UriParse.c $URIPARSER_DIR/src/UriParseBase.c $URIPARSER_DIR/src/UriQuery.c \
$URIPARSER_DIR/src/UriRecompose.c $URIPARSER_DIR/src/UriResolve.c $URIPARSER_DIR/src/UriShorten.c"
PHP_NEW_EXTENSION(uri, [php_lexbor.c php_uri.c php_uri_common.c $URIPARSER_SOURCES], [no],,[-I$ext_srcdir/$URIPARSER_DIR/include -DURI_STATIC_BUILD -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1])
PHP_NEW_EXTENSION(uri, [php_lexbor.c php_uri.c php_uri_common.c php_uriparser.c $URIPARSER_SOURCES], [no],,[-I$ext_srcdir/$URIPARSER_DIR/include -DURI_STATIC_BUILD -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1])
PHP_ADD_EXTENSION_DEP(uri, lexbor)
PHP_ADD_BUILD_DIR($ext_builddir/$URIPARSER_DIR/src $ext_builddir/$URIPARSER_DIR/include)

View File

@@ -1,4 +1,4 @@
EXTENSION("uri", "php_lexbor.c php_uri.c php_uri_common.c", false /* never shared */, "/I ext/lexbor /I ext/uri/uriparser/include /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
EXTENSION("uri", "php_lexbor.c php_uri.c php_uri_common.c php_uriparser.c", false /* never shared */, "/I ext/lexbor /I ext/uri/uriparser/include /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
AC_DEFINE("URI_ENABLE_ANSI", 1, "Define to 1 for enabling ANSI support of uriparser.")
AC_DEFINE("URI_NO_UNICODE", 1, "Define to 1 for disabling unicode support of uriparser.")
@@ -6,4 +6,4 @@ ADD_FLAG("CFLAGS_URI", "/D URI_STATIC_BUILD");
ADD_EXTENSION_DEP('uri', 'lexbor');
ADD_SOURCES("ext/uri/uriparser/src", "UriCommon.c UriCompare.c UriCopy.c UriEscape.c UriFile.c UriIp4.c UriIp4Base.c UriMemory.c UriNormalize.c UriNormalizeBase.c UriParse.c UriParseBase.c UriQuery.c UriRecompose.c UriResolve.c UriShorten.c", "uri");
PHP_INSTALL_HEADERS("ext/uri", "php_lexbor.h php_uri.h php_uri_common.h uriparser/src uriparser/include");
PHP_INSTALL_HEADERS("ext/uri", "php_lexbor.h php_uri.h php_uri_common.h php_uriparser.h uriparser/src uriparser/include");

View File

@@ -25,12 +25,14 @@
#include "Zend/zend_enum.h"
#include "ext/standard/info.h"
#include "php_uri.h"
#include "php_uri_common.h"
#include "php_lexbor.h"
#include "php_uriparser.h"
#include "php_uri_arginfo.h"
#include "uriparser/src/UriConfig.h"
zend_class_entry *uri_rfc3986_uri_ce;
zend_object_handlers uri_rfc3986_uri_object_handlers;
zend_class_entry *uri_whatwg_url_ce;
zend_object_handlers uri_whatwg_uri_object_handlers;
zend_class_entry *uri_comparison_mode_ce;
@@ -104,67 +106,6 @@ static HashTable *uri_get_debug_properties(zend_object *object)
return result;
}
PHP_METHOD(Uri_WhatWg_InvalidUrlException, __construct)
{
zend_string *message = NULL;
zval *errors = NULL;
zend_long code = 0;
zval *previous = NULL;
ZEND_PARSE_PARAMETERS_START(0, 4)
Z_PARAM_OPTIONAL
Z_PARAM_STR(message)
Z_PARAM_ARRAY(errors)
Z_PARAM_LONG(code)
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(previous, zend_ce_throwable)
ZEND_PARSE_PARAMETERS_END();
if (zend_update_exception_properties(INTERNAL_FUNCTION_PARAM_PASSTHRU, message, code, previous) == FAILURE) {
RETURN_THROWS();
}
if (errors == NULL) {
zval tmp;
ZVAL_EMPTY_ARRAY(&tmp);
zend_update_property(uri_whatwg_invalid_url_exception_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), &tmp);
} else {
zend_update_property(uri_whatwg_invalid_url_exception_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), errors);
}
if (EG(exception)) {
RETURN_THROWS();
}
}
PHP_METHOD(Uri_WhatWg_UrlValidationError, __construct)
{
zend_string *context;
zval *type;
bool failure;
ZEND_PARSE_PARAMETERS_START(3, 3)
Z_PARAM_STR(context)
Z_PARAM_OBJECT_OF_CLASS(type, uri_whatwg_url_validation_error_type_ce)
Z_PARAM_BOOL(failure)
ZEND_PARSE_PARAMETERS_END();
zend_update_property_str(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("context"), context);
if (EG(exception)) {
RETURN_THROWS();
}
zend_update_property_ex(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZSTR_KNOWN(ZEND_STR_TYPE), type);
if (EG(exception)) {
RETURN_THROWS();
}
zval failure_zv;
ZVAL_BOOL(&failure_zv, failure);
zend_update_property(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("failure"), &failure_zv);
if (EG(exception)) {
RETURN_THROWS();
}
}
/**
* Pass the errors parameter by ref to errors_zv for userland, and frees it if
* it is not not needed anymore.
@@ -242,6 +183,91 @@ PHPAPI void php_uri_instantiate_uri(
uri_object->internal.uri = uri;
}
static void create_rfc3986_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
{
zend_string *uri_str;
zend_object *base_url_object = NULL;
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_PATH_STR(uri_str)
Z_PARAM_OPTIONAL
Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, uri_rfc3986_uri_ce)
ZEND_PARSE_PARAMETERS_END();
php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, &uriparser_uri_handler, uri_str, base_url_object, is_constructor, is_constructor, NULL);
}
PHP_METHOD(Uri_Rfc3986_Uri, parse)
{
create_rfc3986_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
}
PHP_METHOD(Uri_Rfc3986_Uri, __construct)
{
create_rfc3986_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
}
PHP_METHOD(Uri_WhatWg_InvalidUrlException, __construct)
{
zend_string *message = NULL;
zval *errors = NULL;
zend_long code = 0;
zval *previous = NULL;
ZEND_PARSE_PARAMETERS_START(0, 4)
Z_PARAM_OPTIONAL
Z_PARAM_STR(message)
Z_PARAM_ARRAY(errors)
Z_PARAM_LONG(code)
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(previous, zend_ce_throwable)
ZEND_PARSE_PARAMETERS_END();
if (zend_update_exception_properties(INTERNAL_FUNCTION_PARAM_PASSTHRU, message, code, previous) == FAILURE) {
RETURN_THROWS();
}
if (errors == NULL) {
zval tmp;
ZVAL_EMPTY_ARRAY(&tmp);
zend_update_property(uri_whatwg_invalid_url_exception_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), &tmp);
} else {
zend_update_property(uri_whatwg_invalid_url_exception_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), errors);
}
if (EG(exception)) {
RETURN_THROWS();
}
}
PHP_METHOD(Uri_WhatWg_UrlValidationError, __construct)
{
zend_string *context;
zval *type;
bool failure;
ZEND_PARSE_PARAMETERS_START(3, 3)
Z_PARAM_STR(context)
Z_PARAM_OBJECT_OF_CLASS(type, uri_whatwg_url_validation_error_type_ce)
Z_PARAM_BOOL(failure)
ZEND_PARSE_PARAMETERS_END();
zend_update_property_str(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("context"), context);
if (EG(exception)) {
RETURN_THROWS();
}
zend_update_property_ex(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZSTR_KNOWN(ZEND_STR_TYPE), type);
if (EG(exception)) {
RETURN_THROWS();
}
zval failure_zv;
ZVAL_BOOL(&failure_zv, failure);
zend_update_property(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("failure"), &failure_zv);
if (EG(exception)) {
RETURN_THROWS();
}
}
static void create_whatwg_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
{
zend_string *uri_str;
@@ -268,6 +294,109 @@ PHP_METHOD(Uri_WhatWg_Url, __construct)
create_whatwg_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
}
PHP_METHOD(Uri_Rfc3986_Uri, getScheme)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_SCHEME, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_Rfc3986_Uri, getRawScheme)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_SCHEME, URI_COMPONENT_READ_RAW);
}
static void read_uriparser_userinfo(INTERNAL_FUNCTION_PARAMETERS, uri_component_read_mode_t read_mode)
{
ZEND_PARSE_PARAMETERS_NONE();
uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS);
URI_ASSERT_INITIALIZATION(internal_uri);
if (UNEXPECTED(uriparser_read_userinfo(internal_uri, read_mode, return_value) == FAILURE)) {
zend_throw_error(NULL, "The userinfo component cannot be retrieved");
RETURN_THROWS();
}
}
PHP_METHOD(Uri_Rfc3986_Uri, getUserInfo)
{
read_uriparser_userinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_Rfc3986_Uri, getRawUserInfo)
{
read_uriparser_userinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_COMPONENT_READ_RAW);
}
PHP_METHOD(Uri_Rfc3986_Uri, getUsername)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_USERNAME, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_Rfc3986_Uri, getRawUsername)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_USERNAME, URI_COMPONENT_READ_RAW);
}
PHP_METHOD(Uri_Rfc3986_Uri, getPassword)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PASSWORD, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_Rfc3986_Uri, getRawPassword)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PASSWORD, URI_COMPONENT_READ_RAW);
}
PHP_METHOD(Uri_Rfc3986_Uri, getHost)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_HOST, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_Rfc3986_Uri, getRawHost)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_HOST, URI_COMPONENT_READ_RAW);
}
PHP_METHOD(Uri_Rfc3986_Uri, getPort)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PORT, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_Rfc3986_Uri, getPath)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_Rfc3986_Uri, getRawPath)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH, URI_COMPONENT_READ_RAW);
}
PHP_METHOD(Uri_Rfc3986_Uri, getQuery)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_Rfc3986_Uri, getRawQuery)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY, URI_COMPONENT_READ_RAW);
}
PHP_METHOD(Uri_Rfc3986_Uri, getFragment)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_Rfc3986_Uri, getRawFragment)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT, URI_COMPONENT_READ_RAW);
}
static void throw_cannot_recompose_uri_to_string(zend_object *object)
{
zend_throw_exception_ex(NULL, 0, "Cannot recompose %s to a string", ZSTR_VAL(object->ce->name));
}
static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, zend_object *comparison_mode)
{
zend_object *this_object = Z_OBJ_P(ZEND_THIS);
@@ -293,7 +422,7 @@ static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, z
zend_string *this_str = this_internal_uri->handler->uri_to_string(
this_internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_ASCII, exclude_fragment);
if (this_str == NULL) {
zend_throw_exception_ex(NULL, 0, "Cannot recompose %s to string", ZSTR_VAL(this_object->ce->name));
throw_cannot_recompose_uri_to_string(this_object);
RETURN_THROWS();
}
@@ -301,7 +430,7 @@ static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, z
that_internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_ASCII, exclude_fragment);
if (that_str == NULL) {
zend_string_release(this_str);
zend_throw_exception_ex(NULL, 0, "Cannot recompose %s to string", ZSTR_VAL(that_object->ce->name));
throw_cannot_recompose_uri_to_string(that_object);
RETURN_THROWS();
}
@@ -311,6 +440,99 @@ static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, z
zend_string_release(that_str);
}
PHP_METHOD(Uri_Rfc3986_Uri, equals)
{
zend_object *that_object;
zend_object *comparison_mode = NULL;
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_OBJ_OF_CLASS(that_object, uri_rfc3986_uri_ce)
Z_PARAM_OPTIONAL
Z_PARAM_OBJ_OF_CLASS(comparison_mode, uri_comparison_mode_ce)
ZEND_PARSE_PARAMETERS_END();
uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, that_object, comparison_mode);
}
PHP_METHOD(Uri_Rfc3986_Uri, toRawString)
{
ZEND_PARSE_PARAMETERS_NONE();
zend_object *this_object = Z_OBJ_P(ZEND_THIS);
uri_internal_t *internal_uri = uri_internal_from_obj(this_object);
URI_ASSERT_INITIALIZATION(internal_uri);
zend_string *uri_str = internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_RAW_ASCII, false);
if (uri_str == NULL) {
throw_cannot_recompose_uri_to_string(this_object);
RETURN_THROWS();
}
RETURN_STR(uri_str);
}
PHP_METHOD(Uri_Rfc3986_Uri, toString)
{
ZEND_PARSE_PARAMETERS_NONE();
zend_object *this_object = Z_OBJ_P(ZEND_THIS);
uri_internal_t *internal_uri = uri_internal_from_obj(this_object);
URI_ASSERT_INITIALIZATION(internal_uri);
zend_string *uri_str = internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_ASCII, false);
if (uri_str == NULL) {
throw_cannot_recompose_uri_to_string(this_object);
RETURN_THROWS();
}
RETURN_STR(uri_str);
}
PHP_METHOD(Uri_Rfc3986_Uri, resolve)
{
zend_string *uri_str;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_PATH_STR(uri_str)
ZEND_PARSE_PARAMETERS_END();
zend_object *this_object = Z_OBJ_P(ZEND_THIS);
uri_internal_t *internal_uri = uri_internal_from_obj(this_object);
URI_ASSERT_INITIALIZATION(internal_uri);
php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal_uri->handler, uri_str, this_object, true, false, NULL);
}
PHP_METHOD(Uri_Rfc3986_Uri, __serialize)
{
ZEND_PARSE_PARAMETERS_NONE();
zend_object *this_object = Z_OBJ_P(ZEND_THIS);
uri_internal_t *internal_uri = uri_internal_from_obj(this_object);
URI_ASSERT_INITIALIZATION(internal_uri);
/* Serialize state: "uri" key in the first array */
zend_string *uri_str = internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_RAW_ASCII, false);
if (uri_str == NULL) {
throw_cannot_recompose_uri_to_string(this_object);
RETURN_THROWS();
}
zval tmp;
ZVAL_STR(&tmp, uri_str);
array_init(return_value);
zval arr;
array_init(&arr);
zend_hash_str_add_new(Z_ARRVAL(arr), URI_SERIALIZED_PROPERTY_NAME, sizeof(URI_SERIALIZED_PROPERTY_NAME) - 1, &tmp);
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);
/* Serialize regular properties: second array */
ZVAL_ARR(&arr, this_object->handlers->get_properties(this_object));
Z_TRY_ADDREF(arr);
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);
}
static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *handler_name)
{
HashTable *data;
@@ -371,6 +593,20 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *handler_na
}
}
PHP_METHOD(Uri_Rfc3986_Uri, __unserialize)
{
uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PARSER_RFC3986);
}
PHP_METHOD(Uri_Rfc3986_Uri, __debugInfo)
{
ZEND_PARSE_PARAMETERS_NONE();
zend_object *object = Z_OBJ_P(ZEND_THIS);
RETURN_ARR(uri_get_debug_properties(object));
}
PHP_METHOD(Uri_WhatWg_Url, getScheme)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_SCHEME, URI_COMPONENT_READ_NORMALIZED_ASCII);
@@ -381,21 +617,11 @@ PHP_METHOD(Uri_WhatWg_Url, withScheme)
uri_write_component_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_SCHEME);
}
PHP_METHOD(Uri_WhatWg_Url, getUsername)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_USERNAME, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_WhatWg_Url, withUsername)
{
uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_USERNAME);
}
PHP_METHOD(Uri_WhatWg_Url, getPassword)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PASSWORD, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_WhatWg_Url, withPassword)
{
uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PASSWORD);
@@ -416,41 +642,21 @@ PHP_METHOD(Uri_WhatWg_Url, withHost)
uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_HOST);
}
PHP_METHOD(Uri_WhatWg_Url, getPort)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PORT, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_WhatWg_Url, withPort)
{
uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PORT);
}
PHP_METHOD(Uri_WhatWg_Url, getPath)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_WhatWg_Url, withPath)
{
uri_write_component_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH);
}
PHP_METHOD(Uri_WhatWg_Url, getQuery)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_WhatWg_Url, withQuery)
{
uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY);
}
PHP_METHOD(Uri_WhatWg_Url, getFragment)
{
uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT, URI_COMPONENT_READ_NORMALIZED_ASCII);
}
PHP_METHOD(Uri_WhatWg_Url, withFragment)
{
uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT);
@@ -521,7 +727,7 @@ PHP_METHOD(Uri_WhatWg_Url, __serialize)
/* Serialize state: "uri" key in the first array */
zend_string *uri_str = internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_RAW_ASCII, false);
if (uri_str == NULL) {
zend_throw_exception_ex(NULL, 0, "Cannot recompose %s to string", ZSTR_VAL(this_object->ce->name));
throw_cannot_recompose_uri_to_string(this_object);
RETURN_THROWS();
}
zval tmp;
@@ -629,6 +835,9 @@ zend_result uri_handler_register(const uri_handler_t *uri_handler)
static PHP_MINIT_FUNCTION(uri)
{
uri_rfc3986_uri_ce = register_class_Uri_Rfc3986_Uri();
php_uri_implementation_set_object_handlers(uri_rfc3986_uri_ce, &uri_rfc3986_uri_object_handlers);
uri_whatwg_url_ce = register_class_Uri_WhatWg_Url();
php_uri_implementation_set_object_handlers(uri_whatwg_url_ce, &uri_whatwg_uri_object_handlers);
@@ -641,6 +850,10 @@ static PHP_MINIT_FUNCTION(uri)
zend_hash_init(&uri_handlers, 4, NULL, NULL, true);
if (PHP_MINIT(uri_uriparser)(INIT_FUNC_ARGS_PASSTHRU) == FAILURE) {
return FAILURE;
}
if (uri_handler_register(&lexbor_uri_handler) == FAILURE) {
return FAILURE;
}

View File

@@ -20,6 +20,64 @@ namespace Uri {
}
}
namespace Uri\Rfc3986 {
/** @strict-properties */
final readonly class Uri
{
public static function parse(string $uri, ?\Uri\Rfc3986\Uri $baseUrl = null): ?static {}
public function __construct(string $uri, ?\Uri\Rfc3986\Uri $baseUrl = null) {}
public function getScheme(): ?string {}
public function getRawScheme(): ?string {}
public function getUserInfo(): ?string {}
public function getRawUserInfo(): ?string {}
public function getUsername(): ?string {}
public function getRawUsername(): ?string {}
public function getPassword(): ?string {}
public function getRawPassword(): ?string {}
public function getHost(): ?string {}
public function getRawHost(): ?string {}
public function getPort(): ?int {}
public function getPath(): string {}
public function getRawPath(): string {}
public function getQuery(): ?string {}
public function getRawQuery(): ?string {}
public function getFragment(): ?string {}
public function getRawFragment(): ?string {}
public function equals(\Uri\Rfc3986\Uri $uri, \Uri\UriComparisonMode $comparisonMode = \Uri\UriComparisonMode::ExcludeFragment): bool {}
public function toString(): string {}
public function toRawString(): string {}
public function resolve(string $uri): static {}
public function __serialize(): array {}
public function __unserialize(array $data): void {}
public function __debugInfo(): array {}
}
}
namespace Uri\WhatWg {
/** @strict-properties */
class InvalidUrlException extends \Uri\InvalidUriException
@@ -85,10 +143,12 @@ namespace Uri\WhatWg {
public function withScheme(string $scheme): static {}
/** @implementation-alias Uri\Rfc3986\Uri::getUsername */
public function getUsername(): ?string {}
public function withUsername(?string $username): static {}
/** @implementation-alias Uri\Rfc3986\Uri::getPassword */
public function getPassword(): ?string {}
public function withPassword(#[\SensitiveParameter] ?string $password): static {}
@@ -99,18 +159,22 @@ namespace Uri\WhatWg {
public function withHost(?string $host): static {}
/** @implementation-alias Uri\Rfc3986\Uri::getPort */
public function getPort(): ?int {}
public function withPort(?int $port): static {}
/** @implementation-alias Uri\Rfc3986\Uri::getPath */
public function getPath(): string {}
public function withPath(string $path): static {}
/** @implementation-alias Uri\Rfc3986\Uri::getQuery */
public function getQuery(): ?string {}
public function withQuery(?string $query): static {}
/** @implementation-alias Uri\Rfc3986\Uri::getFragment */
public function getFragment(): ?string {}
public function withFragment(?string $fragment): static {}

View File

@@ -1,5 +1,74 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 1945c28deef13c2af552b18c2a5a6c7798d4aeec */
* Stub hash: e2c448000b1e00485bc988f073ea61dfc984e953 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_parse, 0, 1, IS_STATIC, 1)
ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0)
ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, baseUrl, Uri\\Rfc3986\\\125ri, 1, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Uri_Rfc3986_Uri___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0)
ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, baseUrl, Uri\\Rfc3986\\\125ri, 1, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_getScheme, 0, 0, IS_STRING, 1)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_Rfc3986_Uri_getRawScheme arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_Rfc3986_Uri_getUserInfo arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_Rfc3986_Uri_getRawUserInfo arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_Rfc3986_Uri_getUsername arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_Rfc3986_Uri_getRawUsername arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_Rfc3986_Uri_getPassword arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_Rfc3986_Uri_getRawPassword arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_Rfc3986_Uri_getHost arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_Rfc3986_Uri_getRawHost arginfo_class_Uri_Rfc3986_Uri_getScheme
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_getPort, 0, 0, IS_LONG, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_getPath, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_Rfc3986_Uri_getRawPath arginfo_class_Uri_Rfc3986_Uri_getPath
#define arginfo_class_Uri_Rfc3986_Uri_getQuery arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_Rfc3986_Uri_getRawQuery arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_Rfc3986_Uri_getFragment arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_Rfc3986_Uri_getRawFragment arginfo_class_Uri_Rfc3986_Uri_getScheme
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_equals, 0, 1, _IS_BOOL, 0)
ZEND_ARG_OBJ_INFO(0, uri, Uri\\Rfc3986\\\125ri, 0)
ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, comparisonMode, Uri\\\125riComparisonMode, 0, "Uri\\UriComparisonMode::ExcludeFragment")
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_Rfc3986_Uri_toString arginfo_class_Uri_Rfc3986_Uri_getPath
#define arginfo_class_Uri_Rfc3986_Uri_toRawString arginfo_class_Uri_Rfc3986_Uri_getPath
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_resolve, 0, 1, IS_STATIC, 0)
ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri___serialize, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri___unserialize, 0, 1, IS_VOID, 0)
ZEND_ARG_TYPE_INFO(0, data, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_Rfc3986_Uri___debugInfo arginfo_class_Uri_Rfc3986_Uri___serialize
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Uri_WhatWg_InvalidUrlException___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, message, IS_STRING, 0, "\"\"")
@@ -26,54 +95,51 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Uri_WhatWg_Url___construct, 0, 0, 1)
ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, softErrors, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_getScheme, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url_getScheme arginfo_class_Uri_Rfc3986_Uri_getPath
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withScheme, 0, 1, IS_STATIC, 0)
ZEND_ARG_TYPE_INFO(0, scheme, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_getUsername, 0, 0, IS_STRING, 1)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url_getUsername arginfo_class_Uri_Rfc3986_Uri_getScheme
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withUsername, 0, 1, IS_STATIC, 0)
ZEND_ARG_TYPE_INFO(0, username, IS_STRING, 1)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url_getPassword arginfo_class_Uri_WhatWg_Url_getUsername
#define arginfo_class_Uri_WhatWg_Url_getPassword arginfo_class_Uri_Rfc3986_Uri_getScheme
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withPassword, 0, 1, IS_STATIC, 0)
ZEND_ARG_TYPE_INFO(0, password, IS_STRING, 1)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url_getAsciiHost arginfo_class_Uri_WhatWg_Url_getUsername
#define arginfo_class_Uri_WhatWg_Url_getAsciiHost arginfo_class_Uri_Rfc3986_Uri_getScheme
#define arginfo_class_Uri_WhatWg_Url_getUnicodeHost arginfo_class_Uri_WhatWg_Url_getUsername
#define arginfo_class_Uri_WhatWg_Url_getUnicodeHost arginfo_class_Uri_Rfc3986_Uri_getScheme
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withHost, 0, 1, IS_STATIC, 0)
ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_getPort, 0, 0, IS_LONG, 1)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url_getPort arginfo_class_Uri_Rfc3986_Uri_getPort
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withPort, 0, 1, IS_STATIC, 0)
ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url_getPath arginfo_class_Uri_WhatWg_Url_getScheme
#define arginfo_class_Uri_WhatWg_Url_getPath arginfo_class_Uri_Rfc3986_Uri_getPath
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withPath, 0, 1, IS_STATIC, 0)
ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url_getQuery arginfo_class_Uri_WhatWg_Url_getUsername
#define arginfo_class_Uri_WhatWg_Url_getQuery arginfo_class_Uri_Rfc3986_Uri_getScheme
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withQuery, 0, 1, IS_STATIC, 0)
ZEND_ARG_TYPE_INFO(0, query, IS_STRING, 1)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url_getFragment arginfo_class_Uri_WhatWg_Url_getUsername
#define arginfo_class_Uri_WhatWg_Url_getFragment arginfo_class_Uri_Rfc3986_Uri_getScheme
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withFragment, 0, 1, IS_STATIC, 0)
ZEND_ARG_TYPE_INFO(0, fragment, IS_STRING, 1)
@@ -84,44 +150,61 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_equals, 0,
ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, comparisonMode, Uri\\\125riComparisonMode, 0, "Uri\\UriComparisonMode::ExcludeFragment")
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url_toAsciiString arginfo_class_Uri_WhatWg_Url_getScheme
#define arginfo_class_Uri_WhatWg_Url_toAsciiString arginfo_class_Uri_Rfc3986_Uri_getPath
#define arginfo_class_Uri_WhatWg_Url_toUnicodeString arginfo_class_Uri_WhatWg_Url_getScheme
#define arginfo_class_Uri_WhatWg_Url_toUnicodeString arginfo_class_Uri_Rfc3986_Uri_getPath
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_resolve, 0, 1, IS_STATIC, 0)
ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0)
ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, softErrors, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url___serialize, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url___serialize arginfo_class_Uri_Rfc3986_Uri___serialize
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url___unserialize, 0, 1, IS_VOID, 0)
ZEND_ARG_TYPE_INFO(0, data, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url___unserialize arginfo_class_Uri_Rfc3986_Uri___unserialize
#define arginfo_class_Uri_WhatWg_Url___debugInfo arginfo_class_Uri_WhatWg_Url___serialize
#define arginfo_class_Uri_WhatWg_Url___debugInfo arginfo_class_Uri_Rfc3986_Uri___serialize
ZEND_METHOD(Uri_Rfc3986_Uri, parse);
ZEND_METHOD(Uri_Rfc3986_Uri, __construct);
ZEND_METHOD(Uri_Rfc3986_Uri, getScheme);
ZEND_METHOD(Uri_Rfc3986_Uri, getRawScheme);
ZEND_METHOD(Uri_Rfc3986_Uri, getUserInfo);
ZEND_METHOD(Uri_Rfc3986_Uri, getRawUserInfo);
ZEND_METHOD(Uri_Rfc3986_Uri, getUsername);
ZEND_METHOD(Uri_Rfc3986_Uri, getRawUsername);
ZEND_METHOD(Uri_Rfc3986_Uri, getPassword);
ZEND_METHOD(Uri_Rfc3986_Uri, getRawPassword);
ZEND_METHOD(Uri_Rfc3986_Uri, getHost);
ZEND_METHOD(Uri_Rfc3986_Uri, getRawHost);
ZEND_METHOD(Uri_Rfc3986_Uri, getPort);
ZEND_METHOD(Uri_Rfc3986_Uri, getPath);
ZEND_METHOD(Uri_Rfc3986_Uri, getRawPath);
ZEND_METHOD(Uri_Rfc3986_Uri, getQuery);
ZEND_METHOD(Uri_Rfc3986_Uri, getRawQuery);
ZEND_METHOD(Uri_Rfc3986_Uri, getFragment);
ZEND_METHOD(Uri_Rfc3986_Uri, getRawFragment);
ZEND_METHOD(Uri_Rfc3986_Uri, equals);
ZEND_METHOD(Uri_Rfc3986_Uri, toString);
ZEND_METHOD(Uri_Rfc3986_Uri, toRawString);
ZEND_METHOD(Uri_Rfc3986_Uri, resolve);
ZEND_METHOD(Uri_Rfc3986_Uri, __serialize);
ZEND_METHOD(Uri_Rfc3986_Uri, __unserialize);
ZEND_METHOD(Uri_Rfc3986_Uri, __debugInfo);
ZEND_METHOD(Uri_WhatWg_InvalidUrlException, __construct);
ZEND_METHOD(Uri_WhatWg_UrlValidationError, __construct);
ZEND_METHOD(Uri_WhatWg_Url, parse);
ZEND_METHOD(Uri_WhatWg_Url, __construct);
ZEND_METHOD(Uri_WhatWg_Url, getScheme);
ZEND_METHOD(Uri_WhatWg_Url, withScheme);
ZEND_METHOD(Uri_WhatWg_Url, getUsername);
ZEND_METHOD(Uri_WhatWg_Url, withUsername);
ZEND_METHOD(Uri_WhatWg_Url, getPassword);
ZEND_METHOD(Uri_WhatWg_Url, withPassword);
ZEND_METHOD(Uri_WhatWg_Url, getAsciiHost);
ZEND_METHOD(Uri_WhatWg_Url, getUnicodeHost);
ZEND_METHOD(Uri_WhatWg_Url, withHost);
ZEND_METHOD(Uri_WhatWg_Url, getPort);
ZEND_METHOD(Uri_WhatWg_Url, withPort);
ZEND_METHOD(Uri_WhatWg_Url, getPath);
ZEND_METHOD(Uri_WhatWg_Url, withPath);
ZEND_METHOD(Uri_WhatWg_Url, getQuery);
ZEND_METHOD(Uri_WhatWg_Url, withQuery);
ZEND_METHOD(Uri_WhatWg_Url, getFragment);
ZEND_METHOD(Uri_WhatWg_Url, withFragment);
ZEND_METHOD(Uri_WhatWg_Url, equals);
ZEND_METHOD(Uri_WhatWg_Url, toAsciiString);
@@ -131,6 +214,36 @@ ZEND_METHOD(Uri_WhatWg_Url, __serialize);
ZEND_METHOD(Uri_WhatWg_Url, __unserialize);
ZEND_METHOD(Uri_WhatWg_Url, __debugInfo);
static const zend_function_entry class_Uri_Rfc3986_Uri_methods[] = {
ZEND_ME(Uri_Rfc3986_Uri, parse, arginfo_class_Uri_Rfc3986_Uri_parse, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME(Uri_Rfc3986_Uri, __construct, arginfo_class_Uri_Rfc3986_Uri___construct, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getScheme, arginfo_class_Uri_Rfc3986_Uri_getScheme, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getRawScheme, arginfo_class_Uri_Rfc3986_Uri_getRawScheme, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getUserInfo, arginfo_class_Uri_Rfc3986_Uri_getUserInfo, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getRawUserInfo, arginfo_class_Uri_Rfc3986_Uri_getRawUserInfo, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getUsername, arginfo_class_Uri_Rfc3986_Uri_getUsername, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getRawUsername, arginfo_class_Uri_Rfc3986_Uri_getRawUsername, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getPassword, arginfo_class_Uri_Rfc3986_Uri_getPassword, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getRawPassword, arginfo_class_Uri_Rfc3986_Uri_getRawPassword, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getHost, arginfo_class_Uri_Rfc3986_Uri_getHost, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getRawHost, arginfo_class_Uri_Rfc3986_Uri_getRawHost, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getPort, arginfo_class_Uri_Rfc3986_Uri_getPort, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getPath, arginfo_class_Uri_Rfc3986_Uri_getPath, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getRawPath, arginfo_class_Uri_Rfc3986_Uri_getRawPath, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getQuery, arginfo_class_Uri_Rfc3986_Uri_getQuery, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getRawQuery, arginfo_class_Uri_Rfc3986_Uri_getRawQuery, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getFragment, arginfo_class_Uri_Rfc3986_Uri_getFragment, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, getRawFragment, arginfo_class_Uri_Rfc3986_Uri_getRawFragment, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, equals, arginfo_class_Uri_Rfc3986_Uri_equals, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, toString, arginfo_class_Uri_Rfc3986_Uri_toString, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, toRawString, arginfo_class_Uri_Rfc3986_Uri_toRawString, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, resolve, arginfo_class_Uri_Rfc3986_Uri_resolve, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, __serialize, arginfo_class_Uri_Rfc3986_Uri___serialize, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, __unserialize, arginfo_class_Uri_Rfc3986_Uri___unserialize, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_Uri, __debugInfo, arginfo_class_Uri_Rfc3986_Uri___debugInfo, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
static const zend_function_entry class_Uri_WhatWg_InvalidUrlException_methods[] = {
ZEND_ME(Uri_WhatWg_InvalidUrlException, __construct, arginfo_class_Uri_WhatWg_InvalidUrlException___construct, ZEND_ACC_PUBLIC)
ZEND_FE_END
@@ -146,20 +259,20 @@ static const zend_function_entry class_Uri_WhatWg_Url_methods[] = {
ZEND_ME(Uri_WhatWg_Url, __construct, arginfo_class_Uri_WhatWg_Url___construct, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, getScheme, arginfo_class_Uri_WhatWg_Url_getScheme, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, withScheme, arginfo_class_Uri_WhatWg_Url_withScheme, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, getUsername, arginfo_class_Uri_WhatWg_Url_getUsername, ZEND_ACC_PUBLIC)
ZEND_RAW_FENTRY("getUsername", zim_Uri_Rfc3986_Uri_getUsername, arginfo_class_Uri_WhatWg_Url_getUsername, ZEND_ACC_PUBLIC, NULL, NULL)
ZEND_ME(Uri_WhatWg_Url, withUsername, arginfo_class_Uri_WhatWg_Url_withUsername, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, getPassword, arginfo_class_Uri_WhatWg_Url_getPassword, ZEND_ACC_PUBLIC)
ZEND_RAW_FENTRY("getPassword", zim_Uri_Rfc3986_Uri_getPassword, arginfo_class_Uri_WhatWg_Url_getPassword, ZEND_ACC_PUBLIC, NULL, NULL)
ZEND_ME(Uri_WhatWg_Url, withPassword, arginfo_class_Uri_WhatWg_Url_withPassword, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, getAsciiHost, arginfo_class_Uri_WhatWg_Url_getAsciiHost, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, getUnicodeHost, arginfo_class_Uri_WhatWg_Url_getUnicodeHost, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, withHost, arginfo_class_Uri_WhatWg_Url_withHost, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, getPort, arginfo_class_Uri_WhatWg_Url_getPort, ZEND_ACC_PUBLIC)
ZEND_RAW_FENTRY("getPort", zim_Uri_Rfc3986_Uri_getPort, arginfo_class_Uri_WhatWg_Url_getPort, ZEND_ACC_PUBLIC, NULL, NULL)
ZEND_ME(Uri_WhatWg_Url, withPort, arginfo_class_Uri_WhatWg_Url_withPort, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, getPath, arginfo_class_Uri_WhatWg_Url_getPath, ZEND_ACC_PUBLIC)
ZEND_RAW_FENTRY("getPath", zim_Uri_Rfc3986_Uri_getPath, arginfo_class_Uri_WhatWg_Url_getPath, ZEND_ACC_PUBLIC, NULL, NULL)
ZEND_ME(Uri_WhatWg_Url, withPath, arginfo_class_Uri_WhatWg_Url_withPath, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, getQuery, arginfo_class_Uri_WhatWg_Url_getQuery, ZEND_ACC_PUBLIC)
ZEND_RAW_FENTRY("getQuery", zim_Uri_Rfc3986_Uri_getQuery, arginfo_class_Uri_WhatWg_Url_getQuery, ZEND_ACC_PUBLIC, NULL, NULL)
ZEND_ME(Uri_WhatWg_Url, withQuery, arginfo_class_Uri_WhatWg_Url_withQuery, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, getFragment, arginfo_class_Uri_WhatWg_Url_getFragment, ZEND_ACC_PUBLIC)
ZEND_RAW_FENTRY("getFragment", zim_Uri_Rfc3986_Uri_getFragment, arginfo_class_Uri_WhatWg_Url_getFragment, ZEND_ACC_PUBLIC, NULL, NULL)
ZEND_ME(Uri_WhatWg_Url, withFragment, arginfo_class_Uri_WhatWg_Url_withFragment, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, equals, arginfo_class_Uri_WhatWg_Url_equals, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_WhatWg_Url, toAsciiString, arginfo_class_Uri_WhatWg_Url_toAsciiString, ZEND_ACC_PUBLIC)
@@ -202,6 +315,16 @@ static zend_class_entry *register_class_Uri_UriComparisonMode(void)
return class_entry;
}
static zend_class_entry *register_class_Uri_Rfc3986_Uri(void)
{
zend_class_entry ce, *class_entry;
INIT_NS_CLASS_ENTRY(ce, "Uri\\Rfc3986", "Uri", class_Uri_Rfc3986_Uri_methods);
class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_READONLY_CLASS);
return class_entry;
}
static zend_class_entry *register_class_Uri_WhatWg_InvalidUrlException(zend_class_entry *class_entry_Uri_InvalidUriException)
{
zend_class_entry ce, *class_entry;

View File

@@ -76,8 +76,7 @@ void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t proper
ZEND_ASSERT(property_handler != NULL);
if (UNEXPECTED(property_handler->read_func(internal_uri, component_read_mode, return_value) == FAILURE)) {
zend_throw_error(NULL, "%s::$%s property cannot be retrieved", ZSTR_VAL(Z_OBJ_P(ZEND_THIS)->ce->name),
ZSTR_VAL(get_known_string_by_property_name(property_name)));
zend_throw_error(NULL, "The %s component cannot be retrieved", ZSTR_VAL(get_known_string_by_property_name(property_name)));
RETURN_THROWS();
}
}
@@ -91,14 +90,11 @@ static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, uri_property_na
ZEND_ASSERT(property_handler != NULL);
zend_object *new_object = uri_clone_obj_handler(Z_OBJ_P(ZEND_THIS));
if (UNEXPECTED(EG(exception) != NULL)) {
zend_object_release(new_object);
RETURN_THROWS();
}
ZEND_ASSERT(new_object != NULL);
uri_internal_t *new_internal_uri = uri_internal_from_obj(new_object);
URI_ASSERT_INITIALIZATION(new_internal_uri);
if (property_handler->write_func == NULL) {
if (UNEXPECTED(property_handler->write_func == NULL)) {
zend_readonly_property_modification_error_ex(ZSTR_VAL(Z_OBJ_P(ZEND_THIS)->ce->name),
ZSTR_VAL(get_known_string_by_property_name(property_name)));
zend_object_release(new_object);
@@ -107,7 +103,7 @@ static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, uri_property_na
zval errors;
ZVAL_UNDEF(&errors);
if (property_handler->write_func(new_internal_uri, property_zv, &errors) == FAILURE) {
if (UNEXPECTED(property_handler->write_func(new_internal_uri, property_zv, &errors) == FAILURE)) {
zval_ptr_dtor(&errors);
zend_object_release(new_object);
RETURN_THROWS();

View File

@@ -17,6 +17,8 @@
#ifndef PHP_URI_COMMON_H
#define PHP_URI_COMMON_H
extern zend_class_entry *uri_rfc3986_uri_ce;
extern zend_object_handlers uri_rfc3986_uri_object_handlers;
extern zend_class_entry *uri_whatwg_url_ce;
extern zend_object_handlers uri_whatwg_uri_object_handlers;
extern zend_class_entry *uri_comparison_mode_ce;
@@ -121,6 +123,7 @@ static inline uri_internal_t *uri_internal_from_obj(const zend_object *object) {
#define Z_URI_OBJECT_P(zv) uri_object_from_obj(Z_OBJ_P((zv)))
#define Z_URI_INTERNAL_P(zv) uri_internal_from_obj(Z_OBJ_P((zv)))
#define URI_PARSER_RFC3986 "Uri\\Rfc3986\\Uri"
#define URI_PARSER_WHATWG "Uri\\WhatWg\\Url"
#define URI_SERIALIZED_PROPERTY_NAME "uri"

415
ext/uri/php_uriparser.c Normal file
View File

@@ -0,0 +1,415 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Máté Kocsis <kocsismate@php.net> |
+----------------------------------------------------------------------+
*/
#include "php.h"
#include "php_uriparser.h"
#include "php_uri_common.h"
#include "Zend/zend_smart_str.h"
#include "Zend/zend_exceptions.h"
static void uriparser_free_uri(void *uri);
static void throw_invalid_uri_exception(void);
static inline size_t get_text_range_length(const UriTextRangeA *range)
{
return range->afterLast - range->first;
}
ZEND_ATTRIBUTE_NONNULL static void uriparser_copy_uri(UriUriA *new_uriparser_uri, const UriUriA *uriparser_uri)
{
int result = uriCopyUriA(new_uriparser_uri, uriparser_uri);
ZEND_ASSERT(result == URI_SUCCESS);
}
ZEND_ATTRIBUTE_NONNULL static UriUriA *get_normalized_uri(uriparser_uris_t *uriparser_uris) {
if (!uriparser_uris->normalized_uri_initialized) {
uriparser_copy_uri(&uriparser_uris->normalized_uri, &uriparser_uris->uri);
int result = uriNormalizeSyntaxExA(&uriparser_uris->normalized_uri, (unsigned int)-1);
ZEND_ASSERT(result == URI_SUCCESS);
uriparser_uris->normalized_uri_initialized = true;
}
return &uriparser_uris->normalized_uri;
}
ZEND_ATTRIBUTE_NONNULL static UriUriA *uriparser_read_uri(uriparser_uris_t *uriparser_uris, uri_component_read_mode_t read_mode)
{
switch (read_mode) {
case URI_COMPONENT_READ_RAW:
return &uriparser_uris->uri;
case URI_COMPONENT_READ_NORMALIZED_ASCII:
ZEND_FALLTHROUGH;
case URI_COMPONENT_READ_NORMALIZED_UNICODE:
return get_normalized_uri(uriparser_uris);
EMPTY_SWITCH_DEFAULT_CASE()
}
}
ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_scheme(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
{
UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode);
ZEND_ASSERT(uriparser_uri != NULL);
if (uriparser_uri->scheme.first != NULL && uriparser_uri->scheme.afterLast != NULL) {
zend_string *str = zend_string_init(uriparser_uri->scheme.first, get_text_range_length(&uriparser_uri->scheme), false);
ZVAL_NEW_STR(retval, str);
} else {
ZVAL_NULL(retval);
}
return SUCCESS;
}
ZEND_ATTRIBUTE_NONNULL zend_result uriparser_read_userinfo(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
{
UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode);
ZEND_ASSERT(uriparser_uri != NULL);
if (uriparser_uri->userInfo.first != NULL && uriparser_uri->userInfo.afterLast != NULL) {
ZVAL_STRINGL(retval, uriparser_uri->userInfo.first, get_text_range_length(&uriparser_uri->userInfo));
} else {
ZVAL_NULL(retval);
}
return SUCCESS;
}
ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_username(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
{
UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode);
ZEND_ASSERT(uriparser_uri != NULL);
if (uriparser_uri->userInfo.first != NULL && uriparser_uri->userInfo.afterLast != NULL) {
size_t length = get_text_range_length(&uriparser_uri->userInfo);
const char *c = memchr(uriparser_uri->userInfo.first, ':', length);
if (c == NULL && length > 0) {
ZVAL_STRINGL(retval, uriparser_uri->userInfo.first, length);
} else if (c != NULL && c - uriparser_uri->userInfo.first > 0) {
ZVAL_STRINGL(retval, uriparser_uri->userInfo.first, c - uriparser_uri->userInfo.first);
} else {
ZVAL_NULL(retval);
}
} else {
ZVAL_NULL(retval);
}
return SUCCESS;
}
ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_password(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
{
UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode);
ZEND_ASSERT(uriparser_uri != NULL);
if (uriparser_uri->userInfo.first != NULL && uriparser_uri->userInfo.afterLast != NULL) {
const char *c = memchr(uriparser_uri->userInfo.first, ':', get_text_range_length(&uriparser_uri->userInfo));
if (c != NULL && uriparser_uri->userInfo.afterLast - c - 1 > 0) {
ZVAL_STRINGL(retval, c + 1, uriparser_uri->userInfo.afterLast - c - 1);
} else {
ZVAL_NULL(retval);
}
} else {
ZVAL_NULL(retval);
}
return SUCCESS;
}
ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_host(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
{
UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode);
ZEND_ASSERT(uriparser_uri != NULL);
if (uriparser_uri->hostText.first != NULL && uriparser_uri->hostText.afterLast != NULL && get_text_range_length(&uriparser_uri->hostText) > 0) {
if (uriparser_uri->hostData.ip6 != NULL || uriparser_uri->hostData.ipFuture.first != NULL) {
/* the textual representation of the host is always accessible in the .hostText field no matter what the host is */
smart_str host_str = {0};
smart_str_appendc(&host_str, '[');
smart_str_appendl(&host_str, uriparser_uri->hostText.first, get_text_range_length(&uriparser_uri->hostText));
smart_str_appendc(&host_str, ']');
ZVAL_NEW_STR(retval, smart_str_extract(&host_str));
} else {
ZVAL_STRINGL(retval, uriparser_uri->hostText.first, get_text_range_length(&uriparser_uri->hostText));
}
} else {
ZVAL_NULL(retval);
}
return SUCCESS;
}
ZEND_ATTRIBUTE_NONNULL static size_t str_to_int(const char *str, size_t len)
{
size_t result = 0;
for (size_t i = 0; i < len; ++i) {
result = result * 10 + (str[i] - '0');
}
return result;
}
ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_port(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
{
UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode);
ZEND_ASSERT(uriparser_uri != NULL);
if (uriparser_uri->portText.first != NULL && uriparser_uri->portText.afterLast != NULL) {
ZVAL_LONG(retval, str_to_int(uriparser_uri->portText.first, get_text_range_length(&uriparser_uri->portText)));
} else {
ZVAL_NULL(retval);
}
return SUCCESS;
}
ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_path(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
{
UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode);
ZEND_ASSERT(uriparser_uri != NULL);
if (uriparser_uri->pathHead != NULL) {
smart_str str = {0};
if (uriparser_uri->absolutePath || uriHasHostA(uriparser_uri)) {
smart_str_appendc(&str, '/');
}
for (const UriPathSegmentA *p = uriparser_uri->pathHead; p; p = p->next) {
smart_str_appendl(&str, p->text.first, get_text_range_length(&p->text));
if (p->next) {
smart_str_appendc(&str, '/');
}
}
ZVAL_NEW_STR(retval, smart_str_extract(&str));
} else if (uriparser_uri->absolutePath) {
ZVAL_CHAR(retval, '/');
} else {
ZVAL_EMPTY_STRING(retval);
}
return SUCCESS;
}
ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_query(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
{
UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode);
ZEND_ASSERT(uriparser_uri != NULL);
if (uriparser_uri->query.first != NULL && uriparser_uri->query.afterLast != NULL) {
ZVAL_STRINGL(retval, uriparser_uri->query.first, get_text_range_length(&uriparser_uri->query));
} else {
ZVAL_NULL(retval);
}
return SUCCESS;
}
ZEND_ATTRIBUTE_NONNULL static zend_result uriparser_read_fragment(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
{
UriUriA *uriparser_uri = uriparser_read_uri(internal_uri->uri, read_mode);
ZEND_ASSERT(uriparser_uri != NULL);
if (uriparser_uri->fragment.first != NULL && uriparser_uri->fragment.afterLast != NULL) {
ZVAL_STRINGL(retval, uriparser_uri->fragment.first, get_text_range_length(&uriparser_uri->fragment));
} else {
ZVAL_NULL(retval);
}
return SUCCESS;
}
static void *uriparser_malloc(UriMemoryManager *memory_manager, size_t size)
{
return emalloc(size);
}
static void *uriparser_calloc(UriMemoryManager *memory_manager, size_t nmemb, size_t size)
{
return ecalloc(nmemb, size);
}
static void *uriparser_realloc(UriMemoryManager *memory_manager, void *ptr, size_t size)
{
return erealloc(ptr, size);
}
static void *uriparser_reallocarray(UriMemoryManager *memory_manager, void *ptr, size_t nmemb, size_t size)
{
return safe_erealloc(ptr, nmemb, size, 0);
}
static void uriparser_free(UriMemoryManager *memory_manager, void *ptr)
{
efree(ptr);
}
PHP_MINIT_FUNCTION(uri_uriparser)
{
if (uri_handler_register(&uriparser_uri_handler) == FAILURE) {
return FAILURE;
}
defaultMemoryManager.malloc = uriparser_malloc;
defaultMemoryManager.calloc = uriparser_calloc;
defaultMemoryManager.realloc = uriparser_realloc;
defaultMemoryManager.reallocarray = uriparser_reallocarray;
defaultMemoryManager.free = uriparser_free;
return SUCCESS;
}
static uriparser_uris_t *uriparser_create_uris(void)
{
uriparser_uris_t *uriparser_uris = ecalloc(1, sizeof(*uriparser_uris));
uriparser_uris->normalized_uri_initialized = false;
return uriparser_uris;
}
static void throw_invalid_uri_exception(void)
{
zend_throw_exception(uri_invalid_uri_exception_ce, "The specified URI is malformed", 0);
}
#define PARSE_URI(dest_uri, uri_str, uriparser_uris, silent) \
do { \
if (ZSTR_LEN(uri_str) == 0 || \
uriParseSingleUriExA(dest_uri, ZSTR_VAL(uri_str), ZSTR_VAL(uri_str) + ZSTR_LEN(uri_str), NULL) != URI_SUCCESS \
) { \
efree(uriparser_uris); \
if (!silent) { \
throw_invalid_uri_exception(); \
} \
return NULL; \
} \
} while (0)
void *uriparser_parse_uri_ex(const zend_string *uri_str, const uriparser_uris_t *uriparser_base_urls, bool silent)
{
uriparser_uris_t *uriparser_uris = uriparser_create_uris();
if (uriparser_base_urls == NULL) {
PARSE_URI(&uriparser_uris->uri, uri_str, uriparser_uris, silent);
uriMakeOwnerA(&uriparser_uris->uri);
} else {
UriUriA uri;
PARSE_URI(&uri, uri_str, uriparser_uris, silent);
if (uriAddBaseUriA(&uriparser_uris->uri, &uri, &uriparser_base_urls->uri) != URI_SUCCESS) {
efree(uriparser_uris);
uriFreeUriMembersA(&uri);
if (!silent) {
throw_invalid_uri_exception();
}
return NULL;
}
uriMakeOwnerA(&uriparser_uris->uri);
uriFreeUriMembersA(&uri);
}
return uriparser_uris;
}
void *uriparser_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors, bool silent)
{
return uriparser_parse_uri_ex(uri_str, 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
* 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)
{
uriparser_uris_t *uriparser_uris = uri;
uriparser_uris_t *new_uriparser_uris = uriparser_create_uris();
uriparser_copy_uri(&new_uriparser_uris->uri, &uriparser_uris->uri);
if (uriparser_uris->normalized_uri_initialized) {
uriparser_copy_uri(&new_uriparser_uris->normalized_uri, &uriparser_uris->normalized_uri);
new_uriparser_uris->normalized_uri_initialized = true;
}
return new_uriparser_uris;
}
ZEND_ATTRIBUTE_NONNULL static zend_string *uriparser_uri_to_string(void *uri, uri_recomposition_mode_t recomposition_mode, bool exclude_fragment)
{
uriparser_uris_t *uriparser_uris = uri;
UriUriA *uriparser_uri;
if (recomposition_mode == URI_RECOMPOSITION_RAW_ASCII || recomposition_mode == URI_RECOMPOSITION_RAW_UNICODE) {
uriparser_uri = &uriparser_uris->uri;
} else {
uriparser_uri = get_normalized_uri(uriparser_uris);
}
int charsRequired = 0;
int result = uriToStringCharsRequiredA(uriparser_uri, &charsRequired);
ZEND_ASSERT(result == URI_SUCCESS);
charsRequired++;
zend_string *uri_string = zend_string_alloc(charsRequired - 1, false);
result = uriToStringA(ZSTR_VAL(uri_string), uriparser_uri, charsRequired, NULL);
ZEND_ASSERT(result == URI_SUCCESS);
if (exclude_fragment) {
const char *pos = zend_memrchr(ZSTR_VAL(uri_string), '#', ZSTR_LEN(uri_string));
if (pos != NULL) {
uri_string = zend_string_truncate(uri_string, (pos - ZSTR_VAL(uri_string)), false);
}
}
return uri_string;
}
ZEND_ATTRIBUTE_NONNULL static void uriparser_free_uri(void *uri)
{
uriparser_uris_t *uriparser_uris = uri;
uriFreeUriMembersA(&uriparser_uris->uri);
uriFreeUriMembersA(&uriparser_uris->normalized_uri);
efree(uriparser_uris);
}
const uri_handler_t uriparser_uri_handler = {
.name = URI_PARSER_RFC3986,
.parse_uri = uriparser_parse_uri,
.clone_uri = uriparser_clone_uri,
.uri_to_string = uriparser_uri_to_string,
.free_uri = uriparser_free_uri,
{
.scheme = {.read_func = uriparser_read_scheme, .write_func = NULL},
.username = {.read_func = uriparser_read_username, .write_func = NULL},
.password = {.read_func = uriparser_read_password, .write_func = NULL},
.host = {.read_func = uriparser_read_host, .write_func = NULL},
.port = {.read_func = uriparser_read_port, .write_func = NULL},
.path = {.read_func = uriparser_read_path, .write_func = NULL},
.query = {.read_func = uriparser_read_query, .write_func = NULL},
.fragment = {.read_func = uriparser_read_fragment, .write_func = NULL},
}
};

38
ext/uri/php_uriparser.h Normal file
View File

@@ -0,0 +1,38 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Máté Kocsis <kocsismate@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef PHP_URIPARSER_H
#define PHP_URIPARSER_H
#include <uriparser/Uri.h>
#include "uriparser/src/UriMemory.h"
#include "php_uri_common.h"
extern const uri_handler_t uriparser_uri_handler;
typedef struct uriparser_uris_t {
UriUriA uri;
UriUriA normalized_uri;
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);
#endif

View File

@@ -5,12 +5,15 @@ uri
--FILE--
<?php
var_dump(Uri\Rfc3986\Uri::parse("http://username:password@héééostname:9090/gah/../path?arg=vaéue#anchor"));
var_dump(Uri\WhatWg\Url::parse("http://username:password@héééostname:9090/gah/../path?arg=vaéue#anchor"));
var_dump(Uri\Rfc3986\Uri::parse("/page:1"));
var_dump(Uri\WhatWg\Url::parse("/page:1"));
?>
--EXPECTF--
NULL
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(4) "http"
@@ -29,4 +32,22 @@ object(Uri\WhatWg\Url)#%d (%d) {
["fragment"]=>
string(6) "anchor"
}
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
NULL
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
NULL
["port"]=>
NULL
["path"]=>
string(7) "/page:1"
["query"]=>
NULL
["fragment"]=>
NULL
}
NULL

View File

@@ -5,6 +5,14 @@ uri
--FILE--
<?php
try {
new Uri\Rfc3986\Uri("");
} catch (Uri\InvalidUriException $e) {
echo $e->getMessage() . "\n";
}
var_dump(Uri\Rfc3986\Uri::parse(""));
try {
new Uri\WhatWg\Url("");
} catch (Uri\WhatWg\InvalidUrlException $e) {
@@ -13,13 +21,36 @@ try {
var_dump(Uri\WhatWg\Url::parse(""));
var_dump(Uri\Rfc3986\Uri::parse("192.168/contact.html"));
var_dump(Uri\WhatWg\Url::parse("192.168/contact.html", null));
var_dump(Uri\Rfc3986\Uri::parse("http://RuPaul's Drag Race All Stars 7 Winners Cast on This Season's"));
var_dump(Uri\WhatWg\Url::parse("http://RuPaul's Drag Race All Stars 7 Winners Cast on This Season's", null));
?>
--EXPECT--
--EXPECTF--
The specified URI is malformed
NULL
The specified URI is malformed (MissingSchemeNonRelativeUrl)
NULL
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
NULL
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
NULL
["port"]=>
NULL
["path"]=>
string(20) "192.168/contact.html"
["query"]=>
NULL
["fragment"]=>
NULL
}
NULL
NULL
NULL

View File

@@ -5,6 +5,8 @@ uri
--FILE--
<?php
var_dump(Uri\Rfc3986\Uri::parse("http://username:password@héééostname:9090/gah/../path?arg=vaéue#anchor"));
$url = Uri\WhatWg\Url::parse("http://username:password@héééostname:9090/gah/../path?arg=vaéue#anchor");
var_dump($url);
var_dump($url->getAsciiHost());
@@ -14,6 +16,7 @@ var_dump($url->toUnicodeString());
?>
--EXPECTF--
NULL
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(4) "http"

View File

@@ -5,11 +5,32 @@ uri
--FILE--
<?php
$uri = new Uri\Rfc3986\Uri("https://username:password@example.com:8080/path?q=r#fragment");
var_dump($uri);
$url = new Uri\WhatWg\Url("https://username:password@example.com:8080/path?q=r#fragment");
var_dump($url);
?>
--EXPECTF--
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(5) "https"
["username"]=>
string(8) "username"
["password"]=>
string(8) "password"
["host"]=>
string(11) "example.com"
["port"]=>
int(8080)
["path"]=>
string(5) "/path"
["query"]=>
string(3) "q=r"
["fragment"]=>
string(8) "fragment"
}
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(5) "https"

View File

@@ -5,6 +5,12 @@ uri
--FILE--
<?php
try {
new Uri\Rfc3986\Uri("https://example.com:8080@username:password/path?q=r#fragment");
} catch (Uri\InvalidUriException $e) {
echo $e->getMessage() . "\n";
}
try {
new Uri\WhatWg\Url("https://example.com:8080@username:password/path?q=r#fragment");
} catch (Uri\WhatWg\InvalidUrlException $e) {
@@ -19,6 +25,7 @@ var_dump($failures);
?>
--EXPECTF--
The specified URI is malformed
The specified URI is malformed (PortInvalid)
array(%d) {
[0]=>

View File

@@ -5,6 +5,27 @@ uri
--FILE--
<?php
function callRfc3986Getters($uri)
{
var_dump($uri->getScheme());
var_dump($uri->getRawScheme());
var_dump($uri->getUsername());
var_dump($uri->getRawUsername());
var_dump($uri->getPassword());
var_dump($uri->getRawPassword());
var_dump($uri->getUserInfo());
var_dump($uri->getRawUserInfo());
var_dump($uri->getHost());
var_dump($uri->getRawHost());
var_dump($uri->getPort());
var_dump($uri->getPath());
var_dump($uri->getRawPath());
var_dump($uri->getQuery());
var_dump($uri->getRawQuery());
var_dump($uri->getFragment());
var_dump($uri->getRawFragment());
}
function callWhatWgGetters($url)
{
var_dump($url->getScheme());
@@ -18,11 +39,34 @@ function callWhatWgGetters($url)
var_dump($url->getFragment());
}
$uri = Uri\Rfc3986\Uri::parse("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists");
callRfc3986Getters($uri);
echo "\n";
$url = Uri\WhatWg\Url::parse("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists");
callWhatWgGetters($url);
?>
--EXPECT--
string(5) "https"
string(5) "https"
string(8) "username"
string(8) "username"
string(8) "password"
string(8) "password"
string(17) "username:password"
string(17) "username:password"
string(14) "www.google.com"
string(14) "www.google.com"
int(8080)
string(30) "/pathname1/pathname2/pathname3"
string(30) "/pathname1/pathname2/pathname3"
string(10) "query=true"
string(10) "query=true"
string(11) "hash-exists"
string(11) "hash-exists"
string(5) "https"
string(8) "username"
string(8) "password"

View File

@@ -5,10 +5,29 @@ uri
--FILE--
<?php
var_dump(Uri\Rfc3986\Uri::parse("chrome-extension://example.com"));
var_dump(Uri\WhatWg\Url::parse("chrome-extension://example.com"));
?>
--EXPECTF--
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(16) "chrome-extension"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
string(11) "example.com"
["port"]=>
NULL
["path"]=>
string(0) ""
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(16) "chrome-extension"

View File

@@ -5,11 +5,49 @@ uri
--FILE--
<?php
var_dump(Uri\Rfc3986\Uri::parse("http://example.com/path/to/file2", new Uri\Rfc3986\Uri("https://test.com")));
var_dump(Uri\Rfc3986\Uri::parse("/path/to/file2", new Uri\Rfc3986\Uri("https://test.com")));
var_dump(Uri\WhatWg\Url::parse("http://example.com/path/to/file1", new Uri\WhatWg\Url("https://test.com")));
var_dump(Uri\WhatWg\Url::parse("/path/to/file1", new Uri\WhatWg\Url("https://test.com")));
?>
--EXPECTF--
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(4) "http"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
string(11) "example.com"
["port"]=>
NULL
["path"]=>
string(14) "/path/to/file2"
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(5) "https"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
string(8) "test.com"
["port"]=>
NULL
["path"]=>
string(14) "/path/to/file2"
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(4) "http"

View File

@@ -5,6 +5,12 @@ uri
--FILE--
<?php
var_dump(Uri\Rfc3986\Uri::parse("http://////www.EXAMPLE.com:80")->toRawString());
var_dump(Uri\Rfc3986\Uri::parse("https://www.example.com/dir1/../dir2")->toRawString());
var_dump(Uri\Rfc3986\Uri::parse("https://你好你好"));
var_dump(Uri\Rfc3986\Uri::parse("https://"));
var_dump(Uri\Rfc3986\Uri::parse("HttPs://0300.0250.0000.0001/path?query=foo%20bar")->toRawString());
var_dump(Uri\WhatWg\Url::parse("http://////www.EXAMPLE.com:80")->toAsciiString());
var_dump(Uri\WhatWg\Url::parse("https://www.example.com:443/dir1/../dir2")->toAsciiString());
var_dump(Uri\WhatWg\Url::parse("https://你好你好")->toAsciiString());
@@ -14,6 +20,11 @@ var_dump(Uri\WhatWg\Url::parse("HttPs://0300.0250.0000.0001/path?query=foo%20bar
?>
--EXPECT--
string(29) "http://////www.EXAMPLE.com:80"
string(36) "https://www.example.com/dir1/../dir2"
NULL
NULL
string(48) "HttPs://0300.0250.0000.0001/path?query=foo%20bar"
string(23) "http://www.example.com/"
string(28) "https://www.example.com/dir2"
string(23) "https://xn--6qqa088eba/"

View File

@@ -5,12 +5,32 @@ uri
--FILE--
<?php
var_dump(Uri\Rfc3986\Uri::parse("mailto:Joe@Example.COM"));
var_dump(Uri\WhatWg\Url::parse("mailto:Joe@Example.COM"));
var_dump(Uri\Rfc3986\Uri::parse("file:///E:/Documents%20and%20Settings"));
var_dump(Uri\WhatWg\Url::parse("file:///E:\\Documents and Settings"));
?>
--EXPECTF--
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(6) "mailto"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
NULL
["port"]=>
NULL
["path"]=>
string(15) "Joe@Example.COM"
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(6) "mailto"
@@ -29,6 +49,24 @@ object(Uri\WhatWg\Url)#%d (%d) {
["fragment"]=>
NULL
}
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(4) "file"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
NULL
["port"]=>
NULL
["path"]=>
string(30) "/E:/Documents%20and%20Settings"
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(4) "file"

View File

@@ -5,14 +5,39 @@ uri
--FILE--
<?php
var_dump(Uri\Rfc3986\Uri::parse("http://example.com?foo=Hell%C3%B3+W%C3%B6rld"));
var_dump(Uri\Rfc3986\Uri::parse("http://example.com?foo=Helló Wörld"));
var_dump(Uri\WhatWg\Url::parse("http://example.com?foo=Hell%C3%B3+W%C3%B6rld"));
var_dump(Uri\WhatWg\Url::parse("http://example.com?foo=Helló Wörld"));
var_dump(Uri\Rfc3986\Uri::parse("http://example.com?foobar=%27%3Cscript%3E+%2B+%40"));
var_dump(Uri\Rfc3986\Uri::parse("http://example.com?foobar='<script> + @"));
var_dump(Uri\WhatWg\Url::parse("http://example.com?foobar=%27%3Cscript%3E+%2B+%40"));
var_dump(Uri\WhatWg\Url::parse("http://example.com?foobar='<script> + @"));
?>
--EXPECTF--
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(4) "http"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
string(11) "example.com"
["port"]=>
NULL
["path"]=>
string(0) ""
["query"]=>
string(25) "foo=Hell%C3%B3+W%C3%B6rld"
["fragment"]=>
NULL
}
NULL
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(4) "http"
@@ -49,6 +74,25 @@ object(Uri\WhatWg\Url)#%d (%d) {
["fragment"]=>
NULL
}
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(4) "http"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
string(11) "example.com"
["port"]=>
NULL
["path"]=>
string(0) ""
["query"]=>
string(30) "foobar=%27%3Cscript%3E+%2B+%40"
["fragment"]=>
NULL
}
NULL
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(4) "http"

View File

@@ -5,8 +5,11 @@ uri
--FILE--
<?php
var_dump(Uri\Rfc3986\Uri::parse("http://example.com?foo=Hell%C3%B3+W%C3%B6rld")->toRawString());
var_dump(Uri\WhatWg\Url::parse("http://example.com?foo=Hell%C3%B3+W%C3%B6rld")->toAsciiString());
?>
--EXPECT--
string(44) "http://example.com?foo=Hell%C3%B3+W%C3%B6rld"
string(45) "http://example.com/?foo=Hell%C3%B3+W%C3%B6rld"

View File

@@ -6,6 +6,13 @@ uri
--FILE--
<?php
try {
$reflectionClass = new ReflectionClass(Uri\Rfc3986\Uri::class);
$reflectionClass->newInstanceWithoutConstructor();
} catch (ReflectionException $e) {
echo $e->getMessage() . "\n";
}
try {
$reflectionClass = new ReflectionClass(Uri\WhatWg\Url::class);
$reflectionClass->newInstanceWithoutConstructor();
@@ -15,4 +22,5 @@ try {
?>
--EXPECT--
Class Uri\Rfc3986\Uri is an internal class marked as final that cannot be instantiated without invoking its constructor
Class Uri\WhatWg\Url is an internal class marked as final that cannot be instantiated without invoking its constructor

View File

@@ -5,6 +5,11 @@ uri
--FILE--
<?php
$uri1 = Uri\Rfc3986\Uri::parse("https://example.com");
$uri2 = clone $uri1;
var_dump($uri1);
var_dump($uri2);
$url3 = Uri\WhatWg\Url::parse("https://example.com");
$url4 = clone $url3;
var_dump($url3);
@@ -12,7 +17,43 @@ var_dump($url4);
?>
--EXPECTF--
object(Uri\WhatWg\Url)#1 (%d) {
object(Uri\Rfc3986\Uri)#1 (%d) {
["scheme"]=>
string(5) "https"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
string(11) "example.com"
["port"]=>
NULL
["path"]=>
string(0) ""
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\Rfc3986\Uri)#2 (%d) {
["scheme"]=>
string(5) "https"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
string(11) "example.com"
["port"]=>
NULL
["path"]=>
string(0) ""
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\WhatWg\Url)#3 (%d) {
["scheme"]=>
string(5) "https"
["username"]=>
@@ -30,7 +71,7 @@ object(Uri\WhatWg\Url)#1 (%d) {
["fragment"]=>
NULL
}
object(Uri\WhatWg\Url)#2 (%d) {
object(Uri\WhatWg\Url)#4 (%d) {
["scheme"]=>
string(5) "https"
["username"]=>

View File

@@ -5,11 +5,17 @@ uri
--FILE--
<?php
$uri = Uri\Rfc3986\Uri::parse("🐘");
var_dump($uri);
$errors = [];
$url = Uri\WhatWg\Url::parse("🐘", null, $errors);
var_dump($url);
var_dump($errors);
$uri = Uri\Rfc3986\Uri::parse("https://🐘.com/🐘?🐘=🐘");
var_dump($uri);
$url = Uri\WhatWg\Url::parse("https://🐘.com/🐘?🐘=🐘", null);
var_dump($url);
var_dump($url->getAsciiHost());
@@ -20,6 +26,7 @@ var_dump($url->toUnicodeString());
?>
--EXPECTF--
NULL
NULL
array(1) {
[0]=>
object(Uri\WhatWg\UrlValidationError)#%d (%d) {
@@ -31,6 +38,7 @@ array(1) {
bool(true)
}
}
NULL
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(5) "https"

14
ext/uri/tests/021.phpt Normal file
View File

@@ -0,0 +1,14 @@
--TEST--
Test extension of Uri\Rfc3986\Uri
--EXTENSIONS--
uri
--FILE--
<?php
readonly class MyRfc3986Uri extends Uri\Rfc3986\Uri
{
}
?>
--EXPECTF--
Fatal error: Class MyRfc3986Uri cannot extend final class Uri\Rfc3986\Uri in %s on line %d

View File

@@ -5,6 +5,61 @@ uri
--FILE--
<?php
$uri1 = new Uri\Rfc3986\Uri("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists");
$serializedUri1 = serialize($uri1);
$uri2 = unserialize($serializedUri1);
var_dump($serializedUri1);
var_dump($uri2);
try {
unserialize('O:15:"Uri\Rfc3986\Uri":1:{i:0;a:0:{}}'); // less than 2 items
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
try {
unserialize('O:15:"Uri\Rfc3986\Uri":3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}'); // more than 2 items
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
try {
unserialize('O:15:"Uri\Rfc3986\Uri":2:{i:0;N;i:1;a:0:{}}'); // first item is not an array
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
try {
unserialize('O:15:"Uri\Rfc3986\Uri":2:{i:0;a:0:{}i:1;a:0:{}}'); // first array is empty
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
try {
unserialize('O:15:"Uri\Rfc3986\Uri":2:{i:0;a:1:{s:3:"uri";i:1;}i:1;a:0:{}}'); // "uri" key in first array is not a string
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
try {
unserialize('O:15:"Uri\Rfc3986\Uri":2:{i:0;a:1:{s:3:"uri";s:2:"%1";}i:1;a:0:{}}'); // "uri" key in first array contains invalid URI
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
try {
unserialize('O:15:"Uri\Rfc3986\Uri":2:{i:0;a:1:{s:3:"uri";s:4:"/uri";}i:1;s:0:"";}'); // second item in not an array
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
try {
unserialize('O:15:"Uri\Rfc3986\Uri":2:{i:0;a:1:{s:3:"uri";s:4:"/uri";}i:1;a:1:{s:5:"prop1";i:123;}}'); // second array contains a property
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
$url1 = new Uri\WhatWg\Url("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists");
$serializedUrl1 = serialize($url1);
$url2 = unserialize($serializedUrl1);
@@ -68,6 +123,33 @@ try {
?>
--EXPECTF--
string(163) "O:15:"Uri\Rfc3986\Uri":2:{i:0;a:1:{s:3:"uri";s:98:"https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists";}i:1;a:0:{}}"
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(5) "https"
["username"]=>
string(8) "username"
["password"]=>
string(8) "password"
["host"]=>
string(14) "www.google.com"
["port"]=>
int(8080)
["path"]=>
string(30) "/pathname1/pathname2/pathname3"
["query"]=>
string(10) "query=true"
["fragment"]=>
string(11) "hash-exists"
}
Invalid serialization data for Uri\Rfc3986\Uri object
Invalid serialization data for Uri\Rfc3986\Uri object
Invalid serialization data for Uri\Rfc3986\Uri object
Invalid serialization data for Uri\Rfc3986\Uri object
Invalid serialization data for Uri\Rfc3986\Uri object
Invalid serialization data for Uri\Rfc3986\Uri object
Invalid serialization data for Uri\Rfc3986\Uri object
Invalid serialization data for Uri\Rfc3986\Uri object
string(162) "O:14:"Uri\WhatWg\Url":2:{i:0;a:1:{s:3:"uri";s:98:"https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists";}i:1;a:0:{}}"
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>

View File

@@ -5,9 +5,13 @@ uri
--FILE--
<?php
$uri = new Uri\Rfc3986\Uri("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists");
var_dump(json_encode($uri));
$url = new Uri\WhatWg\Url("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists");
var_dump(json_encode($url));
?>
--EXPECT--
string(2) "{}"
string(2) "{}"

View File

@@ -5,11 +5,17 @@ uri
--FILE--
<?php
$uri = new Uri\Rfc3986\Uri("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists");
var_export($uri);
echo "\n";
$url = new Uri\WhatWg\Url("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists");
var_export($url);
echo "\n";
?>
--EXPECT--
\Uri\Rfc3986\Uri::__set_state(array(
))
\Uri\WhatWg\Url::__set_state(array(
))

View File

@@ -5,6 +5,9 @@ uri
--FILE--
<?php
$uri = new Uri\Rfc3986\Uri("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists");
var_dump((array) $uri);
$url = new Uri\WhatWg\Url("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists");
var_dump((array) $url);
@@ -12,3 +15,5 @@ var_dump((array) $url);
--EXPECTF--
array(%d) {
}
array(%d) {
}

View File

@@ -5,6 +5,12 @@ uri
--FILE--
<?php
try {
new Uri\Rfc3986\Uri("https://exam\0ple.com");
} catch (Error $e) {
echo $e->getMessage() . "\n";
}
try {
new Uri\WhatWg\Url("https://exam\0ple.com");
} catch (Error $e) {
@@ -20,5 +26,6 @@ try {
?>
--EXPECT--
Uri\Rfc3986\Uri::__construct(): Argument #1 ($uri) must not contain any null bytes
Uri\WhatWg\Url::__construct(): Argument #1 ($uri) must not contain any null bytes
Uri\WhatWg\Url::withHost(): Argument #1 ($host) must not contain any null bytes

View File

@@ -5,6 +5,14 @@ uri
--FILE--
<?php
var_dump(new Uri\Rfc3986\Uri("https://example.com")->equals(new Uri\Rfc3986\Uri("https://example.com"))); // true: identical URIs
var_dump(new Uri\Rfc3986\Uri("https://example.com#foo")->equals(new Uri\Rfc3986\Uri("https://example.com#bar"), Uri\UriComparisonMode::ExcludeFragment)); // true: fragment differs, but fragment is excluded
var_dump(new Uri\Rfc3986\Uri("https://example.com#foo")->equals(new Uri\Rfc3986\Uri("https://example.com#bar"), Uri\UriComparisonMode::IncludeFragment)); // false: fragment differs and fragment is included
var_dump(new Uri\Rfc3986\Uri("https://example.com/foo/..")->equals(new Uri\Rfc3986\Uri("https://example.com"))); // false: first URI becomes https://example.com/ after normalization
var_dump(new Uri\Rfc3986\Uri("https://example.com/foo/..")->equals(new Uri\Rfc3986\Uri("https://example.com/"))); // true: both URIs are https://example.com/ after normalization
var_dump(new Uri\Rfc3986\Uri("http://example%2ecom/foo%2fb%61r")->equals(new Uri\Rfc3986\Uri("http://example%2ecom/foo/bar"))); // false: "/" in the path should not be decoded
var_dump(new Uri\Rfc3986\Uri("http://example%2ecom/foo/b%61r")->equals(new Uri\Rfc3986\Uri("http://example%2ecom/foo/bar"))); // true: percent-decoding during normalization gives same URIs
var_dump(new Uri\WhatWg\Url("https://example.com")->equals(new Uri\WhatWg\Url("https://example.com"))); // true: identical URIs
var_dump(new Uri\WhatWg\Url("https://example.com#foo")->equals(new Uri\WhatWg\Url("https://example.com#bar"), Uri\UriComparisonMode::ExcludeFragment)); // true: fragment differs, but fragment is excluded
var_dump(new Uri\WhatWg\Url("https://example.com#foo")->equals(new Uri\WhatWg\Url("https://example.com#bar"), Uri\UriComparisonMode::IncludeFragment)); // false: fragment differs and fragment is included
@@ -18,6 +26,13 @@ var_dump(new Uri\WhatWg\Url("http://example%2ecom/foo/b%61r")->equals(new Uri\Wh
bool(true)
bool(true)
bool(false)
bool(false)
bool(true)
bool(false)
bool(true)
bool(true)
bool(true)
bool(false)
bool(true)
bool(true)
bool(false)

View File

@@ -5,6 +5,16 @@ uri
--FILE--
<?php
$uri1 = Uri\Rfc3986\Uri::parse("HTTPS://////EXAMPLE.com");
$uri2 = Uri\Rfc3986\Uri::parse("https://example.com");
$uri3 = Uri\Rfc3986\Uri::parse("https://example.com/foo/..");
var_dump($uri1->toRawString());
var_dump($uri1->toString());
var_dump($uri2->toRawString());
var_dump($uri2->toString());
var_dump($uri3->toRawString());
var_dump($uri3->toString());
$url1 = Uri\WhatWg\Url::parse("HTTPS://////EXAMPLE.com");
$url2 = Uri\WhatWg\Url::parse("https://example.com");
$url3 = Uri\WhatWg\Url::parse("https://example.com/foo/..");
@@ -18,6 +28,12 @@ var_dump($url3->toAsciiString());
?>
--EXPECT--
string(23) "HTTPS://////EXAMPLE.com"
string(23) "https://////EXAMPLE.com"
string(19) "https://example.com"
string(19) "https://example.com"
string(26) "https://example.com/foo/.."
string(20) "https://example.com/"
string(20) "https://example.com/"
string(20) "https://example.com/"
string(20) "https://example.com/"

View File

@@ -5,6 +5,27 @@ uri
--FILE--
<?php
function callRfc3986Getters($uri)
{
var_dump($uri->getScheme());
var_dump($uri->getRawScheme());
var_dump($uri->getUsername());
var_dump($uri->getRawUsername());
var_dump($uri->getPassword());
var_dump($uri->getRawPassword());
var_dump($uri->getUserInfo());
var_dump($uri->getRawUserInfo());
var_dump($uri->getHost());
var_dump($uri->getRawHost());
var_dump($uri->getPort());
var_dump($uri->getPath());
var_dump($uri->getRawPath());
var_dump($uri->getQuery());
var_dump($uri->getRawQuery());
var_dump($uri->getFragment());
var_dump($uri->getRawFragment());
}
function callWhatWgGetters($url)
{
var_dump($url->getScheme());
@@ -18,11 +39,34 @@ function callWhatWgGetters($url)
var_dump($url->getFragment());
}
$uri = Uri\Rfc3986\Uri::parse("http://%61pple:p%61ss@ex%61mple.com/foob%61r?%61bc=%61bc#%61bc");
callRfc3986Getters($uri);
echo "\n";
$url = Uri\WhatWg\Url::parse("http://%61pple:p%61ss@ex%61mple.com/foob%61r?%61bc=%61bc#%61bc");
callWhatWgGetters($url);
?>
--EXPECT--
string(4) "http"
string(4) "http"
string(5) "apple"
string(7) "%61pple"
string(4) "pass"
string(6) "p%61ss"
string(10) "apple:pass"
string(14) "%61pple:p%61ss"
string(11) "example.com"
string(13) "ex%61mple.com"
NULL
string(7) "/foobar"
string(9) "/foob%61r"
string(7) "abc=abc"
string(11) "%61bc=%61bc"
string(3) "abc"
string(5) "%61bc"
string(4) "http"
string(7) "%61pple"
string(6) "p%61ss"

View File

@@ -5,12 +5,35 @@ uri
--FILE--
<?php
$uri = Uri\Rfc3986\Uri::parse("https:example.com");
var_dump($uri);
var_dump($uri->toRawString());
$url = Uri\WhatWg\Url::parse("https:example.com");
var_dump($url);
var_dump($url->toAsciiString());
?>
--EXPECTF--
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(5) "https"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
NULL
["port"]=>
NULL
["path"]=>
string(11) "example.com"
["query"]=>
NULL
["fragment"]=>
NULL
}
string(17) "https:example.com"
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(5) "https"

View File

@@ -5,6 +5,9 @@ uri
--FILE--
<?php
$uri = Uri\Rfc3986\Uri::parse("?query#fragment");
var_dump($uri);
$errors = [];
$url = Uri\WhatWg\Url::parse("?query#fragment", null, $errors);
var_dump($url);
@@ -12,6 +15,24 @@ var_dump($errors);
?>
--EXPECTF--
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
NULL
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
NULL
["port"]=>
NULL
["path"]=>
string(0) ""
["query"]=>
string(5) "query"
["fragment"]=>
string(8) "fragment"
}
NULL
array(%d) {
[0]=>

View File

@@ -5,10 +5,31 @@ uri
--FILE--
<?php
$uri = Uri\Rfc3986\Uri::parse("urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66");
var_dump($uri);
$url = Uri\WhatWg\Url::parse("urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66");
var_dump($url);
?>
--EXPECTF--
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(3) "urn"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
NULL
["port"]=>
NULL
["path"]=>
string(41) "uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66"
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(3) "urn"

View File

@@ -5,6 +5,19 @@ uri
--FILE--
<?php
$uri = Uri\Rfc3986\Uri::parse("https://example.com/without-base");
var_dump($uri);
$uri = Uri\Rfc3986\Uri::parse("/with-base", new Uri\Rfc3986\Uri("https://example.com"));
var_dump($uri);
$uri = Uri\Rfc3986\Uri::parse("https://test.com/with-base-in-vain", new Uri\Rfc3986\Uri("https://example.com"));
var_dump($uri);
$uri = Uri\Rfc3986\Uri::parse("HTTPS://TEST.com/with-base-in-vain", Uri\Rfc3986\Uri::parse("https://example.com"));
var_dump($uri);
var_dump($uri->toString());
$url = Uri\WhatWg\Url::parse("https://example.com/without-base/");
var_dump($url);
@@ -15,6 +28,79 @@ $url = Uri\WhatWg\Url::parse("https://test.com/with-base-in-vain", Uri\WhatWg\Ur
var_dump($url);
?>
--EXPECTF--
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(5) "https"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
string(11) "example.com"
["port"]=>
NULL
["path"]=>
string(13) "/without-base"
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(5) "https"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
string(11) "example.com"
["port"]=>
NULL
["path"]=>
string(10) "/with-base"
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(5) "https"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
string(8) "test.com"
["port"]=>
NULL
["path"]=>
string(18) "/with-base-in-vain"
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
string(5) "HTTPS"
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
string(8) "TEST.com"
["port"]=>
NULL
["path"]=>
string(18) "/with-base-in-vain"
["query"]=>
NULL
["fragment"]=>
NULL
}
string(34) "https://test.com/with-base-in-vain"
object(Uri\WhatWg\Url)#%d (%d) {
["scheme"]=>
string(5) "https"

View File

@@ -5,6 +5,12 @@ uri
--FILE--
<?php
$uri = new Uri\Rfc3986\Uri("https://example.com/foo/bar%2Fbaz");
var_dump($uri->toRawString());
var_dump($uri->getPath());
var_dump($uri->getRawPath());
$url = new Uri\Whatwg\Url("https://example.com/foo/bar%2Fbaz");
var_dump($url->toAsciiString());
@@ -14,3 +20,6 @@ var_dump($url->getPath());
--EXPECT--
string(33) "https://example.com/foo/bar%2Fbaz"
string(14) "/foo/bar%2Fbaz"
string(14) "/foo/bar%2Fbaz"
string(33) "https://example.com/foo/bar%2Fbaz"
string(14) "/foo/bar%2Fbaz"

View File

@@ -5,6 +5,44 @@ uri
--FILE--
<?php
$uri = new Uri\Rfc3986\Uri("mailto:johndoe@example.com");
var_dump($uri->toRawString());
var_dump($uri->getPath());
var_dump($uri->getRawPath());
$uri = new Uri\Rfc3986\Uri("foo/bar");
var_dump($uri->toRawString());
var_dump($uri->getPath());
var_dump($uri->getRawPath());
$uri = new Uri\Rfc3986\Uri("/foo/bar");
var_dump($uri->toRawString());
var_dump($uri->getPath());
var_dump($uri->getRawPath());
$uri = new Uri\Rfc3986\Uri("//");
var_dump($uri->toRawString());
var_dump($uri->getPath());
var_dump($uri->getRawPath());
$uri = new Uri\Rfc3986\Uri("///");
var_dump($uri->toRawString());
var_dump($uri->getPath());
var_dump($uri->getRawPath());
$uri = new Uri\Rfc3986\Uri("https://example.com");
var_dump($uri->toRawString());
var_dump($uri->getPath());
var_dump($uri->getRawPath());
$uri = new Uri\Rfc3986\Uri("https://example.com/");
var_dump($uri->toRawString());
var_dump($uri->getPath());
var_dump($uri->getRawPath());
$url = new Uri\Whatwg\Url("mailto:johndoe@example.com");
var_dump($url->toAsciiString());
@@ -24,6 +62,27 @@ var_dump($url->getPath());
--EXPECT--
string(26) "mailto:johndoe@example.com"
string(19) "johndoe@example.com"
string(19) "johndoe@example.com"
string(7) "foo/bar"
string(7) "foo/bar"
string(7) "foo/bar"
string(8) "/foo/bar"
string(8) "/foo/bar"
string(8) "/foo/bar"
string(2) "//"
string(0) ""
string(0) ""
string(3) "///"
string(1) "/"
string(1) "/"
string(19) "https://example.com"
string(0) ""
string(0) ""
string(20) "https://example.com/"
string(1) "/"
string(1) "/"
string(26) "mailto:johndoe@example.com"
string(19) "johndoe@example.com"
string(20) "https://example.com/"
string(1) "/"
string(20) "https://example.com/"

View File

@@ -5,6 +5,24 @@ uri
--FILE--
<?php
$uri = new Uri\Rfc3986\Uri("https://192.168.0.1");
var_dump($uri->getRawHost());
var_dump($uri->getHost());
var_dump($uri->toRawString());
var_dump($uri->toString());
$uri = new Uri\Rfc3986\Uri("https://[2001:0db8:0001:0000:0000:0ab9:C0A8:0102]");
var_dump($uri->getRawHost());
var_dump($uri->getHost());
var_dump($uri->toRawString());
var_dump($uri->toString());
$uri = new Uri\Rfc3986\Uri("//[v7.host]/source");
var_dump($uri->getRawHost());
var_dump($uri->getHost());
var_dump($uri->toRawString());
var_dump($uri->toString());
$url = new Uri\WhatWg\Url("https://192.168.0.1");
var_dump($url->getAsciiHost());
var_dump($url->toAsciiString());
@@ -20,6 +38,18 @@ var_dump($url->toAsciiString());
?>
--EXPECT--
string(11) "192.168.0.1"
string(11) "192.168.0.1"
string(19) "https://192.168.0.1"
string(19) "https://192.168.0.1"
string(41) "[2001:0db8:0001:0000:0000:0ab9:C0A8:0102]"
string(41) "[2001:0db8:0001:0000:0000:0ab9:c0a8:0102]"
string(49) "https://[2001:0db8:0001:0000:0000:0ab9:c0a8:0102]"
string(49) "https://[2001:0db8:0001:0000:0000:0ab9:c0a8:0102]"
string(9) "[v7.host]"
string(9) "[v7.host]"
string(18) "//[v7.host]/source"
string(18) "//[v7.host]/source"
string(11) "192.168.0.1"
string(20) "https://192.168.0.1/"
string(26) "[2001:db8:1::ab9:c0a8:102]"
string(35) "https://[2001:db8:1::ab9:c0a8:102]/"

17
ext/uri/tests/048.phpt Normal file
View File

@@ -0,0 +1,17 @@
--TEST--
Test RFC 3986 percent-encoding normalization
--EXTENSIONS--
uri
--FILE--
<?php
$uri = Uri\Rfc3986\Uri::parse("https://%e4%bd%a0%e5%a5%bd%e4%bd%a0%e5%a5%bd.com"); // percent-encoded form of https://你好你好.com
var_dump($uri->toString());
$uri = Uri\Rfc3986\Uri::parse("https://example.com/%e4%bd%a0%e5%a5%bd%e4%bd%a0%e5%a5%bd"); // percent-encoded form of https://example.com/你好你好.com
var_dump($uri->toString());
?>
--EXPECT--
string(48) "https://%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD.com"
string(56) "https://example.com/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD"

View File

@@ -5,9 +5,15 @@ uri
--FILE--
<?php
$uri = new Uri\Rfc3986\Uri("https://example.com/foo/bar%2Fbaz");
var_dump($uri->getRawPath());
var_dump($uri->getPath());
$url = new Uri\WhatWg\Url("https://example.com/foo/bar%2Fbaz");
var_dump($url->getPath());
?>
--EXPECT--
string(14) "/foo/bar%2Fbaz"
string(14) "/foo/bar%2Fbaz"
string(14) "/foo/bar%2Fbaz"

View File

@@ -5,6 +5,11 @@ uri
--FILE--
<?php
$uri = new Uri\Rfc3986\Uri("https://example.com");
var_dump($uri->resolve("/foo/")->toString());
var_dump($uri->resolve("https://test.com/foo")->toString());
$url = new Uri\WhatWg\Url("https://example.com");
var_dump($url->resolve("/foo/")->toAsciiString());
@@ -14,3 +19,5 @@ var_dump($url->resolve("https://test.com/foo")->toAsciiString());
--EXPECTF--
string(24) "https://example.com/foo/"
string(20) "https://test.com/foo"
string(24) "https://example.com/foo/"
string(20) "https://test.com/foo"

View File

@@ -5,6 +5,14 @@ uri
--FILE--
<?php
$uri = new Uri\Rfc3986\Uri("https://example.com");
try {
$uri->resolve("á");
} catch (Uri\InvalidUriException $e) {
echo $e->getMessage() . "\n";
}
$url = new Uri\WhatWg\Url("https://example.com");
try {
@@ -20,6 +28,7 @@ var_dump($softErrors);
?>
--EXPECTF--
The specified URI is malformed
The specified URI is malformed (Ipv4TooManyParts)
string(23) "https://example.com/foo"
array(%d) {

15
ext/uri/tests/055.phpt Normal file
View File

@@ -0,0 +1,15 @@
--TEST--
Test InvalidUrlException constructor error handling
--EXTENSIONS--
uri
--FILE--
<?php
try {
var_dump(new Uri\Rfc3986\Uri('foo', new Uri\Rfc3986\Uri('bar')));
} catch (Uri\InvalidUriException $e) {
echo $e->getMessage() . "\n";
}
?>
--EXPECT--
The specified URI is malformed