Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions Boxer/BXDriveBundleImport.m
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,18 @@ - (void) main
if (self.isCancelled) return;

//Work out what to do with the related file paths we've parsed from the cue file
NSURL *baseURL = sourceURL.URLByDeletingLastPathComponent;
NSMutableDictionary *revisedPaths = [NSMutableDictionary dictionaryWithCapacity: numRelatedPaths];

for (NSString *fromPath in relatedPaths)
{
//Rewrite Windows-style paths
NSString *sanitisedFromPath = [fromPath stringByReplacingOccurrencesOfString: @"\\" withString: @"/"];
NSError *pathError = nil;
NSURL *fromURL = [ADBBinCueImage resourceURLForRawPath: fromPath inCueAtURL: sourceURL error: &pathError];
if (!fromURL)
{
self.error = pathError;
return;
}

NSURL *fromURL = [baseURL URLByAppendingPathComponent: sanitisedFromPath];
NSString *fromName = fromURL.lastPathComponent;
NSURL *toURL = [destinationURL URLByAppendingPathComponent: fromName];

Expand Down
5 changes: 5 additions & 0 deletions Other Sources/ADBToolkit/ADBBinCueImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,13 @@ NS_ASSUME_NONNULL_BEGIN

/// Returns an array of the track files specified in the specified CUE,
/// as absolute OS X filesystem URLs resolved relative to the CUE's location.
/// Returns @c nil and populates @c outError if any resource resolves outside the CUE's folder.
+ (nullable NSArray<NSURL*> *) resourceURLsInCueAtURL: (NSURL *)cueURL error: (out NSError **)outError;

/// Returns a track file URL resolved relative to the specified CUE file.
/// Returns @c nil and populates @c outError if the resource resolves outside the CUE's folder.
+ (nullable NSURL *) resourceURLForRawPath: (NSString *)rawPath inCueAtURL: (NSURL *)cueURL error: (out NSError **)outError;

/// Returns the location of the binary image for the specified CUE file,
/// as an absolute OS X filesystem URL resolved relative to the CUE's location.
/// Returns @c nil if the binary image path could not be determined.
Expand Down
66 changes: 58 additions & 8 deletions Other Sources/ADBToolkit/ADBBinCueImage.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,26 @@
/// This is used as a sanity check by +isCueAtPath: to avoid scanning large files unnecessarily.
#define ADBCueMaxFileSize 10240

static BOOL ADBURLIsInDirectory(NSURL *URL, NSURL *directoryURL)
{
NSString *path = URL.URLByStandardizingPath.URLByResolvingSymlinksInPath.path;
NSString *directoryPath = directoryURL.URLByStandardizingPath.URLByResolvingSymlinksInPath.path;

return [path isEqualToString: directoryPath] || [path hasPrefix: [directoryPath stringByAppendingString: @"/"]];
}

static NSError *ADBCueResourcePathError(NSURL *cueURL, NSString *rawPath)
{
NSString *description = [NSString stringWithFormat: @"The CUE file “%@” refers to a resource outside its folder.", cueURL.lastPathComponent];
NSString *failureReason = [NSString stringWithFormat: @"The resource path “%@” does not resolve inside the CUE file's folder.", rawPath];

return [NSError errorWithDomain: NSCocoaErrorDomain
code: NSFileReadInvalidFileNameError
userInfo: @{ NSLocalizedDescriptionKey: description,
NSLocalizedFailureReasonErrorKey: failureReason,
NSURLErrorKey: cueURL }];
}


@implementation ADBBinCueImage

Expand Down Expand Up @@ -70,6 +90,28 @@ + (NSArray *) rawPathsInCueContents: (NSString *)cueContents
return paths;
}

+ (NSURL *) resourceURLForRawPath: (NSString *)rawPath inCueAtURL: (NSURL *)cueURL error: (out NSError **)outError
{
NSURL *baseURL = cueURL.URLByDeletingLastPathComponent.URLByStandardizingPath;

//Rewrite Windows-style paths
NSString *normalizedPath = [rawPath stringByReplacingOccurrencesOfString: @"\\" withString: @"/"];

//Form an absolute path with all ../ components resolved.
NSURL *resourceURL = [baseURL URLByAppendingPathComponent: normalizedPath].URLByStandardizingPath;

if (!ADBURLIsInDirectory(resourceURL, baseURL))
{
if (outError)
{
*outError = ADBCueResourcePathError(cueURL, rawPath);
}
return nil;
}

return resourceURL;
}

+ (NSArray *) resourceURLsInCueAtURL: (NSURL *)cueURL error: (out NSError **)outError
{
NSString *cueContents = [[NSString alloc] initWithContentsOfURL: cueURL
Expand All @@ -81,20 +123,28 @@ + (NSArray *) resourceURLsInCueAtURL: (NSURL *)cueURL error: (out NSError **)out

NSArray *rawPaths = [self rawPathsInCueContents: cueContents];

//The URL relative to which we will resolve the paths in the CUE
NSURL *baseURL = cueURL.URLByDeletingLastPathComponent;

NSMutableArray *resolvedURLs = [NSMutableArray arrayWithCapacity: rawPaths.count];
NSError *resourceError = nil;
for (NSString *rawPath in rawPaths)
@autoreleasepool {
//Rewrite Windows-style paths
NSString *normalizedPath = [rawPath stringByReplacingOccurrencesOfString: @"\\" withString: @"/"];

//Form an absolute path with all ../ components resolved.
NSURL *resourceURL = [baseURL URLByAppendingPathComponent: normalizedPath].URLByStandardizingPath;
NSURL *resourceURL = [self resourceURLForRawPath: rawPath inCueAtURL: cueURL error: &resourceError];
if (!resourceURL)
{
break;
}

[resolvedURLs addObject: resourceURL];
}

if (resourceError)
{
if (outError)
{
*outError = resourceError;
}
return nil;
}

return resolvedURLs;
}

Expand Down