Search code examples
cocoasandboxappstore-sandbox

Creating a security scope bookmark for a file from one of a directory containing it


I have a security scope bookmark for a directory, provided by a user via an openDialog request.

I'm trying to create another security scope bookmark for a file inside this directory:

NSURL *musicFolder = /* Secured URL Resolved from a NSData, bookmark not stale */;

if (![musicFolder startAccessingSecurityScopedResource]) {
    NSLog(@"Error accessing bookmark.");
}

NSString *file = @"myfile.txt"; /* This file exists inside the directory */
NSURL *pathURL = [musicFolder URLByAppendingPathComponent:file];

NSError *systemError;
NSData *bookmarkData = [pathURL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
                         includingResourceValuesForKeys:nil
                                          relativeToURL:nil
                                                  error:&systemError];

[musicFolder stopAccessingSecurityScopedResource];

if (!bookmarkData) {
    NSLog(@"%@", systemError);
}

Both bookmarkData and systemError end up nil which is not very useful...

Is this even supported or can you only get valid secured scope bookmarks from the system?


Solution

  • In my test program this works fine. I suspect the append of the file name to the URL is failing in your case (but that's a huge guess) because it's the only thing that seems materially different.

    I notice that the url for a security resolved location is: file://localhost/Users/dad/Desktop/TestFolder?applesecurityscope=343335323030663066393432306234363030346263613464636464643130663635353065373030373b30303030303030303b303030303030303030303030303032303b636f6d2e6170706c652e6170702d73616e64626f782e726561642d77726974653b30303030303030313b30313030303030323b303030303030303030326461363838663b2f75736572732f74796c65722f6465736b746f702f74657374666f6c646572

    which is the other reason I wonder if the append is the issue.

    In my test I have the user choose the folder, create the security scoped bookmark and then save that in user defaults.

    Then I quit & relaunch the app and via a menu command I get that bookmark and then resolve it. Then I added a case where I use the resolved bookmark to a folder and make a new bookmark to the file within the folder.

    It seems to work fine.


    In my test where it's working I'm getting the path to the file like this:

    NSURL * resolvedURL = [NSURL URLByResolvingBookmarkData: data
                            options: NSURLBookmarkResolutionWithSecurityScope
                            relativeToURL: nil
                            bookmarkDataIsStale: &isStale
                            error: &error];
    ... // (error checking)
    
    [resolvedURL startAccessingSecurityScopedResource];
    
    NSArray * files = [[NSFileManager defaultManager] 
                         contentsOfDirectoryAtURL: resolvedURL
                         includingPropertiesForKeys: @[NSURLLocalizedNameKey, NSURLCreationDateKey]
                         options:  NSDirectoryEnumerationSkipsHiddenFiles
                         error: &error];
    if ( files != nil )
    {
        NSURL * fileURL = [files objectAtIndex: 0]; // hard coded for my quick test
        NSData * newData = [fileURL bookmarkDataWithOptions: NSURLBookmarkCreationWithSecurityScope
                              includingResourceValuesForKeys: nil
                              relativeToURL: nil
                              error: &error];
    
       if ( newData != nil )
       {
           NSLog(@"it's good!");
       }
       .... // error checking and logging.
    

    if that doesn't get you on the right track, I'm going to need to see more code (you'll probably need to make a simple example).

    Note that in my case I'm resolving the bookmark and calling startAccessingSecurityScopedResource even when I just got the url & created the bookmark (when I tried to create a bookmark from the path I'd just acquired from PowerBox (openPanel) it failed with an error 256).

    Some configuration details: OS X 10.8.4, Xcode 5 (first public release from today 9/18/2013).