Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 1 addition & 5 deletions ext/uri/php_uri.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,7 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_get_property(const uri_interna
return FAILURE;
}

zend_result result = property_handler->read_func(internal_uri, read_mode, zv);

ZEND_ASSERT(result == FAILURE || (Z_TYPE_P(zv) == IS_STRING && GC_REFCOUNT(Z_STR_P(zv)) == 2) || Z_TYPE_P(zv) == IS_NULL || Z_TYPE_P(zv) == IS_LONG);

return result;
return property_handler->read_func(internal_uri, read_mode, zv);
}

ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_scheme(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv)
Expand Down
52 changes: 52 additions & 0 deletions ext/uri/tests/100.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
--TEST--
Test the parse_url-based URI parser
--EXTENSIONS--
uri
zend_test
--FILE--
<?php

var_dump(zend_test_uri_parser("https://%65xample:%65xample@%65xample.com:123/%65xample.html?%65xample=%65xample#%65xample", "parse_url"));

?>
--EXPECT--
array(2) {
["normalized"]=>
array(8) {
["scheme"]=>
string(5) "https"
["username"]=>
string(7) "example"
["password"]=>
string(7) "example"
["host"]=>
string(11) "example.com"
["port"]=>
int(123)
["path"]=>
string(13) "/example.html"
["query"]=>
string(15) "example=example"
["fragment"]=>
string(7) "example"
}
["raw"]=>
array(8) {
["scheme"]=>
string(5) "https"
["username"]=>
string(9) "%65xample"
["password"]=>
string(9) "%65xample"
["host"]=>
string(13) "%65xample.com"
["port"]=>
int(123)
["path"]=>
string(15) "/%65xample.html"
["query"]=>
string(19) "%65xample=%65xample"
["fragment"]=>
string(9) "%65xample"
}
}
42 changes: 19 additions & 23 deletions ext/uri/uri_parser_php_parse_url.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,29 @@
#include "Zend/zend_exceptions.h"
#include "ext/standard/url.h"

