[php-src] master: Implement "Followup improvements for ext/uri" RFC - WHATWG URL percent-encoding (#22820)
Máté Kocsis via GitHub <[email protected]>
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: Máté Kocsis (kocsismate)
Committer: GitHub (web-flow)
Pusher: kocsismate
Date: 2026-08-30T14:25:46+02:00
Commit: https://github.com/php/php-src/commit/1273587b05ad44e917990ef8740e5fb8b610b6ce
Raw diff: https://github.com/php/php-src/commit/1273587b05ad44e917990ef8740e5fb8b610b6ce.diff
Implement "Followup improvements for ext/uri" RFC - WHATWG URL percent-encoding (#22820)
RFC: https://wiki.php.net/rfc/uri_followup#percent-encoding_support
Changed paths:
A ext/uri/tests/whatwg/percent_encoding/form_query_success_control.phpt
A ext/uri/tests/whatwg/percent_encoding/form_query_success_percent.phpt
A ext/uri/tests/whatwg/percent_encoding/form_query_success_space.phpt
A ext/uri/tests/whatwg/percent_encoding/form_query_success_special_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/form_query_success_special_not_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/form_query_success_unicode.phpt
A ext/uri/tests/whatwg/percent_encoding/fragment_success_control.phpt
A ext/uri/tests/whatwg/percent_encoding/fragment_success_percent.phpt
A ext/uri/tests/whatwg/percent_encoding/fragment_success_special_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/fragment_success_special_not_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/fragment_success_unicode.phpt
A ext/uri/tests/whatwg/percent_encoding/opaque_host_success_control.phpt
A ext/uri/tests/whatwg/percent_encoding/opaque_host_success_percent.phpt
A ext/uri/tests/whatwg/percent_encoding/opaque_host_success_special_not_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/opaque_host_success_unicode.phpt
A ext/uri/tests/whatwg/percent_encoding/opaque_path_success_control.phpt
A ext/uri/tests/whatwg/percent_encoding/opaque_path_success_percent.phpt
A ext/uri/tests/whatwg/percent_encoding/opaque_path_success_special_not_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/opaque_path_success_unicode.phpt
A ext/uri/tests/whatwg/percent_encoding/password_success_control.phpt
A ext/uri/tests/whatwg/percent_encoding/password_success_percent.phpt
A ext/uri/tests/whatwg/percent_encoding/password_success_special_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/password_success_special_not_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/password_success_unicode.phpt
A ext/uri/tests/whatwg/percent_encoding/path_segment_success_control.phpt
A ext/uri/tests/whatwg/percent_encoding/path_segment_success_percent.phpt
A ext/uri/tests/whatwg/percent_encoding/path_segment_success_special_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/path_segment_success_special_not_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/path_segment_success_unicode.phpt
A ext/uri/tests/whatwg/percent_encoding/path_success_control.phpt
A ext/uri/tests/whatwg/percent_encoding/path_success_percent.phpt
A ext/uri/tests/whatwg/percent_encoding/path_success_special_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/path_success_special_not_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/path_success_unicode.phpt
A ext/uri/tests/whatwg/percent_encoding/query_success_control.phpt
A ext/uri/tests/whatwg/percent_encoding/query_success_percent.phpt
A ext/uri/tests/whatwg/percent_encoding/query_success_space.phpt
A ext/uri/tests/whatwg/percent_encoding/query_success_special_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/query_success_special_not_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/query_success_unicode.phpt
A ext/uri/tests/whatwg/percent_encoding/special_query_success_control.phpt
A ext/uri/tests/whatwg/percent_encoding/special_query_success_percent.phpt
A ext/uri/tests/whatwg/percent_encoding/special_query_success_space.phpt
A ext/uri/tests/whatwg/percent_encoding/special_query_success_special_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/special_query_success_special_not_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/special_query_success_unicode.phpt
A ext/uri/tests/whatwg/percent_encoding/username_success_control.phpt
A ext/uri/tests/whatwg/percent_encoding/username_success_percent.phpt
A ext/uri/tests/whatwg/percent_encoding/username_success_special_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/username_success_special_not_in_set.phpt
A ext/uri/tests/whatwg/percent_encoding/username_success_unicode.phpt
M UPGRADING
M ext/uri/php_uri.c
M ext/uri/php_uri.stub.php
M ext/uri/php_uri_arginfo.h
M ext/uri/php_uri_common.h
M ext/uri/php_uri_decl.h
M ext/uri/uri_parser_whatwg.c
M ext/uri/uri_parser_whatwg.h
Diff:
diff --git a/UPGRADING b/UPGRADING
index 74ecf90408aa..148cad212238 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -484,10 +484,10 @@ PHP 8.6 UPGRADE NOTES
RFC: https://wiki.php.net/rfc/uri_followup#uri_type_detection
. Added Uri\Rfc3986\Uri::getHostType() and Uri\WhatWg\Url::getHostType().
RFC: https://wiki.php.net/rfc/uri_followup#host_type_detection
- . Added Uri\Rfc3986\UriBuilder.
- RFC: https://wiki.php.net/rfc/uri_followup#uri_building
- . Added Uri\WhatWg\UrlBuilder.
+ . Added Uri\Rfc3986\UriBuilder and Uri\WhatWg\UrlBuilder.
RFC: https://wiki.php.net/rfc/uri_followup#uri_building
+ . Added Uri\url_percent_encode().
+ RFC: https://wiki.php.net/rfc/uri_followup#percent-encoding_support
========================================
3. Changes in SAPI modules
diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c
index 4caeca9f1465..bb1d8c8bb13c 100644
--- a/ext/uri/php_uri.c
+++ b/ext/uri/php_uri.c
@@ -36,6 +36,7 @@ zend_class_entry *php_uri_ce_rfc3986_uri_type;
zend_class_entry *php_uri_ce_rfc3986_uri_host_type;
zend_class_entry *php_uri_ce_whatwg_url_builder;
zend_class_entry *php_uri_ce_whatwg_url;
+zend_class_entry *php_uri_ce_whatwg_url_percent_encoding_mode;
zend_class_entry *php_uri_ce_comparison_mode;
zend_class_entry *php_uri_ce_exception;
zend_class_entry *php_uri_ce_error;
@@ -1073,6 +1074,60 @@ PHP_METHOD(Uri_WhatWg_Url, __debugInfo)
RETURN_ARR(uri_get_debug_properties(uri_object));
}
+PHP_FUNCTION(Uri_WhatWg_url_percent_encode)
+{
+ zend_string *input;
+ zend_enum_Uri_WhatWg_UrlPercentEncodingMode mode;
+
+ ZEND_PARSE_PARAMETERS_START(2, 2)
+ Z_PARAM_STR(input)
+ Z_PARAM_ENUM(mode, php_uri_ce_whatwg_url_percent_encoding_mode)
+ ZEND_PARSE_PARAMETERS_END();
+
+ zend_string *str;
+
+ switch (mode) {
+ case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Username:
+ ZEND_FALLTHROUGH;
+ case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Password:
+ str = php_uri_parser_whatwg_percent_encode_userinfo_component(ZSTR_VAL(input), ZSTR_LEN(input));
+ break;
+ case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_OpaqueHost:
+ str = php_uri_parser_whatwg_percent_encode_opaque_host_component(ZSTR_VAL(input), ZSTR_LEN(input));
+ break;
+ case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Path:
+ str = php_uri_parser_whatwg_percent_encode_path_component(ZSTR_VAL(input), ZSTR_LEN(input));
+ break;
+ case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_OpaquePath:
+ str = php_uri_parser_whatwg_percent_encode_opaque_path_component(ZSTR_VAL(input), ZSTR_LEN(input));
+ break;
+ case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_PathSegment:
+ str = php_uri_parser_whatwg_percent_encode_path_segment_component(ZSTR_VAL(input), ZSTR_LEN(input));
+ break;
+ case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Query:
+ str = php_uri_parser_whatwg_percent_encode_query_component(ZSTR_VAL(input), ZSTR_LEN(input));
+ break;
+ case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_SpecialQuery:
+ str = php_uri_parser_whatwg_percent_encode_special_query_component(ZSTR_VAL(input), ZSTR_LEN(input));
+ break;
+ case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_FormQuery:
+ str = php_uri_parser_whatwg_percent_encode_form_query_component(ZSTR_VAL(input), ZSTR_LEN(input));
+ break;
+ case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Fragment:
+ str = php_uri_parser_whatwg_percent_encode_fragment_component(ZSTR_VAL(input), ZSTR_LEN(input));
+ break;
+ default: ZEND_UNREACHABLE();
+ }
+
+ /* This should be unreachable in practice, as str is null only due to memory errors. */
+ if (str == NULL) {
+ zend_throw_exception(php_uri_ce_error, "Cannot percent-encode input", 0);
+ RETURN_THROWS();
+ }
+
+ RETURN_NEW_STR(str);
+}
+
PHP_METHOD(Uri_Rfc3986_UriBuilder, reset)
{
ZEND_PARSE_PARAMETERS_NONE();
@@ -1481,6 +1536,8 @@ static PHP_MINIT_FUNCTION(uri)
object_handlers_whatwg_uri.free_obj = php_uri_object_handler_free;
object_handlers_whatwg_uri.clone_obj = php_uri_object_handler_clone;
+ php_uri_ce_whatwg_url_percent_encoding_mode = register_class_Uri_WhatWg_UrlPercentEncodingMode();
+
php_uri_ce_comparison_mode = register_class_Uri_UriComparisonMode();
php_uri_ce_exception = register_class_Uri_UriException(zend_ce_exception);
php_uri_ce_error = register_class_Uri_UriError(zend_ce_error);
@@ -1548,14 +1605,14 @@ ZEND_MODULE_POST_ZEND_DEACTIVATE_D(uri)
zend_module_entry uri_module_entry = {
STANDARD_MODULE_HEADER_EX, NULL,
uri_deps,
- "uri", /* Extension name */
- NULL, /* zend_function_entry */
+ "uri", /* Extension name */
+ ext_functions, /* zend_function_entry */
PHP_MINIT(uri), /* PHP_MINIT - Module initialization */
- PHP_MSHUTDOWN(uri), /* PHP_MSHUTDOWN - Module shutdown */
+ PHP_MSHUTDOWN(uri), /* PHP_MSHUTDOWN - Module shutdown */
PHP_RINIT(uri), /* PHP_RINIT - Request initialization */
- NULL, /* PHP_RSHUTDOWN - Request shutdown */
- PHP_MINFO(uri), /* PHP_MINFO - Module info */
- PHP_VERSION, /* Version */
+ NULL, /* PHP_RSHUTDOWN - Request shutdown */
+ PHP_MINFO(uri), /* PHP_MINFO - Module info */
+ PHP_VERSION, /* Version */
NO_MODULE_GLOBALS,
ZEND_MODULE_POST_ZEND_DEACTIVATE_N(uri),
STANDARD_MODULE_PROPERTIES_EX
diff --git a/ext/uri/php_uri.stub.php b/ext/uri/php_uri.stub.php
index 98f8873d9845..ad1d2fe32dee 100644
--- a/ext/uri/php_uri.stub.php
+++ b/ext/uri/php_uri.stub.php
@@ -317,4 +317,20 @@ public function __unserialize(array $data): void {}
public function __debugInfo(): array {}
}
+
+ enum UrlPercentEncodingMode
+ {
+ case Username;
+ case Password;
+ case OpaqueHost;
+ case Path;
+ case OpaquePath;
+ case PathSegment;
+ case Query;
+ case SpecialQuery;
+ case FormQuery;
+ case Fragment;
+ }
+
+ function url_percent_encode(string $input, \Uri\WhatWg\UrlPercentEncodingMode $mode): string {}
}
diff --git a/ext/uri/php_uri_arginfo.h b/ext/uri/php_uri_arginfo.h
index 93cc3ee45a2b..c77d0485d052 100644
--- a/ext/uri/php_uri_arginfo.h
+++ b/ext/uri/php_uri_arginfo.h
@@ -1,7 +1,12 @@
/* This is a generated file, edit php_uri.stub.php instead.
- * Stub hash: 54e953b1da0d08c64509666b9278c59483d1e171
+ * Stub hash: 9e087e3aefdab5662892e7fad9de87857aa63057
* Has decl header: yes */
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_Uri_WhatWg_url_percent_encode, 0, 2, IS_STRING, 0)
+ ZEND_ARG_TYPE_INFO(0, input, IS_STRING, 0)
+ ZEND_ARG_OBJ_INFO(0, mode, Uri\\WhatWg\\\125rlPercentEncodingMode, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_UriBuilder_reset, 0, 0, IS_STATIC, 0)
ZEND_END_ARG_INFO()
@@ -242,6 +247,7 @@ ZEND_END_ARG_INFO()
#define arginfo_class_Uri_WhatWg_Url___debugInfo arginfo_class_Uri_Rfc3986_Uri___serialize
+ZEND_FUNCTION(Uri_WhatWg_url_percent_encode);
ZEND_METHOD(Uri_Rfc3986_UriBuilder, reset);
ZEND_METHOD(Uri_Rfc3986_UriBuilder, setScheme);
ZEND_METHOD(Uri_Rfc3986_UriBuilder, setUserInfo);
@@ -316,6 +322,11 @@ ZEND_METHOD(Uri_WhatWg_Url, __serialize);
ZEND_METHOD(Uri_WhatWg_Url, __unserialize);
ZEND_METHOD(Uri_WhatWg_Url, __debugInfo);
+static const zend_function_entry ext_functions[] = {
+ ZEND_RAW_FENTRY(ZEND_NS_NAME("Uri\\WhatWg", "url_percent_encode"), zif_Uri_WhatWg_url_percent_encode, arginfo_Uri_WhatWg_url_percent_encode, 0, NULL, NULL)
+ ZEND_FE_END
+};
+
static const zend_function_entry class_Uri_Rfc3986_UriBuilder_methods[] = {
ZEND_ME(Uri_Rfc3986_UriBuilder, reset, arginfo_class_Uri_Rfc3986_UriBuilder_reset, ZEND_ACC_PUBLIC)
ZEND_ME(Uri_Rfc3986_UriBuilder, setScheme, arginfo_class_Uri_Rfc3986_UriBuilder_setScheme, ZEND_ACC_PUBLIC)
@@ -733,3 +744,30 @@ static zend_class_entry *register_class_Uri_WhatWg_Url(void)
return class_entry;
}
+
+static zend_class_entry *register_class_Uri_WhatWg_UrlPercentEncodingMode(void)
+{
+ zend_class_entry *class_entry = zend_register_internal_enum("Uri\\WhatWg\\UrlPercentEncodingMode", IS_UNDEF, NULL);
+
+ zend_enum_add_case_cstr(class_entry, "Username", NULL);
+
+ zend_enum_add_case_cstr(class_entry, "Password", NULL);
+
+ zend_enum_add_case_cstr(class_entry, "OpaqueHost", NULL);
+
+ zend_enum_add_case_cstr(class_entry, "Path", NULL);
+
+ zend_enum_add_case_cstr(class_entry, "OpaquePath", NULL);
+
+ zend_enum_add_case_cstr(class_entry, "PathSegment", NULL);
+
+ zend_enum_add_case_cstr(class_entry, "Query", NULL);
+
+ zend_enum_add_case_cstr(class_entry, "SpecialQuery", NULL);
+
+ zend_enum_add_case_cstr(class_entry, "FormQuery", NULL);
+
+ zend_enum_add_case_cstr(class_entry, "Fragment", NULL);
+
+ return class_entry;
+}
diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h
index 31ef1dd2130c..a1d9d852f3b7 100644
--- a/ext/uri/php_uri_common.h
+++ b/ext/uri/php_uri_common.h
@@ -23,6 +23,7 @@ extern zend_class_entry *php_uri_ce_rfc3986_uri_type;
extern zend_class_entry *php_uri_ce_rfc3986_uri_host_type;
extern zend_class_entry *php_uri_ce_whatwg_url_builder;
extern zend_class_entry *php_uri_ce_whatwg_url;
+extern zend_class_entry *php_uri_ce_whatwg_url_percent_encoding_mode;
extern zend_class_entry *php_uri_ce_comparison_mode;
extern zend_class_entry *php_uri_ce_exception;
extern zend_class_entry *php_uri_ce_error;
diff --git a/ext/uri/php_uri_decl.h b/ext/uri/php_uri_decl.h
index 71f748b71070..a55b44a95205 100644
--- a/ext/uri/php_uri_decl.h
+++ b/ext/uri/php_uri_decl.h
@@ -1,8 +1,8 @@
/* This is a generated file, edit php_uri.stub.php instead.
- * Stub hash: 54e953b1da0d08c64509666b9278c59483d1e171 */
+ * Stub hash: 9e087e3aefdab5662892e7fad9de87857aa63057 */
-#ifndef ZEND_PHP_URI_DECL_54e953b1da0d08c64509666b9278c59483d1e171_H
-#define ZEND_PHP_URI_DECL_54e953b1da0d08c64509666b9278c59483d1e171_H
+#ifndef ZEND_PHP_URI_DECL_9e087e3aefdab5662892e7fad9de87857aa63057_H
+#define ZEND_PHP_URI_DECL_9e087e3aefdab5662892e7fad9de87857aa63057_H
typedef enum zend_enum_Uri_UriComparisonMode {
ZEND_ENUM_Uri_UriComparisonMode_IncludeFragment = 1,
@@ -63,4 +63,17 @@ typedef enum zend_enum_Uri_WhatWg_UrlHostType {
ZEND_ENUM_Uri_WhatWg_UrlHostType_Empty = 5,
} zend_enum_Uri_WhatWg_UrlHostType;
-#endif /* ZEND_PHP_URI_DECL_54e953b1da0d08c64509666b9278c59483d1e171_H */
+typedef enum zend_enum_Uri_WhatWg_UrlPercentEncodingMode {
+ ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Username = 1,
+ ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Password = 2,
+ ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_OpaqueHost = 3,
+ ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Path = 4,
+ ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_OpaquePath = 5,
+ ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_PathSegment = 6,
+ ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Query = 7,
+ ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_SpecialQuery = 8,
+ ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_FormQuery = 9,
+ ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Fragment = 10,
+} zend_enum_Uri_WhatWg_UrlPercentEncodingMode;
+
+#endif /* ZEND_PHP_URI_DECL_9e087e3aefdab5662892e7fad9de87857aa63057_H */
diff --git a/ext/uri/tests/whatwg/percent_encoding/form_query_success_control.phpt b/ext/uri/tests/whatwg/percent_encoding/form_query_success_control.phpt
new file mode 100644
index 000000000000..a5dd0ce69038
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/form_query_success_control.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - form query - control code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("\x11", Uri\WhatWg\UrlPercentEncodingMode::FormQuery));
+
+?>
+--EXPECT--
+string(3) "%11"
diff --git a/ext/uri/tests/whatwg/percent_encoding/form_query_success_percent.phpt b/ext/uri/tests/whatwg/percent_encoding/form_query_success_percent.phpt
new file mode 100644
index 000000000000..238f1b0b01f7
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/form_query_success_percent.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - form query - percent sign code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG%20url", Uri\WhatWg\UrlPercentEncodingMode::FormQuery));
+
+?>
+--EXPECT--
+string(14) "WHATWG%2520url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/form_query_success_space.phpt b/ext/uri/tests/whatwg/percent_encoding/form_query_success_space.phpt
new file mode 100644
index 000000000000..50d649454213
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/form_query_success_space.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - form query - space code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG url", Uri\WhatWg\UrlPercentEncodingMode::FormQuery));
+
+?>
+--EXPECT--
+string(10) "WHATWG+url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/form_query_success_special_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/form_query_success_special_in_set.phpt
new file mode 100644
index 000000000000..82f622575917
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/form_query_success_special_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - form query - special code points in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode('"#<>&+,', Uri\WhatWg\UrlPercentEncodingMode::FormQuery));
+
+?>
+--EXPECT--
+string(21) "%22%23%3C%3E%26%2B%2C"
diff --git a/ext/uri/tests/whatwg/percent_encoding/form_query_success_special_not_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/form_query_success_special_not_in_set.phpt
new file mode 100644
index 000000000000..590f6dd31023
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/form_query_success_special_not_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - form query - special code points not in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("*-._", Uri\WhatWg\UrlPercentEncodingMode::FormQuery));
+
+?>
+--EXPECT--
+string(4) "*-._"
diff --git a/ext/uri/tests/whatwg/percent_encoding/form_query_success_unicode.phpt b/ext/uri/tests/whatwg/percent_encoding/form_query_success_unicode.phpt
new file mode 100644
index 000000000000..bcb843ca67a6
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/form_query_success_unicode.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - form query - Unicode code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("föő", Uri\WhatWg\UrlPercentEncodingMode::FormQuery));
+
+?>
+--EXPECT--
+string(13) "f%C3%B6%C5%91"
diff --git a/ext/uri/tests/whatwg/percent_encoding/fragment_success_control.phpt b/ext/uri/tests/whatwg/percent_encoding/fragment_success_control.phpt
new file mode 100644
index 000000000000..c0992a9e260f
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/fragment_success_control.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - fragment - control code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("\x11", Uri\WhatWg\UrlPercentEncodingMode::Fragment));
+
+?>
+--EXPECT--
+string(3) "%11"
diff --git a/ext/uri/tests/whatwg/percent_encoding/fragment_success_percent.phpt b/ext/uri/tests/whatwg/percent_encoding/fragment_success_percent.phpt
new file mode 100644
index 000000000000..12b2bada8fae
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/fragment_success_percent.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - fragment - percent sign code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG%20url", Uri\WhatWg\UrlPercentEncodingMode::Username));
+
+?>
+--EXPECT--
+string(14) "WHATWG%2520url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/fragment_success_special_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/fragment_success_special_in_set.phpt
new file mode 100644
index 000000000000..fe129d66895f
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/fragment_success_special_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - fragment - special code points in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode(' "<>`', Uri\WhatWg\UrlPercentEncodingMode::Fragment));
+
+?>
+--EXPECT--
+string(15) "%20%22%3C%3E%60"
diff --git a/ext/uri/tests/whatwg/percent_encoding/fragment_success_special_not_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/fragment_success_special_not_in_set.phpt
new file mode 100644
index 000000000000..255c5173ef83
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/fragment_success_special_not_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - fragment - special code points not in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("('$+)", Uri\WhatWg\UrlPercentEncodingMode::Fragment));
+
+?>
+--EXPECT--
+string(5) "('$+)"
diff --git a/ext/uri/tests/whatwg/percent_encoding/fragment_success_unicode.phpt b/ext/uri/tests/whatwg/percent_encoding/fragment_success_unicode.phpt
new file mode 100644
index 000000000000..0a14a113f386
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/fragment_success_unicode.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - fragment - Unicode code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("föő", Uri\WhatWg\UrlPercentEncodingMode::Fragment));
+
+?>
+--EXPECT--
+string(13) "f%C3%B6%C5%91"
diff --git a/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_control.phpt b/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_control.phpt
new file mode 100644
index 000000000000..7adc5b963787
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_control.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - opaque host - control code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("\x11", Uri\WhatWg\UrlPercentEncodingMode::OpaqueHost));
+
+?>
+--EXPECT--
+string(3) "%11"
diff --git a/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_percent.phpt b/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_percent.phpt
new file mode 100644
index 000000000000..f6c6d12e4c7b
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_percent.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - opaque host - percent sign code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG%20url", Uri\WhatWg\UrlPercentEncodingMode::OpaqueHost));
+
+?>
+--EXPECT--
+string(14) "WHATWG%2520url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_special_not_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_special_not_in_set.phpt
new file mode 100644
index 000000000000..a170079625f9
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_special_not_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - opaque host - special code points not in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode(" \"#<>?^`{}@'$+,", Uri\WhatWg\UrlPercentEncodingMode::OpaqueHost));
+
+?>
+--EXPECT--
+string(15) " "#<>?^`{}@'$+,"
diff --git a/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_unicode.phpt b/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_unicode.phpt
new file mode 100644
index 000000000000..b51ad97b54dc
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/opaque_host_success_unicode.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - opaque host - Unicode code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("föő", Uri\WhatWg\UrlPercentEncodingMode::OpaquePath));
+
+?>
+--EXPECT--
+string(13) "f%C3%B6%C5%91"
diff --git a/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_control.phpt b/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_control.phpt
new file mode 100644
index 000000000000..adf1bee19b6c
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_control.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - opaque path - control code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("\x11", Uri\WhatWg\UrlPercentEncodingMode::OpaquePath));
+
+?>
+--EXPECT--
+string(3) "%11"
diff --git a/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_percent.phpt b/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_percent.phpt
new file mode 100644
index 000000000000..7fa6a7c3973f
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_percent.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - opaque path - percent sign code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG%20url", Uri\WhatWg\UrlPercentEncodingMode::OpaquePath));
+
+?>
+--EXPECT--
+string(14) "WHATWG%2520url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_special_not_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_special_not_in_set.phpt
new file mode 100644
index 000000000000..fa9075856a5c
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_special_not_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - opaque path - special code points not in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode(" \"#<>?^`{}@'$+,", Uri\WhatWg\UrlPercentEncodingMode::OpaquePath));
+
+?>
+--EXPECT--
+string(15) " "#<>?^`{}@'$+,"
diff --git a/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_unicode.phpt b/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_unicode.phpt
new file mode 100644
index 000000000000..3fbae7c2c156
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/opaque_path_success_unicode.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - opaque path - Unicode code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("föő", Uri\WhatWg\UrlPercentEncodingMode::OpaquePath));
+
+?>
+--EXPECT--
+string(13) "f%C3%B6%C5%91"
diff --git a/ext/uri/tests/whatwg/percent_encoding/password_success_control.phpt b/ext/uri/tests/whatwg/percent_encoding/password_success_control.phpt
new file mode 100644
index 000000000000..57ff019878df
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/password_success_control.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - password - control code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("\x11", Uri\WhatWg\UrlPercentEncodingMode::Password));
+
+?>
+--EXPECT--
+string(3) "%11"
diff --git a/ext/uri/tests/whatwg/percent_encoding/password_success_percent.phpt b/ext/uri/tests/whatwg/percent_encoding/password_success_percent.phpt
new file mode 100644
index 000000000000..536a2702a428
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/password_success_percent.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - password - percent sign code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG%20url", Uri\WhatWg\UrlPercentEncodingMode::Password));
+
+?>
+--EXPECT--
+string(14) "WHATWG%2520url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/password_success_special_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/password_success_special_in_set.phpt
new file mode 100644
index 000000000000..f4041e059e88
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/password_success_special_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - password - special code points in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("[#=? `]", Uri\WhatWg\UrlPercentEncodingMode::Password));
+
+?>
+--EXPECT--
+string(21) "%5B%23%3D%3F%20%60%5D"
diff --git a/ext/uri/tests/whatwg/percent_encoding/password_success_special_not_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/password_success_special_not_in_set.phpt
new file mode 100644
index 000000000000..a4a151c44487
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/password_success_special_not_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - password - special code points not in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("('$+)", Uri\WhatWg\UrlPercentEncodingMode::Password));
+
+?>
+--EXPECT--
+string(5) "('$+)"
diff --git a/ext/uri/tests/whatwg/percent_encoding/password_success_unicode.phpt b/ext/uri/tests/whatwg/percent_encoding/password_success_unicode.phpt
new file mode 100644
index 000000000000..d2d0247f98f3
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/password_success_unicode.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - password - Unicode code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("föő", Uri\WhatWg\UrlPercentEncodingMode::Password));
+
+?>
+--EXPECT--
+string(13) "f%C3%B6%C5%91"
diff --git a/ext/uri/tests/whatwg/percent_encoding/path_segment_success_control.phpt b/ext/uri/tests/whatwg/percent_encoding/path_segment_success_control.phpt
new file mode 100644
index 000000000000..0c9bfcbb0b1e
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/path_segment_success_control.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - path segment - control code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("\x11", Uri\WhatWg\UrlPercentEncodingMode::PathSegment));
+
+?>
+--EXPECT--
+string(3) "%11"
diff --git a/ext/uri/tests/whatwg/percent_encoding/path_segment_success_percent.phpt b/ext/uri/tests/whatwg/percent_encoding/path_segment_success_percent.phpt
new file mode 100644
index 000000000000..258cca36a2ee
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/path_segment_success_percent.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - path segment - percent sign code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG%20url", Uri\WhatWg\UrlPercentEncodingMode::PathSegment));
+
+?>
+--EXPECT--
+string(14) "WHATWG%2520url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/path_segment_success_special_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/path_segment_success_special_in_set.phpt
new file mode 100644
index 000000000000..03f43a8a0405
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/path_segment_success_special_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - path segment - special code points in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode(' "#<>?^`{}/', Uri\WhatWg\UrlPercentEncodingMode::PathSegment));
+
+?>
+--EXPECT--
+string(33) "%20%22%23%3C%3E%3F%5E%60%7B%7D%2F"
diff --git a/ext/uri/tests/whatwg/percent_encoding/path_segment_success_special_not_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/path_segment_success_special_not_in_set.phpt
new file mode 100644
index 000000000000..50790f66eb6c
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/path_segment_success_special_not_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - path segment - special code points not in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("@'$+,", Uri\WhatWg\UrlPercentEncodingMode::PathSegment));
+
+?>
+--EXPECT--
+string(5) "@'$+,"
diff --git a/ext/uri/tests/whatwg/percent_encoding/path_segment_success_unicode.phpt b/ext/uri/tests/whatwg/percent_encoding/path_segment_success_unicode.phpt
new file mode 100644
index 000000000000..218d120ae9ea
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/path_segment_success_unicode.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - path segment - Unicode code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("föő", Uri\WhatWg\UrlPercentEncodingMode::PathSegment));
+
+?>
+--EXPECT--
+string(13) "f%C3%B6%C5%91"
diff --git a/ext/uri/tests/whatwg/percent_encoding/path_success_control.phpt b/ext/uri/tests/whatwg/percent_encoding/path_success_control.phpt
new file mode 100644
index 000000000000..fa56acc3a3c5
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/path_success_control.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - path - control code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("\x11", Uri\WhatWg\UrlPercentEncodingMode::Path));
+
+?>
+--EXPECT--
+string(3) "%11"
diff --git a/ext/uri/tests/whatwg/percent_encoding/path_success_percent.phpt b/ext/uri/tests/whatwg/percent_encoding/path_success_percent.phpt
new file mode 100644
index 000000000000..013c9e770740
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/path_success_percent.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - path - percent sign code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG%20url", Uri\WhatWg\UrlPercentEncodingMode::Path));
+
+?>
+--EXPECT--
+string(14) "WHATWG%2520url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/path_success_special_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/path_success_special_in_set.phpt
new file mode 100644
index 000000000000..785c82902620
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/path_success_special_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - path - special code points in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode(' "#<>?^`{}', Uri\WhatWg\UrlPercentEncodingMode::Path));
+
+?>
+--EXPECT--
+string(30) "%20%22%23%3C%3E%3F%5E%60%7B%7D"
diff --git a/ext/uri/tests/whatwg/percent_encoding/path_success_special_not_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/path_success_special_not_in_set.phpt
new file mode 100644
index 000000000000..17f6bf915407
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/path_success_special_not_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - path - special code points not in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("@'$+,", Uri\WhatWg\UrlPercentEncodingMode::Path));
+
+?>
+--EXPECT--
+string(5) "@'$+,"
diff --git a/ext/uri/tests/whatwg/percent_encoding/path_success_unicode.phpt b/ext/uri/tests/whatwg/percent_encoding/path_success_unicode.phpt
new file mode 100644
index 000000000000..edfa72359251
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/path_success_unicode.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - path - Unicode code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("föő", Uri\WhatWg\UrlPercentEncodingMode::Path));
+
+?>
+--EXPECT--
+string(13) "f%C3%B6%C5%91"
diff --git a/ext/uri/tests/whatwg/percent_encoding/query_success_control.phpt b/ext/uri/tests/whatwg/percent_encoding/query_success_control.phpt
new file mode 100644
index 000000000000..2502cc7a662c
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/query_success_control.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - query - control code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("\x11", Uri\WhatWg\UrlPercentEncodingMode::Query));
+
+?>
+--EXPECT--
+string(3) "%11"
diff --git a/ext/uri/tests/whatwg/percent_encoding/query_success_percent.phpt b/ext/uri/tests/whatwg/percent_encoding/query_success_percent.phpt
new file mode 100644
index 000000000000..e9a4187b963d
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/query_success_percent.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - query - percent sign code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG%20url", Uri\WhatWg\UrlPercentEncodingMode::Query));
+
+?>
+--EXPECT--
+string(14) "WHATWG%2520url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/query_success_space.phpt b/ext/uri/tests/whatwg/percent_encoding/query_success_space.phpt
new file mode 100644
index 000000000000..b9a491018580
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/query_success_space.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - query - space code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG url", Uri\WhatWg\UrlPercentEncodingMode::Query));
+
+?>
+--EXPECT--
+string(12) "WHATWG%20url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/query_success_special_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/query_success_special_in_set.phpt
new file mode 100644
index 000000000000..a5fab6b7cd08
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/query_success_special_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - query - special code points in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode(' "#<>', Uri\WhatWg\UrlPercentEncodingMode::Query));
+
+?>
+--EXPECT--
+string(15) "%20%22%23%3C%3E"
diff --git a/ext/uri/tests/whatwg/percent_encoding/query_success_special_not_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/query_success_special_not_in_set.phpt
new file mode 100644
index 000000000000..c8e4123d93ff
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/query_success_special_not_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - query - special code points not in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("[@?&]'", Uri\WhatWg\UrlPercentEncodingMode::Query));
+
+?>
+--EXPECT--
+string(6) "[@?&]'"
diff --git a/ext/uri/tests/whatwg/percent_encoding/query_success_unicode.phpt b/ext/uri/tests/whatwg/percent_encoding/query_success_unicode.phpt
new file mode 100644
index 000000000000..f5b3988f08fe
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/query_success_unicode.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - query - Unicode code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("föő", Uri\WhatWg\UrlPercentEncodingMode::Query));
+
+?>
+--EXPECT--
+string(13) "f%C3%B6%C5%91"
diff --git a/ext/uri/tests/whatwg/percent_encoding/special_query_success_control.phpt b/ext/uri/tests/whatwg/percent_encoding/special_query_success_control.phpt
new file mode 100644
index 000000000000..f6d76153043f
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/special_query_success_control.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - special query - control code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("\x11", Uri\WhatWg\UrlPercentEncodingMode::SpecialQuery));
+
+?>
+--EXPECT--
+string(3) "%11"
diff --git a/ext/uri/tests/whatwg/percent_encoding/special_query_success_percent.phpt b/ext/uri/tests/whatwg/percent_encoding/special_query_success_percent.phpt
new file mode 100644
index 000000000000..a1683a1ef77b
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/special_query_success_percent.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - special query - percent sign code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG%20url", Uri\WhatWg\UrlPercentEncodingMode::SpecialQuery));
+
+?>
+--EXPECT--
+string(14) "WHATWG%2520url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/special_query_success_space.phpt b/ext/uri/tests/whatwg/percent_encoding/special_query_success_space.phpt
new file mode 100644
index 000000000000..049a5da1d4ed
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/special_query_success_space.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - special query - space code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG url", Uri\WhatWg\UrlPercentEncodingMode::SpecialQuery));
+
+?>
+--EXPECT--
+string(12) "WHATWG%20url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/special_query_success_special_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/special_query_success_special_in_set.phpt
new file mode 100644
index 000000000000..e84df8465c9f
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/special_query_success_special_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - special query - special code points in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode(" '\"#<>", Uri\WhatWg\UrlPercentEncodingMode::SpecialQuery));
+
+?>
+--EXPECT--
+string(18) "%20%27%22%23%3C%3E"
diff --git a/ext/uri/tests/whatwg/percent_encoding/special_query_success_special_not_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/special_query_success_special_not_in_set.phpt
new file mode 100644
index 000000000000..0ee677b31fe1
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/special_query_success_special_not_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - special query - special code points not in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("[@?&]", Uri\WhatWg\UrlPercentEncodingMode::SpecialQuery));
+
+?>
+--EXPECT--
+string(5) "[@?&]"
diff --git a/ext/uri/tests/whatwg/percent_encoding/special_query_success_unicode.phpt b/ext/uri/tests/whatwg/percent_encoding/special_query_success_unicode.phpt
new file mode 100644
index 000000000000..b583d8de2ecc
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/special_query_success_unicode.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - special query - Unicode code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("föő", Uri\WhatWg\UrlPercentEncodingMode::SpecialQuery));
+
+?>
+--EXPECT--
+string(13) "f%C3%B6%C5%91"
diff --git a/ext/uri/tests/whatwg/percent_encoding/username_success_control.phpt b/ext/uri/tests/whatwg/percent_encoding/username_success_control.phpt
new file mode 100644
index 000000000000..5a64393065c9
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/username_success_control.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - username - control code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("\x11", Uri\WhatWg\UrlPercentEncodingMode::Username));
+
+?>
+--EXPECT--
+string(3) "%11"
diff --git a/ext/uri/tests/whatwg/percent_encoding/username_success_percent.phpt b/ext/uri/tests/whatwg/percent_encoding/username_success_percent.phpt
new file mode 100644
index 000000000000..9ea2831efa46
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/username_success_percent.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - username - percent sign code point
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("WHATWG%20url", Uri\WhatWg\UrlPercentEncodingMode::Username));
+
+?>
+--EXPECT--
+string(14) "WHATWG%2520url"
diff --git a/ext/uri/tests/whatwg/percent_encoding/username_success_special_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/username_success_special_in_set.phpt
new file mode 100644
index 000000000000..070250ef3630
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/username_success_special_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - username - special code points in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("[#=? `]", Uri\WhatWg\UrlPercentEncodingMode::Username));
+
+?>
+--EXPECT--
+string(21) "%5B%23%3D%3F%20%60%5D"
diff --git a/ext/uri/tests/whatwg/percent_encoding/username_success_special_not_in_set.phpt b/ext/uri/tests/whatwg/percent_encoding/username_success_special_not_in_set.phpt
new file mode 100644
index 000000000000..8626b96ab9b3
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/username_success_special_not_in_set.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - username - special code points not in the percent-encode set
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("('$+)", Uri\WhatWg\UrlPercentEncodingMode::Username));
+
+?>
+--EXPECT--
+string(5) "('$+)"
diff --git a/ext/uri/tests/whatwg/percent_encoding/username_success_unicode.phpt b/ext/uri/tests/whatwg/percent_encoding/username_success_unicode.phpt
new file mode 100644
index 000000000000..d85b0712c1f0
--- /dev/null
+++ b/ext/uri/tests/whatwg/percent_encoding/username_success_unicode.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test Uri\WhatWg\url_percent_encode() - username - Unicode code points
+--FILE--
+<?php
+
+var_dump(Uri\WhatWg\url_percent_encode("föő", Uri\WhatWg\UrlPercentEncodingMode::Username));
+
+?>
+--EXPECT--
+string(13) "f%C3%B6%C5%91"
diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c
index b7a74fc1e231..4f308ba224bd 100644
--- a/ext/uri/uri_parser_whatwg.c
+++ b/ext/uri/uri_parser_whatwg.c
@@ -25,6 +25,7 @@
ZEND_TLS lexbor_mraw_t lexbor_mraw = {0};
ZEND_TLS lxb_url_parser_t lexbor_parser = {0};
ZEND_TLS lxb_unicode_idna_t lexbor_idna = {0};
+ZEND_TLS uint8_t lexbor_custom_url_map[256] = {0};
static const size_t lexbor_mraw_byte_size = 8192;
@@ -549,9 +550,7 @@ static zend_result php_uri_parser_whatwg_fragment_write(void *uri, const zval *v
PHP_RINIT_FUNCTION(uri_parser_whatwg)
{
- lxb_status_t status;
-
- status = lexbor_mraw_init(&lexbor_mraw, lexbor_mraw_byte_size);
+ lxb_status_t status = lexbor_mraw_init(&lexbor_mraw, lexbor_mraw_byte_size);
if (status != LXB_STATUS_OK) {
goto fail;
}
@@ -566,6 +565,9 @@ PHP_RINIT_FUNCTION(uri_parser_whatwg)
goto fail;
}
+ memcpy(lexbor_custom_url_map, lxb_url_get_percent_encoding_map(), sizeof(lexbor_custom_url_map));
+ lexbor_custom_url_map['%'] = -1; /* % is percent-encoded */
+
return SUCCESS;
fail:
@@ -653,6 +655,79 @@ static zend_string *php_uri_parser_whatwg_to_string(void *uri, const php_uri_rec
return smart_str_extract(&uri_str);
}
+static zend_string *php_uri_parser_whatwg_percent_encode_component(const char *str, const size_t str_length, const lxb_url_map_type_t map, const bool space_as_plus)
+{
+ lexbor_str_t lexbor_str = {0};
+
+ const lexbor_status_t status = lxb_url_percent_encode_utf_8(
+ (lxb_char_t *) str, str_length, &lexbor_str, lexbor_parser.mraw, lexbor_custom_url_map, map, space_as_plus
+ );
+
+ if (status != LXB_STATUS_OK) {
+ lexbor_str_destroy(&lexbor_str, lexbor_parser.mraw, false);
+ return NULL;
+ }
+
+ zend_string *result = zend_string_init((const char *) lexbor_str.data, lexbor_str.length, false);
+
+ lexbor_str_destroy(&lexbor_str, lexbor_parser.mraw, false);
+
+ return result;
+}
+
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_userinfo_component(const char *str, const size_t str_length)
+{
+ return php_uri_parser_whatwg_percent_encode_component(str, str_length, LXB_URL_MAP_USERINFO, false);
+}
+
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_opaque_host_component(const char *str, const size_t str_length)
+{
+ return php_uri_parser_whatwg_percent_encode_component(str, str_length, LXB_URL_MAP_C0, false);
+}
+
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_path_component(const char *str, const size_t str_length)
+{
+ return php_uri_parser_whatwg_percent_encode_component(str, str_length, LXB_URL_MAP_PATH, false);
+}
+
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_opaque_path_component(const char *str, const size_t str_length)
+{
+ return php_uri_parser_whatwg_percent_encode_component(str, str_length, LXB_URL_MAP_C0, false);
+}
+
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_path_segment_component(const char *str, const size_t str_length)
+{
+ ZEND_ASSERT((lexbor_custom_url_map['/'] & LXB_URL_MAP_PATH) == 0);
+
+ lexbor_custom_url_map['/'] |= LXB_URL_MAP_PATH;
+
+ zend_string *result = php_uri_parser_whatwg_percent_encode_component(str, str_length, LXB_URL_MAP_PATH, false);
+
+ lexbor_custom_url_map['/'] &= ~LXB_URL_MAP_PATH;
+
+ return result;
+}
+
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_query_component(const char *str, const size_t str_length)
+{
+ return php_uri_parser_whatwg_percent_encode_component(str, str_length, LXB_URL_MAP_QUERY, false);
+}
+
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_special_query_component(const char *str, const size_t str_length)
+{
+ return php_uri_parser_whatwg_percent_encode_component(str, str_length, LXB_URL_MAP_SPECIAL_QUERY, false);
+}
+
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_form_query_component(const char *str, const size_t str_length)
+{
+ return php_uri_parser_whatwg_percent_encode_component(str, str_length, LXB_URL_MAP_X_WWW_FORM, true);
+}
+
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_fragment_component(const char *str, const size_t str_length)
+{
+ return php_uri_parser_whatwg_percent_encode_component(str, str_length, LXB_URL_MAP_FRAGMENT, false);
+}
+
static void php_uri_parser_whatwg_destroy(void *uri)
{
lxb_url_t *lexbor_uri = uri;
diff --git a/ext/uri/uri_parser_whatwg.h b/ext/uri/uri_parser_whatwg.h
index 0a03c8e76a93..ee387a6af95d 100644
--- a/ext/uri/uri_parser_whatwg.h
+++ b/ext/uri/uri_parser_whatwg.h
@@ -30,14 +30,24 @@ ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_whatwg_validate_scheme(const z
ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_whatwg_validate_host(const zend_string *host);
ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_whatwg_validate_port(zend_long port);
-PHP_RINIT_FUNCTION(uri_parser_whatwg);
-
ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_whatwg_build_from_zval(
lxb_url_t *lexbor_base_url, const zval *scheme, const zval *username, const zval *password,
const zval *host, const zval *port, const zval *path, const zval *query, const zval *fragment,
zval *errors_zv
);
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_userinfo_component(const char *str, size_t str_length);
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_opaque_host_component(const char *str, size_t str_length);
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_path_component(const char *str, size_t str_length);
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_opaque_path_component(const char *str, size_t str_length);
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_path_segment_component(const char *str, size_t str_length);
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_query_component(const char *str, size_t str_length);
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_special_query_component(const char *str, size_t str_length);
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_form_query_component(const char *str, size_t str_length);
+ZEND_ATTRIBUTE_NONNULL zend_string *php_uri_parser_whatwg_percent_encode_fragment_component(const char *str, size_t str_length);
+
+PHP_RINIT_FUNCTION(uri_parser_whatwg);
+
ZEND_MODULE_POST_ZEND_DEACTIVATE_D(uri_parser_whatwg);
#endif