Skip to content

[RFC] Add RFC 3986 and WHATWG compliant URL parsing support #14461

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

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
196957b
Create separate lexbor extension
kocsismate May 11, 2025
0334e22
Add RFC 3986 and WHATWG compliant URL parsing support
kocsismate Jun 3, 2024
a09a457
Serialization
kocsismate Oct 22, 2024
3abdb0a
Improve error handling
kocsismate Oct 26, 2024
1445e55
Lot of fixes and added support for equalsTo()
kocsismate Nov 11, 2024
e4de160
Add normalization support
kocsismate Nov 13, 2024
77184ce
SOAP test fixes
kocsismate Nov 13, 2024
3b0449d
Fix some memory leaks
kocsismate Nov 13, 2024
5f90823
Some cleanups
kocsismate Nov 18, 2024
b7011b8
Changes based on discussion
kocsismate Nov 30, 2024
f20842a
Removal of Uri\Uri
kocsismate Dec 30, 2024
c88e92b
A lot of fixes and API changes
kocsismate Jan 6, 2025
c743ead
Updates
kocsismate Feb 5, 2025
19b7180
Add new tests, path fixes
kocsismate Feb 9, 2025
fb0c929
Add more tests for verifying the behavior of withers
kocsismate Feb 15, 2025
cf7ca4e
Fix code review comments
kocsismate Feb 19, 2025
9de1271
A few fixes and improvements after feedback
kocsismate Apr 14, 2025
db3b79d
Test fixes
kocsismate Apr 14, 2025
feefccf
Remove WHATWG non-raw getters
kocsismate Apr 18, 2025
190bbfd
Rename WHATWG getters again
kocsismate Apr 26, 2025
d1df694
Add UriComparisonMode
kocsismate Apr 28, 2025
0d1fc02
Expose $softErrors for Uri\WhatWg\Url::resolve()
kocsismate Apr 30, 2025
df1d0b9
Add SensitiveParameter support
kocsismate May 3, 2025
e8261f7
Proper build support
kocsismate May 19, 2025
7530dd9
Review fixes and serialization update according to the RFC
kocsismate May 20, 2025
b75cc5b
Some extension fixes
kocsismate May 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add new tests, path fixes
  • Loading branch information
kocsismate committed May 25, 2025
commit 19b7180e531fb6f7d032ba2ee79a40a19417a533
2 changes: 1 addition & 1 deletion ext/filter/logical_filters.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ void php_filter_validate_url(http://github.com/PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
}

/* Parse the URI - if it fails, we return NULL */
php_uri *uri = php_uri_parse_to_struct(uri_handler, Z_STR_P(value), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY, NULL);
php_uri *uri = php_uri_parse_to_struct(uri_handler, Z_STR_P(value), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING, NULL);
if (uri == NULL) {
RETURN_VALIDATION_FAILED
}
Expand Down
4 changes: 2 additions & 2 deletions ext/soap/php_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ int make_http_soap_request(zval *this_ptr,
zend_argument_value_error(6, "must be a valid URI parser name");
return FALSE;
}
uri = php_uri_parse_to_struct(uri_handler, location, URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY, NULL);
uri = php_uri_parse_to_struct(uri_handler, location, URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING, NULL);
}

tmp = Z_CLIENT_STREAM_CONTEXT_P(this_ptr);
Expand Down Expand Up @@ -1161,7 +1161,7 @@ int make_http_soap_request(zval *this_ptr,
}

zend_string *loc_str = zend_string_init(loc, strlen(loc), false);
php_uri *new_uri = php_uri_parse_to_struct(uri_handler, loc_str, URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY, NULL);
php_uri *new_uri = php_uri_parse_to_struct(uri_handler, loc_str, URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING, NULL);
zend_string_release(loc_str);

