10000 Add the Uri\Rfc3986\Uri class to ext/uri without wither support by kocsismate · Pull Request #18836 · php/php-src · GitHub
[go: up one dir, main page]

Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jul 5, 2025
Merged
Prev Previous commit
Next Next commit
Allocate on stack
  • Loading branch information
kocsismate committed Jul 4, 2025
commit 35a1217eb80de1de541932ead0dcbaaf7baea18e
132 changes: 63 additions & 69 deletions ext/uri/php_uriparser.c
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something I'm only noticing now: I think this should rather be called ext/uri/parser_rfc3986.c and php_lexbor.c would be ext/uri/parser_whatwg.c. The php_uriparser.c name is confusing to me, because uriparser is an extremely generic term.

To give another comparison with ext/random, since it is architecturally similar: Each engine has its own engine_enginename.c file, e.g. engine_xoshiro256starstar.c.

Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,12 @@ static inline size_t get_text_range_length(const UriTextRangeA *range)
return range->afterLast - range->first;
}

static UriUriA *uriparser_copy_uri(UriUriA *uriparser_uri)
static void uriparser_copy_uri(UriUriA *new_uriparser_uri, UriUriA *uriparser_uri)
{
ZEND_ASSERT(uriparser_uri != NULL);

UriUriA *new_uriparser_uri = emalloc(sizeof(UriUriA));
ZEND_ASSERT(new_uriparser_uri != NULL && uriparser_uri != NULL);

int result = uriCopyUriA(new_uriparser_uri, uriparser_uri);
ZEND_ASSERT(result == URI_SUCCESS && new_uriparser_uri != NULL);

return new_uriparser_uri;
}

static void uriparser_normalize_uri(UriUriA *uriparser_uri)
Expand All @@ -46,20 +42,26 @@ static void uriparser_normalize_uri(UriUriA *uriparser_uri)
ZEND_ASSERT(result == URI_SUCCESS);
}

static void normalize_uri_if_needed(uriparser_uris_t *uriparser_uris)
{
if (uriparser_uris->normalized_uri_initialized == false) {
uriparser_copy_uri(&uriparser_uris->normalized_uri, &uriparser_uris->uri);
uriparser_normalize_uri(&uriparser_uris->normalized_uri);
uriparser_uris->normalized_uri_initialized = true;
}
}

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;
return &uriparser_uris->uri;
case URI_COMPONENT_READ_NORMALIZED_ASCII:
ZEND_FALLTHROUGH;
case URI_COMPONENT_READ_NORMALIZED_UNICODE:
if (uriparser_uris->normalized_uri == NULL) {
uriparser_uris->normalized_uri = uriparser_copy_uri(uriparser_uris->uri);
uriparser_normalize_uri(uriparser_uris->normalized_uri);
}
normalize_uri_if_needed(uriparser_uris);

return uriparser_uris->normalized_uri;
return &uriparser_uris->normalized_uri;
EMPTY_SWITCH_DEFAULT_CASE()
}
}
Expand Down Expand Up @@ -283,62 +285,58 @@ PHP_MINIT_FUNCTION(uri_uriparser)
return SUCCESS;
}

