diff --git a/NEWS b/NEWS index 2954fa75d389..1c7b4b8f5e8e 100644 --- a/NEWS +++ b/NEWS @@ -64,6 +64,7 @@ PHP NEWS . Avoid double conversion to string in php_userstreamop_readdir(). (nielsdos) - URI: + . Added support for Uri\Rfc3986\Uri::with*() methods. (kocsismate) . Fixed memory management of Uri\WhatWg\Url objects. (timwolla) . Fixed memory management of the internal "parse_url" URI parser. (timwolla) diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index 8b6aa5ef05ab..3aff91efc658 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -498,7 +498,12 @@ PHP_METHOD(Uri_Rfc3986_Uri, getRawScheme) uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_SCHEME, URI_COMPONENT_READ_RAW); } -static void read_uriparser_userinfo(INTERNAL_FUNCTION_PARAMETERS, uri_component_read_mode_t read_mode) +PHP_METHOD(Uri_Rfc3986_Uri, withScheme) +{ + uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_SCHEME); +} + +static void rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAMETERS, uri_component_read_mode_t read_mode) { ZEND_PARSE_PARAMETERS_NONE(); @@ -513,12 +518,48 @@ static void read_uriparser_userinfo(INTERNAL_FUNCTION_PARAMETERS, uri_component_ PHP_METHOD(Uri_Rfc3986_Uri, getUserInfo) { - read_uriparser_userinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_COMPONENT_READ_NORMALIZED_ASCII); + rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_COMPONENT_READ_NORMALIZED_ASCII); } PHP_METHOD(Uri_Rfc3986_Uri, getRawUserInfo) { - read_uriparser_userinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_COMPONENT_READ_RAW); + rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_COMPONENT_READ_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withUserInfo) +{ + zend_string *value; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH_STR_OR_NULL(value) + ZEND_PARSE_PARAMETERS_END(); + + zval zv; + if (value == NULL) { + ZVAL_NULL(&zv); + } else { + ZVAL_STR(&zv, value); + } + + zend_object *old_object = Z_OBJ_P(ZEND_THIS); + uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS); + URI_ASSERT_INITIALIZATION(internal_uri); + + zend_object *new_object = old_object->handlers->clone_obj(old_object); + if (new_object == NULL) { + RETURN_THROWS(); + } + + /* Assign the object early. The engine will take care of destruction in + * case of an exception being thrown. */ + RETVAL_OBJ(new_object); + + uri_internal_t *new_internal_uri = uri_internal_from_obj(new_object); + URI_ASSERT_INITIALIZATION(new_internal_uri); + + if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_write(new_internal_uri, &zv, NULL) == FAILURE)) { + RETURN_THROWS(); + } } PHP_METHOD(Uri_Rfc3986_Uri, getUsername) @@ -551,11 +592,21 @@ PHP_METHOD(Uri_Rfc3986_Uri, getRawHost) uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_HOST, URI_COMPONENT_READ_RAW); } +PHP_METHOD(Uri_Rfc3986_Uri, withHost) +{ + uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_HOST); +} + PHP_METHOD(Uri_Rfc3986_Uri, getPort) { uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PORT, URI_COMPONENT_READ_RAW); } +PHP_METHOD(Uri_Rfc3986_Uri, withPort) +{ + uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PORT); +} + PHP_METHOD(Uri_Rfc3986_Uri, getPath) { uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH, URI_COMPONENT_READ_NORMALIZED_ASCII); @@ -566,6 +617,11 @@ PHP_METHOD(Uri_Rfc3986_Uri, getRawPath) uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH, URI_COMPONENT_READ_RAW); } +PHP_METHOD(Uri_Rfc3986_Uri, withPath) +{ + uri_write_component_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH); +} + PHP_METHOD(Uri_Rfc3986_Uri, getQuery) { uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY, URI_COMPONENT_READ_NORMALIZED_ASCII); @@ -576,6 +632,11 @@ PHP_METHOD(Uri_Rfc3986_Uri, getRawQuery) uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY, URI_COMPONENT_READ_RAW); } +PHP_METHOD(Uri_Rfc3986_Uri, withQuery) +{ + uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY); +} + PHP_METHOD(Uri_Rfc3986_Uri, getFragment) { uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT, URI_COMPONENT_READ_NORMALIZED_ASCII); @@ -586,6 +647,11 @@ PHP_METHOD(Uri_Rfc3986_Uri, getRawFragment) uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT, URI_COMPONENT_READ_RAW); } +PHP_METHOD(Uri_Rfc3986_Uri, withFragment) +{ + uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT); +} + static void throw_cannot_recompose_uri_to_string(zend_object *object) { zend_throw_exception_ex(NULL, 0, "Cannot recompose %s to a string", ZSTR_VAL(object->ce->name)); @@ -831,29 +897,9 @@ PHP_METHOD(Uri_WhatWg_Url, getUnicodeHost) uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_HOST, URI_COMPONENT_READ_NORMALIZED_UNICODE); } -PHP_METHOD(Uri_WhatWg_Url, withHost) -{ - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_HOST); -} - -PHP_METHOD(Uri_WhatWg_Url, withPort) -{ - uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PORT); -} - -PHP_METHOD(Uri_WhatWg_Url, withPath) +PHP_METHOD(Uri_WhatWg_Url, getFragment) { - uri_write_component_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH); -} - -PHP_METHOD(Uri_WhatWg_Url, withQuery) -{ - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY); -} - -PHP_METHOD(Uri_WhatWg_Url, withFragment) -{ - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT); + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT, URI_COMPONENT_READ_NORMALIZED_UNICODE); } PHP_METHOD(Uri_WhatWg_Url, equals) diff --git a/ext/uri/php_uri.stub.php b/ext/uri/php_uri.stub.php index 9fbd40d98e5e..b4063bee8f59 100644 --- a/ext/uri/php_uri.stub.php +++ b/ext/uri/php_uri.stub.php @@ -32,10 +32,14 @@ public function getScheme(): ?string {} public function getRawScheme(): ?string {} + public function withScheme(?string $scheme): static {} + public function getUserInfo(): ?string {} public function getRawUserInfo(): ?string {} + public function withUserInfo(#[\SensitiveParameter] ?string $userinfo): static {} + public function getUsername(): ?string {} public function getRawUsername(): ?string {} @@ -48,20 +52,30 @@ public function getHost(): ?string {} public function getRawHost(): ?string {} + public function withHost(?string $host): static {} + public function getPort(): ?int {} + public function withPort(?int $port): static {} + public function getPath(): string {} public function getRawPath(): string {} + public function withPath(string $path): static {} + public function getQuery(): ?string {} public function getRawQuery(): ?string {} + public function withQuery(?string $query): static {} + public function getFragment(): ?string {} public function getRawFragment(): ?string {} + public function withFragment(?string $fragment): static {} + public function equals(\Uri\Rfc3986\Uri $uri, \Uri\UriComparisonMode $comparisonMode = \Uri\UriComparisonMode::ExcludeFragment): bool {} public function toString(): string {} @@ -157,26 +171,31 @@ public function getAsciiHost(): ?string {} public function getUnicodeHost(): ?string {} + /** @implementation-alias Uri\Rfc3986\Uri::withHost */ public function withHost(?string $host): static {} /** @implementation-alias Uri\Rfc3986\Uri::getPort */ public function getPort(): ?int {} + /** @implementation-alias Uri\Rfc3986\Uri::withPort */ public function withPort(?int $port): static {} /** @implementation-alias Uri\Rfc3986\Uri::getPath */ public function getPath(): string {} + /** @implementation-alias Uri\Rfc3986\Uri::withPath */ public function withPath(string $path): static {} /** @implementation-alias Uri\Rfc3986\Uri::getQuery */ public function getQuery(): ?string {} + /** @implementation-alias Uri\Rfc3986\Uri::withQuery */ public function withQuery(?string $query): static {} /** @implementation-alias Uri\Rfc3986\Uri::getFragment */ public function getFragment(): ?string {} + /** @implementation-alias Uri\Rfc3986\Uri::withFragment */ public function withFragment(?string $fragment): static {} public function equals(\Uri\WhatWg\Url $url, \Uri\UriComparisonMode $comparisonMode = \Uri\UriComparisonMode::ExcludeFragment): bool {} diff --git a/ext/uri/php_uri_arginfo.h b/ext/uri/php_uri_arginfo.h index 65630f113a3d..12a498357ea2 100644 --- a/ext/uri/php_uri_arginfo.h +++ b/ext/uri/php_uri_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: e2c448000b1e00485bc988f073ea61dfc984e953 */ + * Stub hash: bf37e0babfcc453ab0c75d0e87e142dfa3b5e61e */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_parse, 0, 1, IS_STATIC, 1) ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0) @@ -16,10 +16,18 @@ ZEND_END_ARG_INFO() #define arginfo_class_Uri_Rfc3986_Uri_getRawScheme arginfo_class_Uri_Rfc3986_Uri_getScheme +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withScheme, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, scheme, IS_STRING, 1) +ZEND_END_ARG_INFO() + #define arginfo_class_Uri_Rfc3986_Uri_getUserInfo arginfo_class_Uri_Rfc3986_Uri_getScheme #define arginfo_class_Uri_Rfc3986_Uri_getRawUserInfo arginfo_class_Uri_Rfc3986_Uri_getScheme +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withUserInfo, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, userinfo, IS_STRING, 1) +ZEND_END_ARG_INFO() + #define arginfo_class_Uri_Rfc3986_Uri_getUsername arginfo_class_Uri_Rfc3986_Uri_getScheme #define arginfo_class_Uri_Rfc3986_Uri_getRawUsername arginfo_class_Uri_Rfc3986_Uri_getScheme @@ -32,22 +40,42 @@ ZEND_END_ARG_INFO() #define arginfo_class_Uri_Rfc3986_Uri_getRawHost arginfo_class_Uri_Rfc3986_Uri_getScheme +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withHost, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 1) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_getPort, 0, 0, IS_LONG, 1) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withPort, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_getPath, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() #define arginfo_class_Uri_Rfc3986_Uri_getRawPath arginfo_class_Uri_Rfc3986_Uri_getPath +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withPath, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0) +ZEND_END_ARG_INFO() + #define arginfo_class_Uri_Rfc3986_Uri_getQuery arginfo_class_Uri_Rfc3986_Uri_getScheme #define arginfo_class_Uri_Rfc3986_Uri_getRawQuery arginfo_class_Uri_Rfc3986_Uri_getScheme +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withQuery, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, query, IS_STRING, 1) +ZEND_END_ARG_INFO() + #define arginfo_class_Uri_Rfc3986_Uri_getFragment arginfo_class_Uri_Rfc3986_Uri_getScheme #define arginfo_class_Uri_Rfc3986_Uri_getRawFragment arginfo_class_Uri_Rfc3986_Uri_getScheme +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withFragment, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, fragment, IS_STRING, 1) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_equals, 0, 1, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, uri, Uri\\Rfc3986\\\125ri, 0) ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, comparisonMode, Uri\\\125riComparisonMode, 0, "Uri\\UriComparisonMode::ExcludeFragment") @@ -117,33 +145,23 @@ ZEND_END_ARG_INFO() #define arginfo_class_Uri_WhatWg_Url_getUnicodeHost arginfo_class_Uri_Rfc3986_Uri_getScheme -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withHost, 0, 1, IS_STATIC, 0) - ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 1) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_withHost arginfo_class_Uri_Rfc3986_Uri_withHost #define arginfo_class_Uri_WhatWg_Url_getPort arginfo_class_Uri_Rfc3986_Uri_getPort -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withPort, 0, 1, IS_STATIC, 0) - ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_withPort arginfo_class_Uri_Rfc3986_Uri_withPort #define arginfo_class_Uri_WhatWg_Url_getPath arginfo_class_Uri_Rfc3986_Uri_getPath -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withPath, 0, 1, IS_STATIC, 0) - ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_withPath arginfo_class_Uri_Rfc3986_Uri_withPath #define arginfo_class_Uri_WhatWg_Url_getQuery arginfo_class_Uri_Rfc3986_Uri_getScheme -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withQuery, 0, 1, IS_STATIC, 0) - ZEND_ARG_TYPE_INFO(0, query, IS_STRING, 1) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_withQuery arginfo_class_Uri_Rfc3986_Uri_withQuery #define arginfo_class_Uri_WhatWg_Url_getFragment arginfo_class_Uri_Rfc3986_Uri_getScheme -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withFragment, 0, 1, IS_STATIC, 0) - ZEND_ARG_TYPE_INFO(0, fragment, IS_STRING, 1) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_withFragment arginfo_class_Uri_Rfc3986_Uri_withFragment ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_equals, 0, 1, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, url, Uri\\WhatWg\\\125rl, 0) @@ -169,21 +187,28 @@ ZEND_METHOD(Uri_Rfc3986_Uri, parse); ZEND_METHOD(Uri_Rfc3986_Uri, __construct); ZEND_METHOD(Uri_Rfc3986_Uri, getScheme); ZEND_METHOD(Uri_Rfc3986_Uri, getRawScheme); +ZEND_METHOD(Uri_Rfc3986_Uri, withScheme); ZEND_METHOD(Uri_Rfc3986_Uri, getUserInfo); ZEND_METHOD(Uri_Rfc3986_Uri, getRawUserInfo); +ZEND_METHOD(Uri_Rfc3986_Uri, withUserInfo); ZEND_METHOD(Uri_Rfc3986_Uri, getUsername); ZEND_METHOD(Uri_Rfc3986_Uri, getRawUsername); ZEND_METHOD(Uri_Rfc3986_Uri, getPassword); ZEND_METHOD(Uri_Rfc3986_Uri, getRawPassword); ZEND_METHOD(Uri_Rfc3986_Uri, getHost); ZEND_METHOD(Uri_Rfc3986_Uri, getRawHost); +ZEND_METHOD(Uri_Rfc3986_Uri, withHost); ZEND_METHOD(Uri_Rfc3986_Uri, getPort); +ZEND_METHOD(Uri_Rfc3986_Uri, withPort); ZEND_METHOD(Uri_Rfc3986_Uri, getPath); ZEND_METHOD(Uri_Rfc3986_Uri, getRawPath); +ZEND_METHOD(Uri_Rfc3986_Uri, withPath); ZEND_METHOD(Uri_Rfc3986_Uri, getQuery); ZEND_METHOD(Uri_Rfc3986_Uri, getRawQuery); +ZEND_METHOD(Uri_Rfc3986_Uri, withQuery); ZEND_METHOD(Uri_Rfc3986_Uri, getFragment); ZEND_METHOD(Uri_Rfc3986_Uri, getRawFragment); +ZEND_METHOD(Uri_Rfc3986_Uri, withFragment); ZEND_METHOD(Uri_Rfc3986_Uri, equals); ZEND_METHOD(Uri_Rfc3986_Uri, toString); ZEND_METHOD(Uri_Rfc3986_Uri, toRawString); @@ -201,11 +226,6 @@ ZEND_METHOD(Uri_WhatWg_Url, withUsername); ZEND_METHOD(Uri_WhatWg_Url, withPassword); ZEND_METHOD(Uri_WhatWg_Url, getAsciiHost); ZEND_METHOD(Uri_WhatWg_Url, getUnicodeHost); -ZEND_METHOD(Uri_WhatWg_Url, withHost); -ZEND_METHOD(Uri_WhatWg_Url, withPort); -ZEND_METHOD(Uri_WhatWg_Url, withPath); -ZEND_METHOD(Uri_WhatWg_Url, withQuery); -ZEND_METHOD(Uri_WhatWg_Url, withFragment); ZEND_METHOD(Uri_WhatWg_Url, equals); ZEND_METHOD(Uri_WhatWg_Url, toAsciiString); ZEND_METHOD(Uri_WhatWg_Url, toUnicodeString); @@ -219,21 +239,28 @@ static const zend_function_entry class_Uri_Rfc3986_Uri_methods[] = { ZEND_ME(Uri_Rfc3986_Uri, __construct, arginfo_class_Uri_Rfc3986_Uri___construct, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getScheme, arginfo_class_Uri_Rfc3986_Uri_getScheme, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getRawScheme, arginfo_class_Uri_Rfc3986_Uri_getRawScheme, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withScheme, arginfo_class_Uri_Rfc3986_Uri_withScheme, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getUserInfo, arginfo_class_Uri_Rfc3986_Uri_getUserInfo, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getRawUserInfo, arginfo_class_Uri_Rfc3986_Uri_getRawUserInfo, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withUserInfo, arginfo_class_Uri_Rfc3986_Uri_withUserInfo, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getUsername, arginfo_class_Uri_Rfc3986_Uri_getUsername, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getRawUsername, arginfo_class_Uri_Rfc3986_Uri_getRawUsername, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getPassword, arginfo_class_Uri_Rfc3986_Uri_getPassword, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getRawPassword, arginfo_class_Uri_Rfc3986_Uri_getRawPassword, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getHost, arginfo_class_Uri_Rfc3986_Uri_getHost, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getRawHost, arginfo_class_Uri_Rfc3986_Uri_getRawHost, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withHost, arginfo_class_Uri_Rfc3986_Uri_withHost, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getPort, arginfo_class_Uri_Rfc3986_Uri_getPort, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withPort, arginfo_class_Uri_Rfc3986_Uri_withPort, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getPath, arginfo_class_Uri_Rfc3986_Uri_getPath, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getRawPath, arginfo_class_Uri_Rfc3986_Uri_getRawPath, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withPath, arginfo_class_Uri_Rfc3986_Uri_withPath, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getQuery, arginfo_class_Uri_Rfc3986_Uri_getQuery, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getRawQuery, arginfo_class_Uri_Rfc3986_Uri_getRawQuery, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withQuery, arginfo_class_Uri_Rfc3986_Uri_withQuery, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getFragment, arginfo_class_Uri_Rfc3986_Uri_getFragment, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, getRawFragment, arginfo_class_Uri_Rfc3986_Uri_getRawFragment, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withFragment, arginfo_class_Uri_Rfc3986_Uri_withFragment, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, equals, arginfo_class_Uri_Rfc3986_Uri_equals, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, toString, arginfo_class_Uri_Rfc3986_Uri_toString, ZEND_ACC_PUBLIC) ZEND_ME(Uri_Rfc3986_Uri, toRawString, arginfo_class_Uri_Rfc3986_Uri_toRawString, ZEND_ACC_PUBLIC) @@ -265,15 +292,15 @@ static const zend_function_entry class_Uri_WhatWg_Url_methods[] = { ZEND_ME(Uri_WhatWg_Url, withPassword, arginfo_class_Uri_WhatWg_Url_withPassword, ZEND_ACC_PUBLIC) ZEND_ME(Uri_WhatWg_Url, getAsciiHost, arginfo_class_Uri_WhatWg_Url_getAsciiHost, ZEND_ACC_PUBLIC) ZEND_ME(Uri_WhatWg_Url, getUnicodeHost, arginfo_class_Uri_WhatWg_Url_getUnicodeHost, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, withHost, arginfo_class_Uri_WhatWg_Url_withHost, ZEND_ACC_PUBLIC) + ZEND_RAW_FENTRY("withHost", zim_Uri_Rfc3986_Uri_withHost, arginfo_class_Uri_WhatWg_Url_withHost, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getPort", zim_Uri_Rfc3986_Uri_getPort, arginfo_class_Uri_WhatWg_Url_getPort, ZEND_ACC_PUBLIC, NULL, NULL) - ZEND_ME(Uri_WhatWg_Url, withPort, arginfo_class_Uri_WhatWg_Url_withPort, ZEND_ACC_PUBLIC) + ZEND_RAW_FENTRY("withPort", zim_Uri_Rfc3986_Uri_withPort, arginfo_class_Uri_WhatWg_Url_withPort, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getPath", zim_Uri_Rfc3986_Uri_getPath, arginfo_class_Uri_WhatWg_Url_getPath, ZEND_ACC_PUBLIC, NULL, NULL) - ZEND_ME(Uri_WhatWg_Url, withPath, arginfo_class_Uri_WhatWg_Url_withPath, ZEND_ACC_PUBLIC) + ZEND_RAW_FENTRY("withPath", zim_Uri_Rfc3986_Uri_withPath, arginfo_class_Uri_WhatWg_Url_withPath, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getQuery", zim_Uri_Rfc3986_Uri_getQuery, arginfo_class_Uri_WhatWg_Url_getQuery, ZEND_ACC_PUBLIC, NULL, NULL) - ZEND_ME(Uri_WhatWg_Url, withQuery, arginfo_class_Uri_WhatWg_Url_withQuery, ZEND_ACC_PUBLIC) + ZEND_RAW_FENTRY("withQuery", zim_Uri_Rfc3986_Uri_withQuery, arginfo_class_Uri_WhatWg_Url_withQuery, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getFragment", zim_Uri_Rfc3986_Uri_getFragment, arginfo_class_Uri_WhatWg_Url_getFragment, ZEND_ACC_PUBLIC, NULL, NULL) - ZEND_ME(Uri_WhatWg_Url, withFragment, arginfo_class_Uri_WhatWg_Url_withFragment, ZEND_ACC_PUBLIC) + ZEND_RAW_FENTRY("withFragment", zim_Uri_Rfc3986_Uri_withFragment, arginfo_class_Uri_WhatWg_Url_withFragment, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_ME(Uri_WhatWg_Url, equals, arginfo_class_Uri_WhatWg_Url_equals, ZEND_ACC_PUBLIC) ZEND_ME(Uri_WhatWg_Url, toAsciiString, arginfo_class_Uri_WhatWg_Url_toAsciiString, ZEND_ACC_PUBLIC) ZEND_ME(Uri_WhatWg_Url, toUnicodeString, arginfo_class_Uri_WhatWg_Url_toUnicodeString, ZEND_ACC_PUBLIC) @@ -322,6 +349,9 @@ static zend_class_entry *register_class_Uri_Rfc3986_Uri(void) INIT_NS_CLASS_ENTRY(ce, "Uri\\Rfc3986", "Uri", class_Uri_Rfc3986_Uri_methods); class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_READONLY_CLASS); + + zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "withuserinfo", sizeof("withuserinfo") - 1), 0, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); + return class_entry; } diff --git a/ext/uri/tests/023.phpt b/ext/uri/tests/023.phpt index a1ca06bd6f6e..d1b97eaa9ae5 100644 --- a/ext/uri/tests/023.phpt +++ b/ext/uri/tests/023.phpt @@ -5,6 +5,30 @@ uri --FILE-- getRawScheme()); +var_dump($uri1->getScheme()); + +$uri2 = $uri1->withScheme("http"); +var_dump($uri2->getRawScheme()); +var_dump($uri2->getScheme()); + +$uri3 = $uri2->withScheme(null); +var_dump($uri3->getRawScheme()); +var_dump($uri3->getScheme()); + +try { + $uri3->withScheme(""); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri3->withScheme("http%73"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + $url1 = Uri\WhatWg\Url::parse("https://example.com"); $url2 = $url1->withScheme("http"); @@ -26,6 +50,14 @@ try { ?> --EXPECT-- string(5) "https" +string(5) "https" +string(4) "http" +string(4) "http" +NULL +NULL +The specified scheme is malformed +The specified scheme is malformed +string(5) "https" string(4) "http" The specified scheme is malformed The specified scheme is malformed diff --git a/ext/uri/tests/026.phpt b/ext/uri/tests/026.phpt index 47a8597fa2e7..2f50e41bb8c1 100644 --- a/ext/uri/tests/026.phpt +++ b/ext/uri/tests/026.phpt @@ -5,19 +5,84 @@ uri --FILE-- getRawHost()); +var_dump($uri1->getHost()); + +$uri2 = $uri1->withHost("test.com"); +var_dump($uri2->getRawHost()); +var_dump($uri2->getHost()); + +$uri3 = $uri2->withHost("t%65st.com"); // test.com +var_dump($uri3->getRawHost()); +var_dump($uri3->getHost()); + +$uri4 = $uri3->withHost(null); +var_dump($uri4->getRawHost()); +var_dump($uri4->getHost()); + +$uri5 = $uri4->withHost("192.168.0.1"); +var_dump($uri5->getRawHost()); +var_dump($uri5->getHost()); + +$uri6 = $uri5->withHost("[2001:db8:3333:4444:5555:6666:7777:8888]"); +var_dump($uri6->getRawHost()); +var_dump($uri6->getHost()); + +try { + $uri3->withHost("test.com:8080"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri3->withHost("t%3As%2Ft.com"); // t:s/t.com +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri3->withHost("t:s/t.com"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri2->withHost(""); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +$uri1 = Uri\Rfc3986\Uri::parse("ftp://user:pass@foo.com?query=abc#foo"); +$uri2 = $uri1->withHost("test.com"); + +var_dump($uri1->getHost()); +var_dump($uri2->getHost()); + +try { + $uri1->withHost(null); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + $url1 = Uri\WhatWg\Url::parse("https://example.com"); $url2 = $url1->withHost("test.com"); $url3 = $url2->withHost("t%65st.com"); // test.com +$url4 = $url3->withHost("192.168.0.1"); +$url5 = $url4->withHost("[2001:db8:3333:4444:5555:6666:7777:8888]"); + +var_dump($url1->getAsciiHost()); +var_dump($url2->getAsciiHost()); +var_dump($url3->getAsciiHost()); +var_dump($url4->getAsciiHost()); +var_dump($url5->getAsciiHost()); + try { $url3->withHost("test.com:8080"); } catch (Uri\WhatWg\InvalidUrlException $e) { echo $e->getMessage() . "\n"; } -var_dump($url1->getAsciiHost()); -var_dump($url2->getAsciiHost()); -var_dump($url3->getAsciiHost()); - try { $url3->withHost("t%3As%2Ft.com"); // t:s/t.com } catch (Uri\WhatWg\InvalidUrlException $e) { @@ -44,10 +109,29 @@ var_dump($url2->getAsciiHost()); ?> --EXPECTF-- +string(11) "example.com" +string(11) "example.com" +string(8) "test.com" +string(8) "test.com" +string(10) "t%65st.com" +string(8) "test.com" +NULL +NULL +string(11) "192.168.0.1" +string(11) "192.168.0.1" +string(40) "[2001:db8:3333:4444:5555:6666:7777:8888]" +string(40) "[2001:db8:3333:4444:5555:6666:7777:8888]" +The specified host is malformed The specified host is malformed +string(7) "foo.com" +string(8) "test.com" +Cannot remove the host from a URI that has a userinfo string(11) "example.com" string(8) "test.com" string(8) "test.com" +string(11) "192.168.0.1" +string(40) "[2001:db8:3333:4444:5555:6666:7777:8888]" +The specified host is malformed The specified host is malformed (DomainInvalidCodePoint) The specified host is malformed The specified host is malformed (HostMissing) diff --git a/ext/uri/tests/026_userinfo.phpt b/ext/uri/tests/026_userinfo.phpt new file mode 100644 index 000000000000..75f54fccf612 --- /dev/null +++ b/ext/uri/tests/026_userinfo.phpt @@ -0,0 +1,53 @@ +--TEST-- +Test property mutation - userinfo +--EXTENSIONS-- +uri +--FILE-- +getRawUserInfo()); +var_dump($uri1->getUserInfo()); + +$uri2 = $uri1->withUserInfo("user"); +var_dump($uri2->getRawUserInfo()); +var_dump($uri2->getUserInfo()); + +$uri3 = $uri2->withUserInfo(null); +var_dump($uri3->getRawUserInfo()); +var_dump($uri3->getUserInfo()); + +$uri4 = $uri3->withUserInfo("%75s%2Fr:pass"); // us/r:pass +var_dump($uri4->getRawUserInfo()); +var_dump($uri4->getUserInfo()); + +$uri1 = Uri\Rfc3986\Uri::parse("/foo"); +$uri2 = $uri1->withUserInfo(null); +var_dump($uri2->getPort()); + +try { + $uri4->withUserInfo("u:s/r"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +$uri5 = Uri\Rfc3986\Uri::parse("file:///foo/bar/"); +$uri6 = $uri5->withUserinfo("user:pass"); + +var_dump($uri5->getUserInfo()); +var_dump($uri6->getUserInfo()); + +?> +--EXPECT-- +NULL +NULL +string(4) "user" +string(4) "user" +NULL +NULL +string(13) "%75s%2Fr:pass" +string(11) "us%2Fr:pass" +NULL +The specified userinfo is malformed +NULL +string(9) "user:pass" diff --git a/ext/uri/tests/027.phpt b/ext/uri/tests/027.phpt index 79c121dd7f38..781932f5889e 100644 --- a/ext/uri/tests/027.phpt +++ b/ext/uri/tests/027.phpt @@ -5,6 +5,36 @@ uri --FILE-- withPort(22); +$uri3 = $uri2->withPort(null); + +var_dump($uri1->getPort()); +var_dump($uri2->getPort()); +var_dump($uri3->getPort()); + +$uri1 = Uri\Rfc3986\Uri::parse("ftp://foo.com:443?query=abc#foo"); +$uri2 = $uri1->withPort(8080); + +var_dump($uri1->getPort()); +var_dump($uri2->getPort()); + +$uri1 = Uri\Rfc3986\Uri::parse("file:///foo/bar"); +$uri2 = $uri1->withPort(80); + +var_dump($uri1->getPort()); +var_dump($uri2->getPort()); + +$uri1 = Uri\Rfc3986\Uri::parse("/foo"); +$uri2 = $uri1->withPort(null); +var_dump($uri2->getPort()); + +try { + $uri1->withPort(1); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + $url1 = Uri\WhatWg\Url::parse("https://example.com:8080"); $url2 = $url1->withPort(22); $url3 = $url2->withPort(null); @@ -33,4 +63,13 @@ NULL int(443) int(8080) NULL +int(80) +NULL +Cannot set a port without having a host +int(8080) +int(22) +NULL +int(443) +int(8080) +NULL NULL diff --git a/ext/uri/tests/028.phpt b/ext/uri/tests/028.phpt index fd565c900e02..9c9c92c00cc0 100644 --- a/ext/uri/tests/028.phpt +++ b/ext/uri/tests/028.phpt @@ -5,6 +5,44 @@ uri --FILE-- getRawPath()); +var_dump($uri1->getPath()); + +$uri2 = $uri1->withPath("/foo"); +var_dump($uri2->getRawPath()); +var_dump($uri2->getPath()); + +$uri3 = $uri2->withPath("/t%65st"); +var_dump($uri3->getRawPath()); +var_dump($uri3->getPath()); + +$uri4 = $uri3->withPath("/foo%2Fbar"); +var_dump($uri4->getRawPath()); +var_dump($uri4->getPath()); + +$uri5 = $uri4->withPath(""); +var_dump($uri5->getRawPath()); +var_dump($uri5->getPath()); + +try { + $uri5->withPath("test"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri5->withPath("/#"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +$uri1 = Uri\Rfc3986\Uri::parse("/foo"); +$uri2 = $uri1->withPath("bar"); + +var_dump($uri1->getPath()); +var_dump($uri2->getPath()); + $url1 = Uri\WhatWg\Url::parse("https://example.com/foo/bar/"); $url2 = $url1->withPath("/foo"); $url3 = $url2->withPath(""); @@ -28,6 +66,20 @@ var_dump($url2->getPath()); ?> --EXPECT-- string(9) "/foo/bar/" +string(9) "/foo/bar/" +string(4) "/foo" +string(4) "/foo" +string(7) "/t%65st" +string(5) "/test" +string(10) "/foo%2Fbar" +string(10) "/foo%2Fbar" +string(0) "" +string(0) "" +The specified path is malformed +The specified path is malformed +string(4) "/foo" +string(3) "bar" +string(9) "/foo/bar/" string(4) "/foo" string(1) "/" string(7) "/t%65st" diff --git a/ext/uri/tests/029.phpt b/ext/uri/tests/029.phpt index e23008a65ad6..f7a1a0989910 100644 --- a/ext/uri/tests/029.phpt +++ b/ext/uri/tests/029.phpt @@ -5,6 +5,44 @@ uri --FILE-- getRawQuery()); +var_dump($uri1->getQuery()); + +$uri2 = $uri1->withQuery("foo=baz"); +var_dump($uri2->getRawQuery()); +var_dump($uri2->getQuery()); + +$uri3 = $uri2->withQuery(null); +var_dump($uri3->getRawQuery()); +var_dump($uri3->getQuery()); + +$uri1 = Uri\Rfc3986\Uri::parse("https://example.com"); +var_dump($uri1->getRawQuery()); +var_dump($uri1->getQuery()); + +$uri2 = $uri1->withQuery("?foo=bar&foo=baz"); +var_dump($uri2->getRawQuery()); +var_dump($uri2->getQuery()); + +$uri3 = $uri1->withQuery("foo=bar&foo=baz"); +var_dump($uri3->getRawQuery()); +var_dump($uri3->getQuery()); + +$uri4 = $uri3->withQuery("t%65st"); +var_dump($uri4->getRawQuery()); +var_dump($uri4->getQuery()); + +$uri5 = $uri4->withQuery("foo=foo%26bar&baz=/qux%3D"); +var_dump($uri5->getRawQuery()); +var_dump($uri5->getQuery()); + +try { + $uri5->withQuery("#"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + $url1 = Uri\WhatWg\Url::parse("https://example.com?foo=bar"); $url2 = $url1->withQuery("?foo=baz"); $url3 = $url2->withQuery(null); @@ -30,6 +68,23 @@ var_dump($url6->getQuery()); ?> --EXPECT-- string(7) "foo=bar" +string(7) "foo=bar" +string(7) "foo=baz" +string(7) "foo=baz" +NULL +NULL +NULL +NULL +string(16) "?foo=bar&foo=baz" +string(16) "?foo=bar&foo=baz" +string(15) "foo=bar&foo=baz" +string(15) "foo=bar&foo=baz" +string(6) "t%65st" +string(4) "test" +string(25) "foo=foo%26bar&baz=/qux%3D" +string(25) "foo=foo%26bar&baz=/qux%3D" +The specified query is malformed +string(7) "foo=bar" string(7) "foo=baz" NULL NULL diff --git a/ext/uri/tests/030.phpt b/ext/uri/tests/030.phpt index 6bb85e6720c9..92e99d01f892 100644 --- a/ext/uri/tests/030.phpt +++ b/ext/uri/tests/030.phpt @@ -5,6 +5,36 @@ uri --FILE-- getRawFragment()); +var_dump($uri1->getFragment()); + +$uri2 = $uri1->withFragment("fragment2"); +var_dump($uri2->getRawFragment()); +var_dump($uri2->getFragment()); + +$uri3 = $uri2->withFragment(null); +var_dump($uri3->getRawFragment()); +var_dump($uri3->getFragment()); + +try { + $uri3->withFragment(" "); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +try { + $uri1->withFragment("#fragment2"); +} catch (Uri\InvalidUriException $e) { + echo $e->getMessage() . "\n"; +} + +$uri1 = Uri\Rfc3986\Uri::parse("https://example.com?abc=def"); +$uri2 = $uri1->withFragment("fragment"); + +var_dump($uri1->getFragment()); +var_dump($uri2->getFragment()); + $url1 = Uri\WhatWg\Url::parse("https://example.com#fragment1"); $url2 = $url1->withFragment("#fragment2"); $url3 = $url2->withFragment(null); @@ -24,6 +54,16 @@ var_dump($url2->getFragment()); ?> --EXPECT-- string(9) "fragment1" +string(9) "fragment1" +string(9) "fragment2" +string(9) "fragment2" +NULL +NULL +The specified fragment is malformed +The specified fragment is malformed +NULL +string(8) "fragment" +string(9) "fragment1" string(9) "fragment2" NULL string(3) "%20" diff --git a/ext/uri/tests/035.phpt b/ext/uri/tests/035.phpt index 2712038d4e3d..3c3987037374 100644 --- a/ext/uri/tests/035.phpt +++ b/ext/uri/tests/035.phpt @@ -11,6 +11,13 @@ try { echo $e->getMessage() . "\n"; } +$uri = new Uri\Rfc3986\Uri("https://example.com"); +try { + $uri->withHost("exam\0ple.com"); +} catch (Error $e) { + echo $e->getMessage() . "\n"; +} + try { new Uri\WhatWg\Url("https://exam\0ple.com"); } catch (Error $e) { @@ -27,5 +34,6 @@ try { ?> --EXPECT-- Uri\Rfc3986\Uri::__construct(): Argument #1 ($uri) must not contain any null bytes +Uri\Rfc3986\Uri::withHost(): Argument #1 ($host) must not contain any null bytes Uri\WhatWg\Url::__construct(): Argument #1 ($uri) must not contain any null bytes Uri\WhatWg\Url::withHost(): Argument #1 ($host) must not contain any null bytes diff --git a/ext/uri/tests/057.phpt b/ext/uri/tests/057.phpt index e2a109ccdacb..458bdb468e34 100644 --- a/ext/uri/tests/057.phpt +++ b/ext/uri/tests/057.phpt @@ -14,7 +14,7 @@ try { Uri\WhatWg\Url::parse(" https://example.org ", errors: $f->x); } catch (Throwable $e) { echo $e::class, ": ", $e->getMessage(), PHP_EOL; -} +} ?> --EXPECT-- diff --git a/ext/uri/uri_parser_rfc3986.c b/ext/uri/uri_parser_rfc3986.c index 70e0eaae1f0a..01f89f4ccc7c 100644 --- a/ext/uri/uri_parser_rfc3986.c +++ b/ext/uri/uri_parser_rfc3986.c @@ -99,6 +99,13 @@ ZEND_ATTRIBUTE_NONNULL static UriUriA *get_uri_for_reading(php_uri_parser_rfc398 } } +ZEND_ATTRIBUTE_NONNULL static UriUriA *get_uri_for_writing(uri_internal_t *internal_uri) +{ + php_uri_parser_rfc3986_uris *uriparser_uris = internal_uri->uri; + + return &uriparser_uris->uri; +} + ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_scheme_read(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) { const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); @@ -112,6 +119,25 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_scheme_read(con return SUCCESS; } +static zend_result php_uri_parser_rfc3986_scheme_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetSchemeMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetSchemeMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + if (result != URI_SUCCESS) { + zend_throw_exception(uri_invalid_uri_exception_ce, "The specified scheme is malformed", 0); + return FAILURE; + } + + return SUCCESS; +} + ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_rfc3986_userinfo_read(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) { const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); @@ -125,6 +151,29 @@ ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_rfc3986_userinfo_read(const ur return SUCCESS; } +zend_result php_uri_parser_rfc3986_userinfo_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetUserInfoMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetUserInfoMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + switch (result) { + case URI_SUCCESS: + return SUCCESS; + case URI_ERROR_SETUSERINFO_HOST_NOT_SET: + zend_throw_exception(uri_invalid_uri_exception_ce, "Cannot set a userinfo without having a host", 0); + return FAILURE; + default: + zend_throw_exception(uri_invalid_uri_exception_ce, "The specified userinfo is malformed", 0); + return FAILURE; + } +} + ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_username_read(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) { const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); @@ -190,6 +239,32 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_host_read(const return SUCCESS; } +static zend_result php_uri_parser_rfc3986_host_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetHostAutoMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetHostAutoMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + switch (result) { + case URI_SUCCESS: + return SUCCESS; + case URI_ERROR_SETHOST_PORT_SET: + zend_throw_exception(uri_invalid_uri_exception_ce, "Cannot remove the host from a URI that has a port", 0); + return FAILURE; + case URI_ERROR_SETHOST_USERINFO_SET: + zend_throw_exception(uri_invalid_uri_exception_ce, "Cannot remove the host from a URI that has a userinfo", 0); + return FAILURE; + default: + zend_throw_exception(uri_invalid_uri_exception_ce, "The specified host is malformed", 0); + return FAILURE; + } +} + ZEND_ATTRIBUTE_NONNULL static zend_long port_str_to_zend_long_checked(const char *str, size_t len) { if (len > MAX_LENGTH_OF_LONG) { @@ -221,6 +296,31 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_port_read(const return SUCCESS; } +static zend_result php_uri_parser_rfc3986_port_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetPortTextMmA(uriparser_uri, NULL, NULL, mm); + } else { + zend_string *tmp = zend_long_to_str(Z_LVAL_P(value)); + result = uriSetPortTextMmA(uriparser_uri, ZSTR_VAL(tmp), ZSTR_VAL(tmp) + ZSTR_LEN(tmp), mm); + zend_string_release_ex(tmp, false); + } + + switch (result) { + case URI_SUCCESS: + return SUCCESS; + case URI_ERROR_SETPORT_HOST_NOT_SET: + zend_throw_exception(uri_invalid_uri_exception_ce, "Cannot set a port without having a host", 0); + return FAILURE; + default: + zend_throw_exception(uri_invalid_uri_exception_ce, "The specified port is malformed", 0); + return FAILURE; + } +} + ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_path_read(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) { const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); @@ -249,6 +349,25 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_path_read(const return SUCCESS; } +static zend_result php_uri_parser_rfc3986_path_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + int result; + + if (Z_STRLEN_P(value) == 0) { + result = uriSetPathMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetPathMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + if (result != URI_SUCCESS) { + zend_throw_exception(uri_invalid_uri_exception_ce, "The specified path is malformed", 0); + return FAILURE; + } + + return SUCCESS; +} + ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_query_read(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) { const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); @@ -262,6 +381,25 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_query_read(cons return SUCCESS; } +static zend_result php_uri_parser_rfc3986_query_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetQueryMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetQueryMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + if (result != URI_SUCCESS) { + zend_throw_exception(uri_invalid_uri_exception_ce, "The specified query is malformed", 0); + return FAILURE; + } + + return SUCCESS; +} + ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_fragment_read(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval) { const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); @@ -275,6 +413,25 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_fragment_read(c return SUCCESS; } +static zend_result php_uri_parser_rfc3986_fragment_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +{ + UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + int result; + + if (Z_TYPE_P(value) == IS_NULL) { + result = uriSetFragmentMmA(uriparser_uri, NULL, NULL, mm); + } else { + result = uriSetFragmentMmA(uriparser_uri, Z_STRVAL_P(value), Z_STRVAL_P(value) + Z_STRLEN_P(value), mm); + } + + if (result != URI_SUCCESS) { + zend_throw_exception(uri_invalid_uri_exception_ce, "The specified fragment is malformed", 0); + return FAILURE; + } + + return SUCCESS; +} + static php_uri_parser_rfc3986_uris *uriparser_create_uris(void) { php_uri_parser_rfc3986_uris *uriparser_uris = ecalloc(1, sizeof(*uriparser_uris)); @@ -414,13 +571,13 @@ const uri_parser_t php_uri_parser_rfc3986 = { .uri_to_string = php_uri_parser_rfc3986_to_string, .free_uri = php_uri_parser_rfc3986_free, { - .scheme = {.read_func = php_uri_parser_rfc3986_scheme_read, .write_func = NULL}, + .scheme = {.read_func = php_uri_parser_rfc3986_scheme_read, .write_func = php_uri_parser_rfc3986_scheme_write}, .username = {.read_func = php_uri_parser_rfc3986_username_read, .write_func = NULL}, .password = {.read_func = php_uri_parser_rfc3986_password_read, .write_func = NULL}, - .host = {.read_func = php_uri_parser_rfc3986_host_read, .write_func = NULL}, - .port = {.read_func = php_uri_parser_rfc3986_port_read, .write_func = NULL}, - .path = {.read_func = php_uri_parser_rfc3986_path_read, .write_func = NULL}, - .query = {.read_func = php_uri_parser_rfc3986_query_read, .write_func = NULL}, - .fragment = {.read_func = php_uri_parser_rfc3986_fragment_read, .write_func = NULL}, + .host = {.read_func = php_uri_parser_rfc3986_host_read, .write_func = php_uri_parser_rfc3986_host_write}, + .port = {.read_func = php_uri_parser_rfc3986_port_read, .write_func = php_uri_parser_rfc3986_port_write}, + .path = {.read_func = php_uri_parser_rfc3986_path_read, .write_func = php_uri_parser_rfc3986_path_write}, + .query = {.read_func = php_uri_parser_rfc3986_query_read, .write_func = php_uri_parser_rfc3986_query_write}, + .fragment = {.read_func = php_uri_parser_rfc3986_fragment_read, .write_func = php_uri_parser_rfc3986_fragment_write}, } }; diff --git a/ext/uri/uri_parser_rfc3986.h b/ext/uri/uri_parser_rfc3986.h index 461136a9f06c..7f54b194ec36 100644 --- a/ext/uri/uri_parser_rfc3986.h +++ b/ext/uri/uri_parser_rfc3986.h @@ -29,6 +29,7 @@ typedef struct php_uri_parser_rfc3986_uris { } php_uri_parser_rfc3986_uris; zend_result php_uri_parser_rfc3986_userinfo_read(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval); +zend_result php_uri_parser_rfc3986_userinfo_write(struct uri_internal_t *internal_uri, zval *value, zval *errors); php_uri_parser_rfc3986_uris *php_uri_parser_rfc3986_parse_ex(const char *uri_str, size_t uri_str_len, const php_uri_parser_rfc3986_uris *uriparser_base_url, bool silent);