static void decode_component(zval *zv, uri_component_read_mode_t read_mode)
static zend_string *decode_component(zend_string *in, uri_component_read_mode_t read_mode)
{
if (Z_TYPE_P(zv) != IS_STRING) {
return;
}
switch (read_mode) {
case URI_COMPONENT_READ_RAW:
return zend_string_copy(in);
case URI_COMPONENT_READ_NORMALIZED_ASCII:
case URI_COMPONENT_READ_NORMALIZED_UNICODE: {
zend_string *out = zend_string_alloc(ZSTR_LEN(in), false);

if (read_mode == URI_COMPONENT_READ_RAW) {
return;
}
ZSTR_LEN(out) = php_raw_url_decode_ex(ZSTR_VAL(out), ZSTR_VAL(in), ZSTR_LEN(in));

php_raw_url_decode(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
return out;
}
EMPTY_SWITCH_DEFAULT_CASE();
}
}

static zend_result uri_parser_php_parse_url_scheme_read(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
{
const php_url *parse_url_uri = internal_uri->uri;

if (parse_url_uri->scheme) {
ZVAL_STR_COPY(retval, parse_url_uri->scheme);
decode_component(retval, read_mode);
ZVAL_STR(retval, decode_component(parse_url_uri->scheme, read_mode));
} else {
ZVAL_NULL(retval);
}
Expand All @@ -53,8 +56,7 @@ static zend_result uri_parser_php_parse_url_username_read(const uri_internal_t *
const php_url *parse_url_uri = internal_uri->uri;

if (parse_url_uri->user) {
ZVAL_STR_COPY(retval, parse_url_uri->user);
decode_component(retval, read_mode);
ZVAL_STR(retval, decode_component(parse_url_uri->user, read_mode));
} else {
ZVAL_NULL(retval);
}
Expand All @@ -67,8 +69,7 @@ static zend_result uri_parser_php_parse_url_password_read(const uri_internal_t *
const php_url *parse_url_uri = internal_uri->uri;

if (parse_url_uri->pass) {
ZVAL_STR_COPY(retval, parse_url_uri->pass);
decode_component(retval, read_mode);
ZVAL_STR(retval, decode_component(parse_url_uri->pass, read_mode));
} else {
ZVAL_NULL(retval);
}
Expand All @@ -81,8 +82,7 @@ static zend_result uri_parser_php_parse_url_host_read(const uri_internal_t *inte
const php_url *parse_url_uri = internal_uri->uri;

if (parse_url_uri->host) {
ZVAL_STR_COPY(retval, parse_url_uri->host);
decode_component(retval, read_mode);
ZVAL_STR(retval, decode_component(parse_url_uri->host, read_mode));
} else {
ZVAL_NULL(retval);
}
Expand All @@ -96,7 +96,6 @@ static zend_result uri_parser_php_parse_url_port_read(const uri_internal_t *inte

if (parse_url_uri->port) {
ZVAL_LONG(retval, parse_url_uri->port);
decode_component(retval, read_mode);
} else {
ZVAL_NULL(retval);
}
Expand All @@ -109,8 +108,7 @@ static zend_result uri_parser_php_parse_url_path_read(const uri_internal_t *inte
const php_url *parse_url_uri = internal_uri->uri;

if (parse_url_uri->path) {
ZVAL_STR_COPY(retval, parse_url_uri->path);
decode_component(retval, read_mode);
ZVAL_STR(retval, decode_component(parse_url_uri->path, read_mode));
} else {
ZVAL_NULL(retval);
}
Expand All @@ -123,8 +121,7 @@ static zend_result uri_parser_php_parse_url_query_read(const uri_internal_t *int
const php_url *parse_url_uri = internal_uri->uri;

if (parse_url_uri->query) {
ZVAL_STR_COPY(retval, parse_url_uri->query);
decode_component(retval, read_mode);
ZVAL_STR(retval, decode_component(parse_url_uri->query, read_mode));
} else {
ZVAL_NULL(retval);
}
Expand All @@ -137,8 +134,7 @@ static zend_result uri_parser_php_parse_url_fragment_read(const uri_internal_t *
const php_url *parse_url_uri = internal_uri->uri;

if (parse_url_uri->fragment) {
ZVAL_STR_COPY(retval, parse_url_uri->fragment);
decode_component(retval, read_mode);
ZVAL_STR(retval, decode_component(parse_url_uri->fragment, read_mode));
} else {
ZVAL_NULL(retval);
}
Expand Down
67 changes: 67 additions & 0 deletions ext/zend_test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "zend_call_stack.h"
#include "zend_exceptions.h"
#include "zend_mm_custom_handlers.h"
#include "ext/uri/php_uri.h"

#if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
# include <libxml/globals.h>
Expand Down Expand Up @@ -724,6 +725,72 @@ static ZEND_FUNCTION(zend_test_crash)
php_printf("%s", invalid);
}

static ZEND_FUNCTION(zend_test_uri_parser)
Copy link
Member

Choose a reason for hiding this comment

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

What I've done for DOM once is define a debugging function under #if ZEND_DEBUG. Doing that here too would keep the uri stuff in ext/uri.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll leave the decision to Máté 😃

Copy link
Member

Choose a reason for hiding this comment

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

I'm fine with adding this function to ext/zend_test. :) It doesn't make it more difficult for any tooling to parse stub files.

E.g. adding any symbol to stub files that is not for production should have the @undocumentable phpdoc, otherwise the documentation generator tries to sync it with the manual. AFAIK PHPStan also parses these files. So 👍 overall!

{
zend_string *uri_string;
zend_string *parser_name;

ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_STR(uri_string)
Z_PARAM_STR(parser_name)
ZEND_PARSE_PARAMETERS_END();

uri_parser_t *parser = php_uri_get_parser(parser_name);
if (parser == NULL) {
zend_argument_value_error(1, "Unknown parser");
RETURN_THROWS();
}

uri_internal_t *uri = php_uri_parse(parser, ZSTR_VAL(uri_string), ZSTR_LEN(uri_string), false);
if (uri == NULL) {
RETURN_THROWS();
}

zval value;

array_init(return_value);
zval normalized;
array_init(&normalized);
php_uri_get_scheme(uri, URI_COMPONENT_READ_NORMALIZED_ASCII, &value);
zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_SCHEME), &value);
php_uri_get_username(uri, URI_COMPONENT_READ_NORMALIZED_ASCII, &value);
zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_USERNAME), &value);
php_uri_get_password(uri, URI_COMPONENT_READ_NORMALIZED_ASCII, &value);
zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_PASSWORD), &value);
php_uri_get_host(uri, URI_COMPONENT_READ_NORMALIZED_ASCII, &value);
zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_HOST), &value);
php_uri_get_port(uri, URI_COMPONENT_READ_NORMALIZED_ASCII, &value);
zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_PORT), &value);
php_uri_get_path(uri, URI_COMPONENT_READ_NORMALIZED_ASCII, &value);
zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_PATH), &value);
php_uri_get_query(uri, URI_COMPONENT_READ_NORMALIZED_ASCII, &value);
zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_QUERY), &value);
php_uri_get_fragment(uri, URI_COMPONENT_READ_NORMALIZED_ASCII, &value);
zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_FRAGMENT), &value);
zend_hash_str_add(Z_ARR_P(return_value), "normalized", strlen("normalized"), &normalized);
zval raw;
array_init(&raw);
php_uri_get_scheme(uri, URI_COMPONENT_READ_RAW, &value);
zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_SCHEME), &value);
php_uri_get_username(uri, URI_COMPONENT_READ_RAW, &value);
zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_USERNAME), &value);
php_uri_get_password(uri, URI_COMPONENT_READ_RAW, &value);
zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_PASSWORD), &value);
php_uri_get_host(uri, URI_COMPONENT_READ_RAW, &value);
zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_HOST), &value);
php_uri_get_port(uri, URI_COMPONENT_READ_RAW, &value);
zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_PORT), &value);
php_uri_get_path(uri, URI_COMPONENT_READ_RAW, &value);
zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_PATH), &value);
php_uri_get_query(uri, URI_COMPONENT_READ_RAW, &value);
zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_QUERY), &value);
php_uri_get_fragment(uri, URI_COMPONENT_READ_RAW, &value);
zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_FRAGMENT), &value);
zend_hash_str_add(Z_ARR_P(return_value), "raw", strlen("raw"), &raw);

php_uri_free(uri);
}

static bool has_opline(zend_execute_data *execute_data)
{
return execute_data
Expand Down
2 changes: 2 additions & 0 deletions ext/zend_test/test.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,8 @@ function zend_test_compile_to_ast(string $str): string {}
function zend_test_gh18756(): void {}

function zend_test_opcache_preloading(): bool {}

function zend_test_uri_parser(string $uri, string $parser): array { }
}

namespace ZendTestNS {
Expand Down
9 changes: 8 additions & 1 deletion ext/zend_test/test_arginfo.h

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