Re: Security scoped bookmarks example?

2020-03-05 Thread Gabriel Zachmann via Cocoa-dev
> 
> So, you created a security scoped bookmark, then what did you do with it? You 
> should store it in user defaults, then load it from user defaults the next 
> time your code starts up, reconstitute it back into a security scoped URL, 
> and then use *that* URL (literally that object, not a different instance 
> based on the same path) as the base URL for all the image file URLs you need.

Argh, now that you explained it, it makes sense to me! Thank you so much!

Best regards, Gabriel


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Security scoped bookmarks example?

2020-03-04 Thread Quincey Morris via Cocoa-dev
On Mar 4, 2020, at 06:12 , Gabriel Zachmann via Cocoa-dev 
 wrote:
> 
>// load new image from disk
>NSURL * url = [NSURL fileURLWithPath: [self absolutePathFor: filename_] 
> isDirectory: NO];  
>// filename_ is one of the paths from the list of images under the user 
> selected directory
>// at this point, url is a proper URL, I have checked
> 
>[url startAccessingSecurityScopedResource];
>CGImageSourceRef sourceRef = CGImageSourceCreateWithURL( (CFURLRef) url, 
> NULL );

This isn’t even nearly correct. You *must* call 
“startAccessingSecurityScopedResource” on a URL that was reconstituted from a 
security scoped bookmark. According to this, you called it on a URL that you 
arbitrarily created. Why would you even expect that to work? If it did, then 
you could access any file without user permission, and security scoped URLs 
would have no purpose.

> I create the SSB like this:
> 
>directoryBookmark_ = [dir bookmarkDataWithOptions: 
> NSURLBookmarkCreationWithSecurityScope | 
> NSURLBookmarkCreationSecurityScopeAllowOnlyReadAccess
>   includingResourceValuesForKeys: nil
>relativeToURL: nil
>error: ];

So, you created a security scoped bookmark, then what did you do with it? You 
should store it in user defaults, then load it from user defaults the next time 
your code starts up, reconstitute it back into a security scoped URL, and then 
use *that* URL (literally that object, not a different instance based on the 
same path) as the base URL for all the image file URLs you need.

Note that you don’t need the bookmark to be reconstituted while your code is 
still running after using the open panel, because the URL that the open panel 
returns is *already* a security scoped URL in the current process. You only 
need to use the bookmark if your code starts up again in a new process.

Note also that you must not *re*-create the bookmark from a reconstituted URL. 
That doesn’t work. You must create the security scoped bookmark *only* from the 
fresh URL that the open panel gives you. Store it once, then keep 
reconstituting it as needed.
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Security scoped bookmarks example?

2020-03-04 Thread Gabriel Zachmann via Cocoa-dev
I am still having problems in my screensaver to access files that are stored on 
an external disk.
The disk is just a simple hard disk connected to my Macbook via USB.
(It is an important use case, since a lot of people like to keep there huge 
image collections on external hard disks.)

I can access the files just fine in Finder.
My screensaver can also access them during the first run, when the users points 
it to the directory (i.e., while it is running in preview mode in System 
Preferences).
However, next time it gets invoked it cannot access them any more, although I 
am using security-scoped bookmarks (SSB).
Details follow. Code excerpts below.

The first time the screensaver runs, the user points it to a specific directory 
via System Preferences / Screen Saver Options.
I get the directory from an NSOpenPanel, and store this as a SSB in the user 
preferences.
Also, I create a list of all image files in the directory, and sub-directories, 
using Spotlight.
I store that as well in the user preferences.
In the next invocation (where it runs as a plugin of legacyScreenSaver),
I get the SSB, resolve it, load the list of images files (basically a list of 
paths),
and try to display them.

Problem is that loading the image fails.

Here is the relevant code excerpt from the function -animateOneFrame:


// load new image from disk
NSURL * url = [NSURL fileURLWithPath: [self absolutePathFor: filename_] 
isDirectory: NO];  
// filename_ is one of the paths from the list of images under the user 
selected directory
// at this point, url is a proper URL, I have checked

[url startAccessingSecurityScopedResource];
CGImageSourceRef sourceRef = CGImageSourceCreateWithURL( (CFURLRef) url, 
NULL );
// sourceRef is not NULL, I checked
CGImageSourceStatus imgstatus = CGImageSourceGetStatus( sourceRef );
if ( imgstatus != kCGImageStatusComplete )
// this happens with each and every file on an external disk!
.. log imgstatus ..
[url stopAccessingSecurityScopedResource];
return;
}


Loading the image with NSImage like this:

[url startAccessingSecurityScopedResource];
NSImage * image = [[NSImage alloc] initWithContentsOfURL: url];

also fails, I always get NULL.


I also tried this (thanks, Steve!):

NSError * error;
NSFileHandle * fileHandle = [NSFileHandle fileHandleForReadingFromURL: url 
error: & error];
if ( ! fileHandle )
{
[self logMessage: [NSString stringWithFormat: @"Complete path: %@ , 
%@",  [url path], error]
 asError: YES];
[url stopAccessingSecurityScopedResource];
return;
}


Interestingly, I get this error message:

Complete path: /Volumes/cgvr/test2/backs_detail.jpg , Error 
Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file 
“backs_detail.jpg” in the folder “test2”." 
UserInfo={NSFilePath=/Volumes/cgvr/test2/backs_detail.jpg, 
NSUnderlyingError=0x62c56c70 {Error Domain=NSPOSIXErrorDomain Code=1 
"Operation not permitted"}}

It talks about "saving" even though I used fileHandleForReadingFromURL :-(


I create the SSB like this:

directoryBookmark_ = [dir bookmarkDataWithOptions: 
NSURLBookmarkCreationWithSecurityScope | 
NSURLBookmarkCreationSecurityScopeAllowOnlyReadAccess
   includingResourceValuesForKeys: nil
relativeToURL: nil
error: ];

I tried it also *without* the 
NSURLBookmarkCreationSecurityScopeAllowOnlyReadAccess,
but there was no difference in the error message.

legacyScreenSaver (the screen saver engine invoking my screen saver) has this 
entitlement:


com.apple.security.temporary-exception.files.absolute-path.read-only

/


It also has the entitlement  com.apple.security.files.user-selected.read-only .

Is the problem that the files I am trying to read are outside / ?
But I thought, I can read all files in folders for which I am getting a 
bookmark via openPanel? (no matter which directory they are ..)


If you want, you can find the complete source code here:

   https://owncloud.informatik.uni-bremen.de/index.php/s/H7wHqwdgwYwqwy9 



I should mention that everything works fine when the folder of images is in my 
home
(which is, of course, on my local disk).


I will appreciate all kinds of hints and pointers very much.

Confused, Gabriel.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com