Macos Security Scoped Url Bookmark for Folder

macOS Security scoped URL bookmark for folder

You're resolving the security-scoped bookmark (for the directory) to let newUrl, but you call startAccessingSecurityScopedResource() on the file's URL fileURL. You need to call it for newURL.

newURL.startAccessingSecurityScopedResource()
// Decompressing fileURL with libarchive...
newURL.stopAccessingSecurityScopedResource()

Two more remarks:

  1. When obtaining access through NSOpenPanel, you don't need to call
    startAccessingSecurityScopedResource() and
    stopAccessingSecurityScopedResource(), because the user explicitly
    granted you access for this session.
  2. I use var isStale: ObjCBool = ObjCBool(false) instead. I'm no Swift expert, so not sure if var isStale = false is ok to use.

Xamarin.Mac Using security-scoped bookmarks

You are confusing some things. Your code

using (var dlg = NSSavePanel.SavePanel)
{
dlg.Message = AppResources.DialogMessageSaveEncryptedFileName;
dlg.AllowedFileTypes = new[] { "zip" };
dlg.Prompt = "Authenticate";

if (dlg.RunModal() > 0)
{
NSError error;
//NSData url = dlg.Url.CreateBookmarkData(NSUrlBookmarkCreationOptions.WithSecurityScope, null, null, out error);
NSData bookmark = dlg.Url.CreateBookmarkData(NSUrlBookmarkCreationOptions.WithSecurityScope, null, null, out error);
}
}

The dlg.Url is the url you want to access.
What you get back from dlg.Url.CreateBookmarkData() is the encoded bookmark data. You can store this data anyway you like to persist it across app launches. For example in UserDefaults
Storing:

NSUserDefaults.StandardUserDefaults["bookmark"] = bookmark; 
NSUserDefaults.StandardUserDefaults.Synchronize();

Later retrieving:

NSData bookmark = NSUserDefaults.StandardUserDefaults.DataForKey("bookmark");

This is the data you
put into NSUrl.FromBookmarkData to get the url back.

//NSData data = new NSData();
//NSUrl url = NSUrl.FromBookmarkData(data, NSUrlBookmarkResolutionOptions.WithSecurityScope, null, out bool isStale, out NSError error);
NSUrl url = NSUrl.FromBookmarkData(bookmark, NSUrlBookmarkResolutionOptions.WithSecurityScope, null, out bool isStale, out NSError error);
url.StartAccessingSecurityScopedResource();

//...

url.StopAccessingSecurityScopedResource();

Also if you need to keep using the access pay attention to the isStale return value from CreateBookmarkData. If it return true you need to refresh the bookmark from the url with url.CreateBookMarkData and replace the stored bookmark with the new one.

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

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).

Security Scoped Bookmark - bookmark resolves but still can't access the file

I just stumbled upon the answer accidentally...

For starters, when I was resolving the URL, I was not using the method which allows you to include OPTIONS, so my URL was resolved WITHOUT the security-scope. My original code to resolve was:

try myURL = URL.init(resolvingBookmarkData: loadedMovieDatabase[0].bookmark, bookmarkDataIsStable: &urlResult)!

When I should have been using the version with options here:

try myURL = URL.init(resolvingBookmarkData: loadedMovieDatabase[0].bookmark, Options: URL.bookmarkResolutionOptions.withSecurityScope, relativeTo: nil, bookmarkDataIsStable: &urlResult)!

Basically, I used the first init option Xcode presented in the predictive list with the words "resolvingBookmarkData:" when I should have looked further down the list. (This is how I found my error.)

NOTE also that it's important to use...

URL.bookmarkResolutionOptions.withSecurityScope

and not

URL.bookmarkCreationOptions.withSecurityScope

...when you're resolving your URL or it doesn't appear to work correctly.

Thus ends my frustration with this problem :) I hope this explanation might help others facing this problem!

Trouble creating Security-Scoped Bookmark

It turns out I was missing a crucial entitlement, not listed in the UI, but listed in the documentation:

com.apple.security.files.bookmarks.app-scope

Update 12/18/2018

According to this Twitter thread, this entitlement may not be required anymore. Thanks @pkamb for alerting me to this.

Security-Scoped Bookmarks for a directory

Your second error message tells you what is wrong - you haven't used a file:// URL.

This can be fixed by creating the URL properly from your path variable, however you will probably be better of sticking with URLs throughout and not doing the URL -> path -> URL transformation. All the operations you've used the path for can be done directly with URLs, just check the documentation for NSFileManager and NSURL. The only one which may be non-obvious is using NSURL's checkResourceIsReachableAndReturnError: rather than NSFileManager's fileExistsAtPath:, however read the documentation for checkResourceIsReachableAndReturnError: carefully and take its advice.

Making these changes should address at least three of the errors you have reported.

HTH



Related Topics



Leave a reply



Submit