if (new_uri != NULL) {
Expand Down
27 changes: 15 additions & 12 deletions ext/uri/php_lexbor.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ const uri_handler_t lexbor_uri_handler = {
case URI_COMPONENT_READ_RAW: \
ZVAL_STRINGL(retval, (const char *) start, len); \
break; \
case URI_COMPONENT_READ_NORMALIZED_HUMAN_FRIENDLY: /* Intentional fallthrough */ \
case URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY: { \
case URI_COMPONENT_READ_NORMALIZED_FOR_DISPLAY: /* Intentional fallthrough */ \
case URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING: { \
lexbor_str_t *str = lexbor_str_create(); \
lxb_url_host_opt_t opt; \
lxb_status_t result = lxb_url_percent_decode(start, start + len, \
Expand Down Expand Up @@ -254,7 +254,9 @@ static lxb_status_t lexbor_serialize_callback(const lxb_char_t *data, size_t len
{
smart_str *uri_str = (smart_str *) ctx;

smart_str_appendl(uri_str, (const char *) data, length);
if (data != NULL && length > 0) {
smart_str_appendl(uri_str, (const char *) data, length);
}

return LXB_STATUS_OK;
}
Expand All @@ -264,7 +266,8 @@ static zend_result lexbor_read_scheme(const uri_internal_t *internal_uri, uri_co
lxb_url_t *lexbor_uri = (lxb_url_t *) internal_uri->uri;

ZEND_ASSERT(lexbor_uri->scheme.type != LXB_URL_SCHEMEL_TYPE__UNDEF);
LEXBOR_READ_PERCENT_ENCODED_URI_COMPONENT(lexbor_uri->scheme.name.data, lexbor_uri->scheme.name.length, read_mode, retval);

ZVAL_STRINGL(retval, (const char *) lexbor_uri->scheme.name.data, lexbor_uri->scheme.name.length);

return SUCCESS;
}
Expand Down Expand Up @@ -354,7 +357,7 @@ static zend_result lexbor_read_host(const uri_internal_t *internal_uri, uri_comp
} else if (lexbor_uri->host.type != LXB_URL_HOST_TYPE_EMPTY && lexbor_uri->host.type != LXB_URL_HOST_TYPE__UNDEF) {

switch (read_mode) {
case URI_COMPONENT_READ_NORMALIZED_HUMAN_FRIENDLY: {
case URI_COMPONENT_READ_NORMALIZED_FOR_DISPLAY: {
smart_str host_str = {0};
if (lexbor_parser->idna == NULL) {
lexbor_parser->idna = lxb_unicode_idna_create();
Expand All @@ -369,7 +372,7 @@ static zend_result lexbor_read_host(const uri_internal_t *internal_uri, uri_comp
ZVAL_STR(retval, smart_str_extract(&host_str));
break;
}
case URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY: /* Intentional fallthrough */
case URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING: /* Intentional fallthrough */
case URI_COMPONENT_READ_RAW:
ZVAL_STRINGL(retval, (const char *) lexbor_uri->host.u.domain.data, lexbor_uri->host.u.domain.length);
break;
Expand Down Expand Up @@ -425,8 +428,8 @@ static zend_result lexbor_read_path(const uri_internal_t *internal_uri, uri_comp

if (lexbor_uri->path.opaque) {
LEXBOR_READ_PERCENT_ENCODED_URI_COMPONENT(lexbor_uri->path.str.data, lexbor_uri->path.str.length, read_mode, retval);
} else if (lexbor_uri->path.str.length > 1) {
LEXBOR_READ_PERCENT_ENCODED_URI_COMPONENT(lexbor_uri->path.str.data + 1, lexbor_uri->path.str.length - 1, read_mode, retval);
} else if (lexbor_uri->path.str.length) {
Copy link
Member

Choose a reason for hiding this comment

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

these two blocks look the same - can they be combined?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, nice catch

LEXBOR_READ_PERCENT_ENCODED_URI_COMPONENT(lexbor_uri->path.str.data, lexbor_uri->path.str.length, read_mode, retval);
} else {
ZVAL_NULL(retval);
}
Expand Down Expand Up @@ -561,8 +564,8 @@ static zend_string *lexbor_uri_to_string(void *uri, uri_recomposition_mode_t rec
smart_str uri_str = {0};

switch (recomposition_mode) {
case URI_RECOMPOSITION_HUMAN_FRIENDLY: /* Intentional fallthrough */
case URI_RECOMPOSITION_NORMALIZED_HUMAN_FRIENDLY:
case URI_RECOMPOSITION_FOR_DISPLAY: /* Intentional fallthrough */
case URI_RECOMPOSITION_NORMALIZED_FOR_DISPLAY:
if (lexbor_parser->idna == NULL) {
lexbor_parser->idna = lxb_unicode_idna_create();
lxb_status_t status = lxb_unicode_idna_init(lexbor_parser->idna);
Expand All @@ -573,8 +576,8 @@ static zend_string *lexbor_uri_to_string(void *uri, uri_recomposition_mode_t rec
lxb_url_serialize_unicode(lexbor_parser->idna, lexbor_uri, lexbor_serialize_callback, (void *) &uri_str, exclude_fragment);
lxb_unicode_idna_clean(lexbor_parser->idna);
break;
case URI_RECOMPOSITION_MACHINE_FRIENDLY: /* Intentional fallthrough */
case URI_RECOMPOSITION_NORMALIZED_MACHINE_FRIENDLY:
case URI_RECOMPOSITION_FOR_MACHINE_PROCESSING: /* Intentional fallthrough */
case URI_RECOMPOSITION_NORMALIZED_FOR_MACHINE_PROCESSING:
lxb_url_serialize(lexbor_uri, lexbor_serialize_callback, (void *) &uri_str, exclude_fragment);
break;
EMPTY_SWITCH_DEFAULT_CASE()
Expand Down
45 changes: 20 additions & 25 deletions ext/uri/php_uri.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ PHP_METHOD(Uri_WhatWg_Url, __construct)

PHP_METHOD(Uri_Rfc3986_Uri, getScheme)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_SCHEME), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_SCHEME), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING);
}

PHP_METHOD(Uri_Rfc3986_Uri, getRawScheme)
Expand All @@ -465,7 +465,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, withScheme)

PHP_METHOD(Uri_Rfc3986_Uri, getUserInfo)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_USERINFO), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_USERINFO), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING);
}

PHP_METHOD(Uri_Rfc3986_Uri, getRawUserInfo)
Expand All @@ -480,7 +480,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, withUserInfo)

PHP_METHOD(Uri_Rfc3986_Uri, getUser)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_USER), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_USER), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING);
}

PHP_METHOD(Uri_Rfc3986_Uri, getRawUser)
Expand All @@ -490,7 +490,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, getRawUser)

PHP_METHOD(Uri_Rfc3986_Uri, getPassword)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_PASSWORD), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_PASSWORD), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING);
}

