decode urls before reencoding with NSURL (#39344)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39344

## Changelog:
[iOS][General] - URLs parsed by RCTConvert should be encoded respecting RFC 3986, 1738/1808

in ios 17, NSURLs are encoded respecting RFC 3986 (https://www.ietf.org/rfc/rfc3986.txt) as opposed to RFC 1738/1808 before.

following this, `NSURL`'s parsing algorithm has changed such that if they encounter a reserved character, such as `[`, the parser will percent encode all possible characters in the url, including `%`.

this causes trouble for urls that already have some encoding. for the string `%22[]`, the new parsing algorithm will return the following:

RFC 1738/1808 -> `%22%5B%5D`
RFC 3986 -> `%2522%5B%5D` (invalid encoding)

the solution here is to decode all the percentified encodings in the input string, completely stripping it of the percent encodings, and then re-encoding it. thus, the string will transform as follows:

`%22[]` -> `"[]` -> `%22%5B%5D`

we probably don't need the OS check, but including it just to be safe.

Reviewed By: yungsters

Differential Revision: D49082077

fbshipit-source-id: 21ac1e37c957db3217746f9385f9d7947261794d
This commit is contained in:
Phillip Pan
2023-09-08 14:12:37 -07:00
committed by Facebook GitHub Bot
parent 8658bdccbc
commit 9841bd8185
@@ -84,8 +84,16 @@ RCT_CUSTOM_CONVERTER(NSData *, NSData, [json dataUsingEncoding:NSUTF8StringEncod
}
@try { // NSURL has a history of crashing with bad input, so let's be safe
NSURL *URL = nil;
NSURL *URL = [NSURL URLWithString:path];
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000
if (@available(iOS 17.0, *)) {
NSString *decodedPercentPath = [path stringByRemovingPercentEncoding];
URL = [NSURL URLWithString:decodedPercentPath encodingInvalidCharacters:YES];
}
#endif
URL = URL ?: [NSURL URLWithString:path];
if (URL.scheme) { // Was a well-formed absolute URL
return URL;
}