@@ -83,13 +83,30 @@ + (NSURL *)NSURL:(id)json
8383 return nil ;
8484 }
8585
86- @try { // NSURL has a history of crashing with bad input, so let's be
86+ @try { // NSURL has a history of crashing with bad input, so let's be safe
8787
88- NSURLComponents *urlComponents = [ NSURLComponents componentsWithString: path]; // [NSURL URLWithString:path];
89- if (urlComponents .scheme ) {
90- return [ self _preprocessURLComponents: urlComponents from: path]. URL ;
88+ NSURL *URL = [NSURL URLWithString: path];
89+ if (URL .scheme ) { // Was a well-formed absolute URL
90+ return URL;
9191 }
9292
93+ // Check if it has a scheme
94+ if ([path rangeOfString: @" ://" ].location != NSNotFound ) {
95+ NSMutableCharacterSet *urlAllowedCharacterSet = [NSMutableCharacterSet new ];
96+ [urlAllowedCharacterSet formUnionWithCharacterSet: [NSCharacterSet URLUserAllowedCharacterSet ]];
97+ [urlAllowedCharacterSet formUnionWithCharacterSet: [NSCharacterSet URLPasswordAllowedCharacterSet ]];
98+ [urlAllowedCharacterSet formUnionWithCharacterSet: [NSCharacterSet URLHostAllowedCharacterSet ]];
99+ [urlAllowedCharacterSet formUnionWithCharacterSet: [NSCharacterSet URLPathAllowedCharacterSet ]];
100+ [urlAllowedCharacterSet formUnionWithCharacterSet: [NSCharacterSet URLQueryAllowedCharacterSet ]];
101+ [urlAllowedCharacterSet formUnionWithCharacterSet: [NSCharacterSet URLFragmentAllowedCharacterSet ]];
102+ path = [path stringByAddingPercentEncodingWithAllowedCharacters: urlAllowedCharacterSet];
103+ URL = [NSURL URLWithString: path];
104+ if (URL) {
105+ return URL;
106+ }
107+ }
108+
109+ // Assume that it's a local path
93110 path = path.stringByRemovingPercentEncoding ;
94111 if ([path hasPrefix: @" ~" ]) {
95112 // Path is inside user directory
@@ -98,8 +115,7 @@ + (NSURL *)NSURL:(id)json
98115 // Assume it's a resource path
99116 path = [[NSBundle mainBundle ].resourcePath stringByAppendingPathComponent: path];
100117 }
101- NSURL *URL = [NSURL fileURLWithPath: path];
102- if (!URL) {
118+ if (!(URL = [NSURL fileURLWithPath: path])) {
103119 RCTLogConvertError (json, @" a valid URL" );
104120 }
105121 return URL;
@@ -109,39 +125,6 @@ + (NSURL *)NSURL:(id)json
109125 }
110126}
111127
112- // This function preprocess the URLComponents received to make sure that we decode it properly
113- // handling all the use cases.
114- // See the `RCTConvert_NSURLTests` file for a list of use cases that we want to support:
115- // To achieve that, we are currently splitting the url, extracting the fragment, so we can
116- // decode and encode everything but the fragment (which has to be left unmodified)
117- + (NSURLComponents *)_preprocessURLComponents : (NSURLComponents *)urlComponents from : (NSString *)path
118- {
119- // https://developer.apple.com/documentation/foundation/nsurlcomponents
120- // "[NSURLComponents's] behavior differs subtly from the NSURL class, which conforms to older RFCs"
121- // Specifically, NSURL rejects some URLs that NSURLComponents will handle
122- // gracefully.
123- NSRange fragmentRange = urlComponents.rangeOfFragment ;
124-
125- if (fragmentRange.length == 0 ) {
126- // No fragment, pre-remove all escaped characters so we can encode them once if they are present.
127- NSError *error = nil ;
128- NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: @" %[0-90-9]" options: 0 error: &error];
129- NSTextCheckingResult *match = [regex firstMatchInString: path options: 0 range: NSMakeRange (0 , path.length)];
130- if (match) {
131- return [NSURLComponents componentsWithString: path.stringByRemovingPercentEncoding];
132- }
133- return [NSURLComponents componentsWithString: path];
134- }
135- // Pre-remove all escaped characters (excluding the fragment) to handle partially encoded strings
136- NSString *baseUrlString = [path substringToIndex: fragmentRange.location].stringByRemovingPercentEncoding ;
137- // Fragment must be kept as they are passed. We don't have to escape them
138- NSString *unmodifiedFragment = [path substringFromIndex: fragmentRange.location];
139-
140- // Recreate the url by using a decoded base and an unmodified fragment.
141- NSString *preprocessedURL = [NSString stringWithFormat: @" %@%@ " , baseUrlString, unmodifiedFragment];
142- return [NSURLComponents componentsWithString: preprocessedURL];
143- }
144-
145128RCT_ENUM_CONVERTER (
146129 NSURLRequestCachePolicy ,
147130 (@{
0 commit comments