PHP_METHOD(Uri_Rfc3986_Uri, getRawPassword)
Expand All @@ -500,7 +500,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, getRawPassword)

PHP_METHOD(Uri_Rfc3986_Uri, getHost)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_HOST), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_HOST), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING);
}

PHP_METHOD(Uri_Rfc3986_Uri, getRawHost)
Expand All @@ -515,7 +515,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, withHost)

PHP_METHOD(Uri_Rfc3986_Uri, getPort)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_PORT), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_PORT), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING);
}

PHP_METHOD(Uri_Rfc3986_Uri, withPort)
Expand All @@ -525,7 +525,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, withPort)

PHP_METHOD(Uri_Rfc3986_Uri, getPath)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_PATH), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_PATH), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING);
}

PHP_METHOD(Uri_Rfc3986_Uri, getRawPath)
Expand All @@ -540,7 +540,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, withPath)

PHP_METHOD(Uri_Rfc3986_Uri, getQuery)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_QUERY), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_QUERY), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING);
}

PHP_METHOD(Uri_Rfc3986_Uri, getRawQuery)
Expand All @@ -555,7 +555,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, withQuery)

PHP_METHOD(Uri_Rfc3986_Uri, getFragment)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_FRAGMENT), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_FRAGMENT), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING);
}

PHP_METHOD(Uri_Rfc3986_Uri, getRawFragment)
Expand Down Expand Up @@ -585,9 +585,9 @@ static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, b
}

zend_string *this_str = this_internal_uri->handler->uri_to_string(
this_internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_MACHINE_FRIENDLY, exclude_fragment);
this_internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_FOR_MACHINE_PROCESSING, exclude_fragment);
zend_string *that_str = that_internal_uri->handler->uri_to_string(
that_internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_MACHINE_FRIENDLY, exclude_fragment);
that_internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_FOR_MACHINE_PROCESSING, exclude_fragment);

RETVAL_BOOL(zend_string_equals(this_str, that_str));

Expand Down Expand Up @@ -617,7 +617,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, toString)
uri_internal_t *internal_uri = uri_internal_from_obj(this_object);
URI_CHECK_INITIALIZATION_RETURN_THROWS(internal_uri, this_object);

RETURN_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_MACHINE_FRIENDLY, false));
RETURN_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_FOR_MACHINE_PROCESSING, false));
}

PHP_METHOD(Uri_Rfc3986_Uri, toNormalizedString)
Expand All @@ -628,7 +628,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, toNormalizedString)
uri_internal_t *internal_uri = uri_internal_from_obj(object);
URI_CHECK_INITIALIZATION_RETURN_THROWS(internal_uri, object);

