From da11b7fc4d0321a1c3876c71fcb07b990b5d6cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Sun, 17 May 2026 21:57:53 +0200 Subject: [PATCH 1/2] Implement "Followup improvements for ext/uri" RFC - URI type detection RFC: https://wiki.php.net/rfc/uri_followup#uri_type_detection --- ext/lexbor/lexbor/url/url.c | 6 ---- ext/lexbor/lexbor/url/url.h | 5 +++ ext/uri/php_uri.c | 23 ++++++++++++++ ext/uri/php_uri.stub.php | 12 +++++++ ext/uri/php_uri_arginfo.h | 27 +++++++++++++++- ext/uri/php_uri_common.h | 1 + ext/uri/php_uri_decl.h | 15 ++++++--- ..._type_success_absolute_path_reference.phpt | 12 +++++++ ...i_type_success_network_path_reference.phpt | 12 +++++++ ..._type_success_relative_path_reference.phpt | 12 +++++++ .../getters/uri_type_success_uri_basic.phpt | 12 +++++++ .../uri_type_success_uri_empty_authority.phpt | 12 +++++++ .../uri_type_success_uri_no_authority.phpt | 12 +++++++ .../is_special_scheme_success_false.phpt | 12 +++++++ .../is_special_scheme_success_true.phpt | 31 +++++++++++++++++++ ext/uri/uri_parser_rfc3986.c | 22 +++++++++++++ ext/uri/uri_parser_rfc3986.h | 2 ++ ext/uri/uri_parser_whatwg.c | 5 +++ ext/uri/uri_parser_whatwg.h | 2 ++ 19 files changed, 224 insertions(+), 11 deletions(-) create mode 100644 ext/uri/tests/rfc3986/getters/uri_type_success_absolute_path_reference.phpt create mode 100644 ext/uri/tests/rfc3986/getters/uri_type_success_network_path_reference.phpt create mode 100644 ext/uri/tests/rfc3986/getters/uri_type_success_relative_path_reference.phpt create mode 100644 ext/uri/tests/rfc3986/getters/uri_type_success_uri_basic.phpt create mode 100644 ext/uri/tests/rfc3986/getters/uri_type_success_uri_empty_authority.phpt create mode 100644 ext/uri/tests/rfc3986/getters/uri_type_success_uri_no_authority.phpt create mode 100644 ext/uri/tests/whatwg/getters/is_special_scheme_success_false.phpt create mode 100644 ext/uri/tests/whatwg/getters/is_special_scheme_success_true.phpt diff --git a/ext/lexbor/lexbor/url/url.c b/ext/lexbor/lexbor/url/url.c index 5a1143469d1a..6ccccb111073 100644 --- a/ext/lexbor/lexbor/url/url.c +++ b/ext/lexbor/lexbor/url/url.c @@ -860,12 +860,6 @@ lxb_url_is_url_codepoint(lxb_codepoint_t cp) return lxb_url_codepoint_alphanumeric[(lxb_char_t) cp] != 0xFF; } -lxb_inline bool -lxb_url_is_special(const lxb_url_t *url) -{ - return url->scheme.type != LXB_URL_SCHEMEL_TYPE__UNKNOWN; -} - lxb_inline const lxb_url_scheme_data_t * lxb_url_scheme_by_type(lxb_url_scheme_type_t type) { diff --git a/ext/lexbor/lexbor/url/url.h b/ext/lexbor/lexbor/url/url.h index 4ed3f32aa646..1841d02d1123 100644 --- a/ext/lexbor/lexbor/url/url.h +++ b/ext/lexbor/lexbor/url/url.h @@ -845,6 +845,11 @@ lxb_url_get(lxb_url_parser_t *parser) return parser->url; } +lxb_inline bool +lxb_url_is_special(const lxb_url_t *url) +{ + return url->scheme.type != LXB_URL_SCHEMEL_TYPE__UNKNOWN; +} #ifdef __cplusplus } /* extern "C" */ diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index d25c310ed0da..8d3d823ced84 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -31,6 +31,7 @@ #include "uriparser/Uri.h" zend_class_entry *php_uri_ce_rfc3986_uri; +zend_class_entry *php_uri_ce_rfc3986_uri_type; zend_class_entry *php_uri_ce_whatwg_url; zend_class_entry *php_uri_ce_comparison_mode; zend_class_entry *php_uri_ce_exception; @@ -508,6 +509,16 @@ PHP_METHOD(Uri_WhatWg_Url, __construct) create_whatwg_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); } +PHP_METHOD(Uri_Rfc3986_Uri, getUriType) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS); + ZEND_ASSERT(uri_object->uri != NULL); + + php_uri_parser_rfc3986_uri_type_read(uri_object->uri, return_value); +} + PHP_METHOD(Uri_Rfc3986_Uri, getScheme) { php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); @@ -883,6 +894,16 @@ PHP_METHOD(Uri_WhatWg_Url, withScheme) php_uri_property_write_str_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME); } +PHP_METHOD(Uri_WhatWg_Url, isSpecialScheme) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS); + ZEND_ASSERT(uri_object->uri != NULL); + + RETVAL_BOOL(php_uri_parser_whatwg_is_special(uri_object->uri)); +} + PHP_METHOD(Uri_WhatWg_Url, withUsername) { php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_USERNAME); @@ -1078,6 +1099,8 @@ static PHP_MINIT_FUNCTION(uri) object_handlers_rfc3986_uri.free_obj = php_uri_object_handler_free; object_handlers_rfc3986_uri.clone_obj = php_uri_object_handler_clone; + php_uri_ce_rfc3986_uri_type = register_class_Uri_Rfc3986_UriType(); + php_uri_ce_whatwg_url = register_class_Uri_WhatWg_Url(); php_uri_ce_whatwg_url->create_object = php_uri_object_create_whatwg; php_uri_ce_whatwg_url->default_object_handlers = &object_handlers_whatwg_uri; diff --git a/ext/uri/php_uri.stub.php b/ext/uri/php_uri.stub.php index 6d4b2c3517a5..03e8a483b0b3 100644 --- a/ext/uri/php_uri.stub.php +++ b/ext/uri/php_uri.stub.php @@ -29,6 +29,14 @@ enum UriComparisonMode } namespace Uri\Rfc3986 { + enum UriType + { + case AbsolutePathReference; + case RelativePathReference; + case NetworkPathReference; + case Uri; + } + /** @strict-properties */ final readonly class Uri { @@ -36,6 +44,8 @@ public static function parse(string $uri, ?\Uri\Rfc3986\Uri $baseUrl = null): ?s public function __construct(string $uri, ?\Uri\Rfc3986\Uri $baseUrl = null) {} + public function getUriType(): ?\Uri\Rfc3986\UriType {} + public function getScheme(): ?string {} public function getRawScheme(): ?string {} @@ -165,6 +175,8 @@ public function getScheme(): string {} public function withScheme(string $scheme): static {} + public function isSpecialScheme(): bool {} + /** @implementation-alias Uri\Rfc3986\Uri::getUsername */ public function getUsername(): ?string {} diff --git a/ext/uri/php_uri_arginfo.h b/ext/uri/php_uri_arginfo.h index 18d7f4adf783..e88d439fa16a 100644 --- a/ext/uri/php_uri_arginfo.h +++ b/ext/uri/php_uri_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit php_uri.stub.php instead. - * Stub hash: 3c228f4227e7543be5c12c99074789d92c27ab99 + * Stub hash: 4143e681e589d6e663f3f7d9eb7677cd3395baf2 * Has decl header: yes */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_parse, 0, 1, IS_STATIC, 1) @@ -12,6 +12,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Uri_Rfc3986_Uri___construct, 0, 0, 1) ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, baseUrl, Uri\\Rfc3986\\\125ri, 1, "null") ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_getUriType, 0, 0, Uri\\Rfc3986\\\125riType, 1) +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() @@ -130,6 +133,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withScheme, 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_isSpecialScheme, 0, 0, _IS_BOOL, 0) +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) @@ -186,6 +192,7 @@ ZEND_END_ARG_INFO() ZEND_METHOD(Uri_Rfc3986_Uri, parse); ZEND_METHOD(Uri_Rfc3986_Uri, __construct); +ZEND_METHOD(Uri_Rfc3986_Uri, getUriType); ZEND_METHOD(Uri_Rfc3986_Uri, getScheme); ZEND_METHOD(Uri_Rfc3986_Uri, getRawScheme); ZEND_METHOD(Uri_Rfc3986_Uri, withScheme); @@ -223,6 +230,7 @@ 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, isSpecialScheme); ZEND_METHOD(Uri_WhatWg_Url, withUsername); ZEND_METHOD(Uri_WhatWg_Url, withPassword); ZEND_METHOD(Uri_WhatWg_Url, getAsciiHost); @@ -238,6 +246,7 @@ 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, getUriType, arginfo_class_Uri_Rfc3986_Uri_getUriType, 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, withScheme, arginfo_class_Uri_Rfc3986_Uri_withScheme, ZEND_ACC_PUBLIC) @@ -287,6 +296,7 @@ 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, isSpecialScheme, arginfo_class_Uri_WhatWg_Url_isSpecialScheme, 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_RAW_FENTRY("getPassword", zim_Uri_Rfc3986_Uri_getPassword, arginfo_class_Uri_WhatWg_Url_getPassword, ZEND_ACC_PUBLIC, NULL, NULL) @@ -353,6 +363,21 @@ static zend_class_entry *register_class_Uri_UriComparisonMode(void) return class_entry; } +static zend_class_entry *register_class_Uri_Rfc3986_UriType(void) +{ + zend_class_entry *class_entry = zend_register_internal_enum("Uri\\Rfc3986\\UriType", IS_UNDEF, NULL); + + zend_enum_add_case_cstr(class_entry, "AbsolutePathReference", NULL); + + zend_enum_add_case_cstr(class_entry, "RelativePathReference", NULL); + + zend_enum_add_case_cstr(class_entry, "NetworkPathReference", NULL); + + zend_enum_add_case_cstr(class_entry, "Uri", NULL); + + return class_entry; +} + static zend_class_entry *register_class_Uri_Rfc3986_Uri(void) { zend_class_entry ce, *class_entry; diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index 888a38245453..6749bba8fe7f 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -18,6 +18,7 @@ #include "php_uri_decl.h" extern zend_class_entry *php_uri_ce_rfc3986_uri; +extern zend_class_entry *php_uri_ce_rfc3986_uri_type; extern zend_class_entry *php_uri_ce_whatwg_url; extern zend_class_entry *php_uri_ce_comparison_mode; extern zend_class_entry *php_uri_ce_exception; diff --git a/ext/uri/php_uri_decl.h b/ext/uri/php_uri_decl.h index 3c069f3abe6d..947858515dbb 100644 --- a/ext/uri/php_uri_decl.h +++ b/ext/uri/php_uri_decl.h @@ -1,14 +1,21 @@ /* This is a generated file, edit php_uri.stub.php instead. - * Stub hash: 3c228f4227e7543be5c12c99074789d92c27ab99 */ + * Stub hash: 4143e681e589d6e663f3f7d9eb7677cd3395baf2 */ -#ifndef ZEND_PHP_URI_DECL_3c228f4227e7543be5c12c99074789d92c27ab99_H -#define ZEND_PHP_URI_DECL_3c228f4227e7543be5c12c99074789d92c27ab99_H +#ifndef ZEND_PHP_URI_DECL_4143e681e589d6e663f3f7d9eb7677cd3395baf2_H +#define ZEND_PHP_URI_DECL_4143e681e589d6e663f3f7d9eb7677cd3395baf2_H typedef enum zend_enum_Uri_UriComparisonMode { ZEND_ENUM_Uri_UriComparisonMode_IncludeFragment = 1, ZEND_ENUM_Uri_UriComparisonMode_ExcludeFragment = 2, } zend_enum_Uri_UriComparisonMode; +typedef enum zend_enum_Uri_Rfc3986_UriType { + ZEND_ENUM_Uri_Rfc3986_UriType_AbsolutePathReference = 1, + ZEND_ENUM_Uri_Rfc3986_UriType_RelativePathReference = 2, + ZEND_ENUM_Uri_Rfc3986_UriType_NetworkPathReference = 3, + ZEND_ENUM_Uri_Rfc3986_UriType_Uri = 4, +} zend_enum_Uri_Rfc3986_UriType; + typedef enum zend_enum_Uri_WhatWg_UrlValidationErrorType { ZEND_ENUM_Uri_WhatWg_UrlValidationErrorType_DomainToAscii = 1, ZEND_ENUM_Uri_WhatWg_UrlValidationErrorType_DomainToUnicode = 2, @@ -41,4 +48,4 @@ typedef enum zend_enum_Uri_WhatWg_UrlValidationErrorType { ZEND_ENUM_Uri_WhatWg_UrlValidationErrorType_FileInvalidWindowsDriveLetterHost = 29, } zend_enum_Uri_WhatWg_UrlValidationErrorType; -#endif /* ZEND_PHP_URI_DECL_3c228f4227e7543be5c12c99074789d92c27ab99_H */ +#endif /* ZEND_PHP_URI_DECL_4143e681e589d6e663f3f7d9eb7677cd3395baf2_H */ diff --git a/ext/uri/tests/rfc3986/getters/uri_type_success_absolute_path_reference.phpt b/ext/uri/tests/rfc3986/getters/uri_type_success_absolute_path_reference.phpt new file mode 100644 index 000000000000..1cddc15fa33c --- /dev/null +++ b/ext/uri/tests/rfc3986/getters/uri_type_success_absolute_path_reference.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Uri\Rfc3986\Uri getter - uri type - Absolute path reference +--FILE-- +getUriType()); + +?> +--EXPECT-- +enum(Uri\Rfc3986\UriType::AbsolutePathReference) diff --git a/ext/uri/tests/rfc3986/getters/uri_type_success_network_path_reference.phpt b/ext/uri/tests/rfc3986/getters/uri_type_success_network_path_reference.phpt new file mode 100644 index 000000000000..d7debc5ba66c --- /dev/null +++ b/ext/uri/tests/rfc3986/getters/uri_type_success_network_path_reference.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Uri\Rfc3986\Uri getter - uri type - Network path reference +--FILE-- +getUriType()); + +?> +--EXPECT-- +enum(Uri\Rfc3986\UriType::NetworkPathReference) diff --git a/ext/uri/tests/rfc3986/getters/uri_type_success_relative_path_reference.phpt b/ext/uri/tests/rfc3986/getters/uri_type_success_relative_path_reference.phpt new file mode 100644 index 000000000000..6cb51405f925 --- /dev/null +++ b/ext/uri/tests/rfc3986/getters/uri_type_success_relative_path_reference.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Uri\Rfc3986\Uri getter - uri type - Relative path reference +--FILE-- +getUriType()); + +?> +--EXPECT-- +enum(Uri\Rfc3986\UriType::RelativePathReference) diff --git a/ext/uri/tests/rfc3986/getters/uri_type_success_uri_basic.phpt b/ext/uri/tests/rfc3986/getters/uri_type_success_uri_basic.phpt new file mode 100644 index 000000000000..262300103f9c --- /dev/null +++ b/ext/uri/tests/rfc3986/getters/uri_type_success_uri_basic.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Uri\Rfc3986\Uri getter - uri type - URI +--FILE-- +getUriType()); + +?> +--EXPECT-- +enum(Uri\Rfc3986\UriType::Uri) diff --git a/ext/uri/tests/rfc3986/getters/uri_type_success_uri_empty_authority.phpt b/ext/uri/tests/rfc3986/getters/uri_type_success_uri_empty_authority.phpt new file mode 100644 index 000000000000..ad8f2f27a8c6 --- /dev/null +++ b/ext/uri/tests/rfc3986/getters/uri_type_success_uri_empty_authority.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Uri\Rfc3986\Uri getter - uri type - URI with empty authority +--FILE-- +getUriType()); + +?> +--EXPECT-- +enum(Uri\Rfc3986\UriType::Uri) diff --git a/ext/uri/tests/rfc3986/getters/uri_type_success_uri_no_authority.phpt b/ext/uri/tests/rfc3986/getters/uri_type_success_uri_no_authority.phpt new file mode 100644 index 000000000000..e266502ce90e --- /dev/null +++ b/ext/uri/tests/rfc3986/getters/uri_type_success_uri_no_authority.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Uri\Rfc3986\Uri getter - uri type - URI without authority +--FILE-- +getUriType()); + +?> +--EXPECT-- +enum(Uri\Rfc3986\UriType::Uri) diff --git a/ext/uri/tests/whatwg/getters/is_special_scheme_success_false.phpt b/ext/uri/tests/whatwg/getters/is_special_scheme_success_false.phpt new file mode 100644 index 000000000000..9bbb85755843 --- /dev/null +++ b/ext/uri/tests/whatwg/getters/is_special_scheme_success_false.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Uri\WhatWg\Url::isSpecialScheme() - success - not special +--FILE-- +isSpecialScheme()); + +?> +--EXPECT-- +bool(false) diff --git a/ext/uri/tests/whatwg/getters/is_special_scheme_success_true.phpt b/ext/uri/tests/whatwg/getters/is_special_scheme_success_true.phpt new file mode 100644 index 000000000000..1e19641b5600 --- /dev/null +++ b/ext/uri/tests/whatwg/getters/is_special_scheme_success_true.phpt @@ -0,0 +1,31 @@ +--TEST-- +Test Uri\WhatWg\Url::isSpecialScheme() - success - special +--FILE-- +isSpecialScheme()); + +$url = Uri\WhatWg\Url::parse("https://example.com"); +var_dump($url->isSpecialScheme()); + +$url = Uri\WhatWg\Url::parse("ws://example.com"); +var_dump($url->isSpecialScheme()); + +$url = Uri\WhatWg\Url::parse("wss://example.com"); +var_dump($url->isSpecialScheme()); + +$url = Uri\WhatWg\Url::parse("ftp://example.com"); +var_dump($url->isSpecialScheme()); + +$url = Uri\WhatWg\Url::parse("file://example.com"); +var_dump($url->isSpecialScheme()); + +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/ext/uri/uri_parser_rfc3986.c b/ext/uri/uri_parser_rfc3986.c index 172d7f08f144..cc7ea5b4a7f4 100644 --- a/ext/uri/uri_parser_rfc3986.c +++ b/ext/uri/uri_parser_rfc3986.c @@ -15,6 +15,7 @@ #include "php.h" #include "uri_parser_rfc3986.h" #include "php_uri_common.h" +#include "Zend/zend_enum.h" #include "Zend/zend_smart_str.h" #include "Zend/zend_exceptions.h" @@ -110,6 +111,27 @@ ZEND_ATTRIBUTE_NONNULL static UriUriA *get_uri_for_writing(php_uri_parser_rfc398 return &uriparser_uris->uri; } +ZEND_ATTRIBUTE_NONNULL void php_uri_parser_rfc3986_uri_type_read(void *uri, zval *retval) +{ + const UriUriA *uriparser_uri = get_uri_for_reading(uri, PHP_URI_COMPONENT_READ_MODE_RAW); + + if (has_text_range(&uriparser_uri->scheme)) { + ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_type, "Uri")); + return; + } + + if (has_text_range(&uriparser_uri->hostText)) { + ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_type, "NetworkPathReference")); + return; + } + + if (uriparser_uri->absolutePath) { + ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_type, "AbsolutePathReference")); + } else { + ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_type, "RelativePathReference")); + } +} + ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_scheme_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); diff --git a/ext/uri/uri_parser_rfc3986.h b/ext/uri/uri_parser_rfc3986.h index 21f938c370ad..f76a71eb0f45 100644 --- a/ext/uri/uri_parser_rfc3986.h +++ b/ext/uri/uri_parser_rfc3986.h @@ -21,6 +21,8 @@ PHPAPI extern const php_uri_parser php_uri_parser_rfc3986; typedef struct php_uri_parser_rfc3986_uris php_uri_parser_rfc3986_uris; +ZEND_ATTRIBUTE_NONNULL void php_uri_parser_rfc3986_uri_type_read(void *uri, zval *retval); + zend_result php_uri_parser_rfc3986_userinfo_read(php_uri_parser_rfc3986_uris *uri, php_uri_component_read_mode read_mode, zval *retval); zend_result php_uri_parser_rfc3986_userinfo_write(php_uri_parser_rfc3986_uris *uri, zval *value, zval *errors); diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c index d140357c18ed..4ca7073847e8 100644 --- a/ext/uri/uri_parser_whatwg.c +++ b/ext/uri/uri_parser_whatwg.c @@ -273,6 +273,11 @@ static zend_result php_uri_parser_whatwg_scheme_write(void *uri, zval *value, zv return SUCCESS; } +ZEND_ATTRIBUTE_NONNULL bool php_uri_parser_whatwg_is_special(const lxb_url_t *lexbor_uri) +{ + return lxb_url_is_special(lexbor_uri); +} + /* 4.2. URL miscellaneous: A URL includes credentials if its username or password is not the empty string. */ static bool includes_credentials(const lxb_url_t *lexbor_uri) { diff --git a/ext/uri/uri_parser_whatwg.h b/ext/uri/uri_parser_whatwg.h index 3e9e2824e42b..1ed2b4ac0e14 100644 --- a/ext/uri/uri_parser_whatwg.h +++ b/ext/uri/uri_parser_whatwg.h @@ -20,6 +20,8 @@ PHPAPI extern const php_uri_parser php_uri_parser_whatwg; +ZEND_ATTRIBUTE_NONNULL bool php_uri_parser_whatwg_is_special(const lxb_url_t *lexbor_uri); + lxb_url_t *php_uri_parser_whatwg_parse_ex(const char *uri_str, size_t uri_str_len, const lxb_url_t *lexbor_base_url, zval *errors, bool silent); PHP_RINIT_FUNCTION(uri_parser_whatwg); From 56d40c10ee0254fa8e7813c97c0422fd1415a76b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 19 May 2026 21:57:17 +0200 Subject: [PATCH 2/2] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tim Düsterhus --- ext/uri/uri_parser_rfc3986.c | 24 +++++++++++------------- ext/uri/uri_parser_rfc3986.h | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/ext/uri/uri_parser_rfc3986.c b/ext/uri/uri_parser_rfc3986.c index cc7ea5b4a7f4..cdf88013252f 100644 --- a/ext/uri/uri_parser_rfc3986.c +++ b/ext/uri/uri_parser_rfc3986.c @@ -111,25 +111,23 @@ ZEND_ATTRIBUTE_NONNULL static UriUriA *get_uri_for_writing(php_uri_parser_rfc398 return &uriparser_uris->uri; } -ZEND_ATTRIBUTE_NONNULL void php_uri_parser_rfc3986_uri_type_read(void *uri, zval *retval) +ZEND_ATTRIBUTE_NONNULL void php_uri_parser_rfc3986_uri_type_read(php_uri_parser_rfc3986_uris *uri, zval *retval) { const UriUriA *uriparser_uri = get_uri_for_reading(uri, PHP_URI_COMPONENT_READ_MODE_RAW); - if (has_text_range(&uriparser_uri->scheme)) { - ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_type, "Uri")); - return; - } - - if (has_text_range(&uriparser_uri->hostText)) { - ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_type, "NetworkPathReference")); - return; - } + const char *type; - if (uriparser_uri->absolutePath) { - ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_type, "AbsolutePathReference")); + if (has_text_range(&uriparser_uri->scheme)) { + type = "Uri"; + } else if (has_text_range(&uriparser_uri->hostText)) { + type = "NetworkPathReference"; + } else if (uriparser_uri->absolutePath) { + type = "AbsolutePathReference"; } else { - ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_type, "RelativePathReference")); + type = "RelativePathReference"; } + + ZVAL_OBJ_COPY(retval, zend_enum_get_case_cstr(php_uri_ce_rfc3986_uri_type, type)); } ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_scheme_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) diff --git a/ext/uri/uri_parser_rfc3986.h b/ext/uri/uri_parser_rfc3986.h index f76a71eb0f45..bf8a0733fc8a 100644 --- a/ext/uri/uri_parser_rfc3986.h +++ b/ext/uri/uri_parser_rfc3986.h @@ -21,7 +21,7 @@ PHPAPI extern const php_uri_parser php_uri_parser_rfc3986; typedef struct php_uri_parser_rfc3986_uris php_uri_parser_rfc3986_uris; -ZEND_ATTRIBUTE_NONNULL void php_uri_parser_rfc3986_uri_type_read(void *uri, zval *retval); +ZEND_ATTRIBUTE_NONNULL void php_uri_parser_rfc3986_uri_type_read(php_uri_parser_rfc3986_uris *uri, zval *retval); zend_result php_uri_parser_rfc3986_userinfo_read(php_uri_parser_rfc3986_uris *uri, php_uri_component_read_mode read_mode, zval *retval); zend_result php_uri_parser_rfc3986_userinfo_write(php_uri_parser_rfc3986_uris *uri, zval *value, zval *errors);