From 50b80a9ef8c78126ce47c534f4a1b671d67c8e60 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 3 Aug 2018 07:50:29 -0700 Subject: [PATCH] Fabric: Fixed image URLs parsing Summary: @public It's a basically reimplementation of `+[RCTConvert NSURL:]`. Reviewed By: mdvacca Differential Revision: D9146850 fbshipit-source-id: 57ecac1eb35b57b0d417b599371bd0c4a3988116 --- .../ios/RCTImagePrimitivesConversions.h | 59 ++++++++++++++++--- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/ReactCommon/fabric/imagemanager/platform/ios/RCTImagePrimitivesConversions.h b/ReactCommon/fabric/imagemanager/platform/ios/RCTImagePrimitivesConversions.h index 8683a0089..32b1a07e4 100644 --- a/ReactCommon/fabric/imagemanager/platform/ios/RCTImagePrimitivesConversions.h +++ b/ReactCommon/fabric/imagemanager/platform/ios/RCTImagePrimitivesConversions.h @@ -32,18 +32,61 @@ inline std::string toString(const ImageResizeMode &value) { } } -inline static NSURLRequest *NSURLRequestFromImageSource(const ImageSource &imageSource) { +inline static NSURL *NSURLFromImageSource(const ImageSource &imageSource) { + // `NSURL` has a history of crashing with bad input, so let's be safe. + @try { + NSString *urlString = [NSString stringWithCString:imageSource.uri.c_str() + encoding:NSASCIIStringEncoding]; - NSString *urlString = [NSString stringWithCString:imageSource.uri.c_str() - encoding:NSASCIIStringEncoding]; + if (!imageSource.bundle.empty()) { + NSString *bundle = [NSString stringWithCString:imageSource.bundle.c_str() + encoding:NSASCIIStringEncoding]; + urlString = [NSString stringWithFormat:@"%@.bundle/%@", bundle, urlString]; + } - if (!imageSource.bundle.empty()) { - NSString *bundle = [NSString stringWithCString:imageSource.bundle.c_str() - encoding:NSASCIIStringEncoding]; - urlString = [NSString stringWithFormat:@"%@.bundle/%@", bundle, urlString]; + NSURL *url = [[NSURL alloc] initWithString:urlString]; + + if (url.scheme) { + // Well-formed absolute URL. + return url; + } + + if ([urlString rangeOfString:@":"].location != NSNotFound) { + // The URL has a scheme. + urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + url = [NSURL URLWithString:urlString]; + return url; + } + + // Assume that it's a local path. + urlString = [urlString stringByRemovingPercentEncoding]; + + if ([urlString hasPrefix:@"~"]) { + // Path is inside user directory. + urlString = [urlString stringByExpandingTildeInPath]; + } else { + if (![urlString isAbsolutePath]) { + // Assume it's a resource path. + urlString = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:urlString]; + } + } + + url = [NSURL fileURLWithPath:urlString]; + + return url; } + @catch (__unused NSException *exception) { + return nil; + } +} - NSURL *url = [[NSURL alloc] initWithString:urlString]; +inline static NSURLRequest *NSURLRequestFromImageSource(const ImageSource &imageSource) { + NSURL *url = NSURLFromImageSource(imageSource); + + if (!url) { + RCTLogError(@"URI parsing error."); + return nil; + } NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];