RETVAL_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_MACHINE_FRIENDLY, false));
RETVAL_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_FOR_MACHINE_PROCESSING, false));
}

PHP_METHOD(Uri_Rfc3986_Uri, resolve)
Expand All @@ -644,7 +644,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, resolve)
URI_CHECK_INITIALIZATION_RETURN_THROWS(internal_uri, this_object);

zend_string *base_uri_str = internal_uri->handler->uri_to_string(
internal_uri->uri, URI_RECOMPOSITION_MACHINE_FRIENDLY, false); // TODO optimize by not reparsing the base URI
internal_uri->uri, URI_RECOMPOSITION_FOR_MACHINE_PROCESSING, false); // TODO optimize by not reparsing the base URI

php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal_uri->handler, uri_str, base_uri_str, true, NULL);
}
Expand All @@ -665,7 +665,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, __serialize)
}

zval uri_zv;
ZVAL_STR(&uri_zv, internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_MACHINE_FRIENDLY, false));
ZVAL_STR(&uri_zv, internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_FOR_MACHINE_PROCESSING, false));
zend_hash_str_add_new(result, URI_SERIALIZED_PROPERTY_NAME, sizeof(URI_SERIALIZED_PROPERTY_NAME) - 1, &uri_zv);

ZVAL_ARR(return_value, result);
Expand Down Expand Up @@ -747,12 +747,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, __debugInfo)

PHP_METHOD(Uri_WhatWg_Url, getScheme)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_SCHEME), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY);
}

PHP_METHOD(Uri_WhatWg_Url, getRawScheme)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_SCHEME), URI_COMPONENT_READ_RAW);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_SCHEME), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING);
}

PHP_METHOD(Uri_WhatWg_Url, withScheme)
Expand All @@ -772,12 +767,12 @@ PHP_METHOD(Uri_WhatWg_Url, withPassword)

PHP_METHOD(Uri_WhatWg_Url, getHost)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_HOST), URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_HOST), URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING);
}

PHP_METHOD(Uri_WhatWg_Url, getHostForDisplay)
{
URI_GETTER(ZSTR_KNOWN(ZEND_STR_HOST), URI_COMPONENT_READ_NORMALIZED_HUMAN_FRIENDLY);
URI_GETTER(ZSTR_KNOWN(ZEND_STR_HOST), URI_COMPONENT_READ_NORMALIZED_FOR_DISPLAY);
}

PHP_METHOD(Uri_WhatWg_Url, withHost)
Expand Down Expand Up @@ -819,7 +814,7 @@ PHP_METHOD(Uri_WhatWg_Url, toDisplayString)
uri_internal_t *internal_uri = uri_internal_from_obj(this_object);
URI_CHECK_INITIALIZATION_RETURN_THROWS(internal_uri, this_object);

RETURN_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_HUMAN_FRIENDLY, false));
RETURN_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_FOR_DISPLAY, false));
}

PHP_METHOD(Uri_WhatWg_Url, toString)
Expand All @@ -830,7 +825,7 @@ PHP_METHOD(Uri_WhatWg_Url, toString)
uri_internal_t *internal_uri = uri_internal_from_obj(this_object);
URI_CHECK_INITIALIZATION_RETURN_THROWS(internal_uri, this_object);

RETURN_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_MACHINE_FRIENDLY, false));
RETURN_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_FOR_MACHINE_PROCESSING, false));
}

