123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- #import "AppSandboxFileAccess.h"
- #import "AppSandboxFileAccessPersist.h"
- #import "AppSandboxFileAccessOpenSavePanelDelegate.h"
- #if !__has_feature(objc_arc)
- #error ARC must be enabled!
- #endif
- #define CFBundleDisplayName @"CFBundleDisplayName"
- #define CFBundleName @"CFBundleName"
- @interface AppSandboxFileAccess ()
- @property (nonatomic, strong) AppSandboxFileAccessPersist *defaultDelegate;
- @end
- @implementation AppSandboxFileAccess
- + (AppSandboxFileAccess *)fileAccess {
- return [[AppSandboxFileAccess alloc] init];
- }
- - (instancetype)init {
- self = [super init];
- if (self) {
- NSString *applicationName = [[NSBundle mainBundle] objectForInfoDictionaryKey:CFBundleDisplayName];
- if (!applicationName) {
- applicationName = [[NSBundle mainBundle] objectForInfoDictionaryKey:CFBundleName];
- }
-
- self.title = NSLocalizedString(@"Allow Access",nil);
- applicationName = [applicationName stringByAppendingString:@" "];
- self.message = [applicationName stringByAppendingString:NSLocalizedString(@"needs to access this path to continue. Click Allow to continue.", nil)];
- self.prompt = NSLocalizedString(@"Allow",nil);
-
-
- self.defaultDelegate = [[AppSandboxFileAccessPersist alloc] init];
- self.bookmarkPersistanceDelegate = _defaultDelegate;
- }
- return self;
- }
- - (NSURL *)askPermissionForURL:(NSURL *)url {
- NSParameterAssert(url);
-
-
- __block NSURL *allowedURL = nil;
-
-
-
- AppSandboxFileAccessOpenSavePanelDelegate *openPanelDelegate = [[AppSandboxFileAccessOpenSavePanelDelegate alloc] initWithFileURL:url];
-
-
- NSFileManager *fileManager = [NSFileManager defaultManager];
- NSString *path = [url path];
- while (path.length > 1) {
- if ([fileManager fileExistsAtPath:path isDirectory:NULL]) {
- break;
- }
- path = [path stringByDeletingLastPathComponent];
- }
- url = [NSURL fileURLWithPath:path];
-
-
- dispatch_block_t displayOpenPanelBlock = ^{
-
- NSOpenPanel *openPanel = [NSOpenPanel openPanel];
- [openPanel setMessage:self.message];
- [openPanel setCanCreateDirectories:NO];
- [openPanel setCanChooseFiles:YES];
- [openPanel setCanChooseDirectories:YES];
- [openPanel setAllowsMultipleSelection:NO];
- [openPanel setPrompt:self.prompt];
- [openPanel setTitle:self.title];
- [openPanel setShowsHiddenFiles:NO];
- [openPanel setExtensionHidden:NO];
- [openPanel setDirectoryURL:url];
- [openPanel setDelegate:openPanelDelegate];
- [[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
- NSInteger openPanelButtonPressed = [openPanel runModal];
- if (openPanelButtonPressed == NSFileHandlingPanelOKButton) {
- allowedURL = [openPanel URL];
- }
- };
- if ([NSThread isMainThread]) {
- displayOpenPanelBlock();
- } else {
- dispatch_sync(dispatch_get_main_queue(), displayOpenPanelBlock);
- }
- return allowedURL;
- }
- - (NSData *)persistPermissionPath:(NSString *)path {
- NSParameterAssert(path);
-
- return [self persistPermissionURL:[NSURL fileURLWithPath:path]];
- }
- - (NSData *)persistPermissionURL:(NSURL *)url {
-
-
- NSParameterAssert(url);
-
-
- NSData *bookmarkData = [url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:NULL];
- if (bookmarkData) {
- [self.bookmarkPersistanceDelegate setBookmarkData:bookmarkData forURL:url];
- }
- return bookmarkData;
- }
- - (BOOL)accessFilePath:(NSString *)path withBlock:(AppSandboxFileAccessBlock)block persistPermission:(BOOL)persist {
-
- return [self accessFilePath:path persistPermission:persist withBlock:block];
- }
- - (BOOL)accessFileURL:(NSURL *)fileURL withBlock:(AppSandboxFileAccessBlock)block persistPermission:(BOOL)persist {
-
- return [self accessFileURL:fileURL persistPermission:persist withBlock:block];
- }
- - (BOOL)accessFilePath:(NSString *)path persistPermission:(BOOL)persist withBlock:(AppSandboxFileAccessBlock)block {
- return [self accessFileURL:[NSURL fileURLWithPath:path] persistPermission:persist withBlock:block];
- }
- - (BOOL)accessFileURL:(NSURL *)fileURL persistPermission:(BOOL)persist withBlock:(AppSandboxFileAccessBlock)block {
- NSParameterAssert(fileURL);
- NSParameterAssert(block);
-
- BOOL success = [self requestAccessPermissionsForFileURL:fileURL persistPermission:persist withBlock:^(NSURL *securityScopedFileURL, NSData *bookmarkData) {
-
- @try {
- [securityScopedFileURL startAccessingSecurityScopedResource];
- block();
- } @finally {
-
- }
- }];
-
- return success;
- }
- - (BOOL)requestAccessPermissionsForFilePath:(NSString *)filePath persistPermission:(BOOL)persist withBlock:(AppSandboxFileSecurityScopeBlock)block {
- NSParameterAssert(filePath);
-
- NSURL *fileURL = [NSURL fileURLWithPath:filePath];
- return [self requestAccessPermissionsForFileURL:fileURL persistPermission:persist withBlock:block];
- }
- - (BOOL)requestAccessPermissionsForFileURL:(NSURL *)fileURL persistPermission:(BOOL)persist withBlock:(AppSandboxFileSecurityScopeBlock)block {
- NSParameterAssert(fileURL);
-
- NSURL *allowedURL = nil;
-
-
- fileURL = [[fileURL URLByStandardizingPath] URLByResolvingSymlinksInPath];
-
-
- NSData *bookmarkData = [self.bookmarkPersistanceDelegate bookmarkDataForURL:fileURL];
- if (bookmarkData) {
-
- BOOL bookmarkDataIsStale;
- allowedURL = [NSURL URLByResolvingBookmarkData:bookmarkData options:NSURLBookmarkResolutionWithSecurityScope|NSURLBookmarkResolutionWithoutUI relativeToURL:nil bookmarkDataIsStale:&bookmarkDataIsStale error:NULL];
-
- if (bookmarkDataIsStale) {
- bookmarkData = nil;
- [self.bookmarkPersistanceDelegate clearBookmarkDataForURL:fileURL];
- if (allowedURL) {
- bookmarkData = [self persistPermissionURL:allowedURL];
- if (!bookmarkData) {
- allowedURL = nil;
- }
- }
- }
- }
-
-
- if (!allowedURL) {
- allowedURL = [self askPermissionForURL:fileURL];
- if (!allowedURL) {
-
- return NO;
- }
- }
-
-
- if (persist && !bookmarkData) {
- bookmarkData = [self persistPermissionURL:allowedURL];
- }
-
- if (block) {
- block(allowedURL, bookmarkData);
- }
-
- return YES;
- }
- - (void)setBookmarkPersistanceDelegate:(NSObject<AppSandboxFileAccessProtocol> *)bookmarkPersistanceDelegate
- {
-
- if (bookmarkPersistanceDelegate == nil) {
- _bookmarkPersistanceDelegate = self.defaultDelegate;
- } else {
- _bookmarkPersistanceDelegate = bookmarkPersistanceDelegate;
- }
- }
- @end
|