static uriparser_uris_t *uriparser_create_uris(
UriUriA *uri,
UriUriA *normalized_uri
) {
uriparser_uris_t *uriparser_uris = emalloc(sizeof(uriparser_uris_t));

uriparser_uris->uri = uri;
uriparser_uris->normalized_uri = normalized_uri;
static uriparser_uris_t *uriparser_create_uris(void)
{
uriparser_uris_t *uriparser_uris = emalloc(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, "URI parsing failed", 0);
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)
{
UriUriA *uriparser_uri = emalloc(sizeof(UriUriA));

if (ZSTR_LEN(uri_str) == 0 ||
uriParseSingleUriExA(uriparser_uri, ZSTR_VAL(uri_str), ZSTR_VAL(uri_str) + ZSTR_LEN(uri_str), NULL) != URI_SUCCESS
) {
efree(uriparser_uri);
if (!silent) {
throw_invalid_uri_exception();
}
uriparser_uris_t *uriparser_uris = uriparser_create_uris();

return NULL;
}

uriMakeOwnerA(uriparser_uri);
if (uriparser_base_urls == NULL) {
return uriparser_create_uris(uriparser_uri, NULL);
}
PARSE_URI(&uriparser_uris->uri, uri_str, uriparser_uris, silent);
uriMakeOwnerA(&uriparser_uris->uri);
} else {
UriUriA uri;

UriUriA *absolute_uri = emalloc(sizeof(UriUriA));
PARSE_URI(&uri, uri_str, uriparser_uris, silent);

if (uriAddBaseUriA(absolute_uri, uriparser_uri, uriparser_base_urls->uri) != URI_SUCCESS) {
uriFreeUriMembersA(uriparser_uri);
efree(uriparser_uri);
efree(absolute_uri);
if (uriAddBaseUriA(&uriparser_uris->uri, &uri, &uriparser_base_urls->uri) != URI_SUCCESS) {
efree(uriparser_uris);
if (!silent) {
throw_invalid_uri_exception();
}

if (!silent) {
throw_invalid_uri_exception();
return NULL;
}

return NULL;
uriMakeOwnerA(&uriparser_uris->uri);
uriFreeUriMembersA(&uri);
}

uriMakeOwnerA(absolute_uri);
uriFreeUriMembersA(uriparser_uri);
efree(uriparser_uri);

return uriparser_create_uris(absolute_uri, NULL);
return uriparser_uris;
}

void *uriparser_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors, bool silent)
Expand All @@ -354,10 +352,14 @@ static void *uriparser_clone_uri(void *uri)
{
uriparser_uris_t *uriparser_uris = (uriparser_uris_t *) uri;

return uriparser_create_uris(
uriparser_copy_uri(uriparser_uris->uri),
uriparser_uris->normalized_uri != NULL ? uriparser_copy_uri(uriparser_uris->normalized_uri) : NULL
);
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;
}

static zend_string *uriparser_uri_to_string(void *uri, uri_recomposition_mode_t recomposition_mode, bool exclude_fragment)
Expand All @@ -366,13 +368,11 @@ static zend_string *uriparser_uri_to_string(void *uri, uri_recomposition_mode_t
UriUriA *uriparser_uri;

if (recomposition_mode == URI_RECOMPOSITION_RAW_ASCII || recomposition_mode == URI_RECOMPOSITION_RAW_UNICODE) {
uriparser_uri = uriparser_uris->uri;
uriparser_uri = &uriparser_uris->uri;
} else {
if (uriparser_uris->normalized_uri == NULL) {
uriparser_uris->normalized_uri = uriparser_copy_uri(uriparser_uris->uri);
uriparser_normalize_uri(uriparser_uris->normalized_uri);
}
uriparser_uri = uriparser_uris->normalized_uri;
normalize_uri_if_needed(uriparser_uris);

uriparser_uri = &uriparser_uris->normalized_uri;
}

int charsRequired = 0;
Expand All @@ -399,18 +399,12 @@ static void uriparser_free_uri(void *uri)
{
uriparser_uris_t *uriparser_uris = (uriparser_uris_t *) uri;

if (uriparser_uris->uri != NULL) {
uriFreeUriMembersA(uriparser_uris->uri);
efree(uriparser_uris->uri);
uriparser_uris->uri = NULL;
}
uriFreeUriMembersA(&uriparser_uris->uri);

if (uriparser_uris->normalized_uri != NULL) {
ZEND_ASSERT(uriparser_uris->normalized_uri->owner);
if (uriparser_uris->normalized_uri_initialized) {
ZEND_ASSERT(uriparser_uris->normalized_uri.owner);

uriFreeUriMembersA(uriparser_uris->normalized_uri);
efree(uriparser_uris->normalized_uri);
uriparser_uris->normalized_uri = NULL;
uriFreeUriMembersA(&uriparser_uris->normalized_uri);
}

efree(uriparser_uris);
Expand Down
5 changes: 3 additions & 2 deletions ext/uri/php_uriparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
extern const uri_handler_t uriparser_uri_handler;

typedef struct uriparser_uris_t {
UriUriA *uri;
UriUriA *normalized_uri;
UriUriA uri;
UriUriA normalized_uri;
bool normalized_uri_initialized;
} uriparser_uris_t;

PHP_MINIT_FUNCTION(uri_uriparser);
Expand Down
2 changes: 1 addition & 1 deletion ext/uri/tests/004.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ var_dump(Uri\WhatWg\Url::parse("http://RuPaul's Drag Race All Stars 7 Winners Ca

?>
--EXPECTF--
The specified URI is malformed (MissingSchemeNonRelativeUrl)
The specified URI is malformed
NULL
The specified URI is malformed (MissingSchemeNonRelativeUrl)
NULL
Expand Down
2 changes: 1 addition & 1 deletion ext/uri/tests/007.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var_dump($failures);

?>
--EXPECTF--
The specified URI is malformed (PortInvalid)
The specified URI is malformed
The specified URI is malformed (PortInvalid)
array(%d) {
[0]=>
Expand Down
2 changes: 1 addition & 1 deletion ext/uri/tests/051.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var_dump($softErrors);

?>
--EXPECTF--
The specified URI is malformed (Ipv4TooManyParts)
The specified URI is malformed
The specified URI is malformed (Ipv4TooManyParts)
string(23) "https://example.com/foo"
array(%d) {
Expand Down
0