PHP_METHOD(Uri_WhatWg_Url, __unserialize)
Expand Down
2 changes: 0 additions & 2 deletions ext/uri/php_uri.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,6 @@ public function __construct(string $uri, ?string $baseUrl = null, &$softErrors =

public function getScheme(): string {}

public function getRawScheme(): string {}

public function withScheme(string $encodedScheme): static {}

/** @implementation-alias Uri\Rfc3986\Uri::getUser */
Expand Down
6 changes: 1 addition & 5 deletions ext/uri/php_uri_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions ext/uri/php_uri_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ extern zend_class_entry *whatwg_error_type_ce;
extern zend_class_entry *whatwg_error_ce;

typedef enum {
URI_RECOMPOSITION_MACHINE_FRIENDLY,
URI_RECOMPOSITION_HUMAN_FRIENDLY,
URI_RECOMPOSITION_NORMALIZED_HUMAN_FRIENDLY,
URI_RECOMPOSITION_NORMALIZED_MACHINE_FRIENDLY,
URI_RECOMPOSITION_FOR_MACHINE_PROCESSING,
URI_RECOMPOSITION_FOR_DISPLAY,
URI_RECOMPOSITION_NORMALIZED_FOR_MACHINE_PROCESSING,
URI_RECOMPOSITION_NORMALIZED_FOR_DISPLAY,
} uri_recomposition_mode_t;

typedef enum {
URI_COMPONENT_READ_RAW,
URI_COMPONENT_READ_NORMALIZED_HUMAN_FRIENDLY,
URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY,
URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING,
URI_COMPONENT_READ_NORMALIZED_FOR_DISPLAY,
} uri_component_read_mode_t;

typedef struct uri_handler_t {
Expand Down
15 changes: 6 additions & 9 deletions ext/uri/php_uriparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ static zend_result uriparser_normalize_uri(UriUriA *uriparser_uri)
#define URIPARSER_READ_URI(uriparser_uri, uriparser_uris, read_mode) do { \
if (read_mode == URI_COMPONENT_READ_RAW) { \
uriparser_uri = (UriUriA *) uriparser_uris->uri; \
Copy link
Member

Choose a reason for hiding this comment

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

a few lines here were indented by spaces not tabs

} else if (read_mode == URI_COMPONENT_READ_NORMALIZED_HUMAN_FRIENDLY || read_mode == URI_COMPONENT_READ_NORMALIZED_MACHINE_FRIENDLY) { \
} else if (read_mode == URI_COMPONENT_READ_NORMALIZED_FOR_DISPLAY || read_mode == URI_COMPONENT_READ_NORMALIZED_FOR_MACHINE_PROCESSING) { \
if (uriparser_uris->normalized_uri == NULL) { \
uriparser_uris->normalized_uri = uriparser_copy_uri(uriparser_uris->uri); \
if (uriparser_normalize_uri(uriparser_uris->normalized_uri) == FAILURE) { \
Expand Down Expand Up @@ -260,6 +260,10 @@ static zend_result uriparser_read_path(const uri_internal_t *internal_uri, uri_c
const UriPathSegmentA *p;
smart_str str = {0};

if (uriparser_uri->absolutePath || uriIsHostSetA(uriparser_uri)) {
smart_str_appends(&str, "/");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
smart_str_appends(&str, "/");
smart_str_appendc(&str, '/');

}

smart_str_appendl(&str, uriparser_uri->pathHead->text.first, (int) ((uriparser_uri->pathHead->text).afterLast - (uriparser_uri->pathHead->text).first));

for (p = uriparser_uri->pathHead->next; p != NULL; p = p->next) {
Expand Down Expand Up @@ -355,15 +359,8 @@ static void uriparser_append_port(const uri_internal_t *internal_uri, smart_str

static void uriparser_append_path(const uri_internal_t *internal_uri, smart_str *uri_str)
{
uriparser_uris_t *uriparser_uris = (uriparser_uris_t *) internal_uri->uri;
UriUriA *uriparser_uri = uriparser_uris->uri;

zval tmp;

if (uriparser_uri->absolutePath || (uriparser_uri->pathHead != NULL && uriIsHostSetA(uriparser_uri))) {
smart_str_appends(uri_str, "/");
}

uriparser_read_path(internal_uri, URI_COMPONENT_READ_RAW, &tmp);
if (Z_TYPE(tmp) == IS_STRING && Z_STRLEN(tmp) > 0) {
smart_str_append(uri_str, Z_STR(tmp));
Expand Down Expand Up @@ -679,7 +676,7 @@ static zend_string *uriparser_uri_to_string(void *uri, uri_recomposition_mode_t
uriparser_uris_t *uriparser_uris = (uriparser_uris_t *) uri;
UriUriA *uriparser_uri = uriparser_uris->uri;

if ((recomposition_mode == URI_RECOMPOSITION_NORMALIZED_HUMAN_FRIENDLY || recomposition_mode == URI_RECOMPOSITION_NORMALIZED_MACHINE_FRIENDLY) &&
if ((recomposition_mode == URI_RECOMPOSITION_NORMALIZED_FOR_DISPLAY || recomposition_mode == URI_RECOMPOSITION_NORMALIZED_FOR_MACHINE_PROCESSING) &&
uriparser_uris->normalized_uri == NULL
) {
uriparser_uris->normalized_uri = uriparser_copy_uri(uriparser_uris->uri);
Expand Down
Loading