Distinguish things like .app/.xcodeproj and actual folders in Cocoa - macos

I am trying to build an alternative file manager that works similar to the default Finder in Cocoa.
As you can imagine, the app needs to show a list of files/subfolders in certain directory, and when the user click on an item, it checks whether it's a folder or a file that a user has clicked. If it's a folder, the app simply shows the content of the folder. If it's a file, it will be opened with the default application.
I used NSFileManager.file​Exists(at​Path:​is​Directory:​) to determine if an item at certain path is a folder. This works well in most cases, but for things like something.app or project.xcodeproj, they are also considered as directories according to the method.
I know it's true that technically they are just folders, but is there a way in Cocoa to distinguish them from actual folders?

Use (NS)URL.
Get the values for resource keys isDirectoryKey and isPackageKey via resourceValues(forKeys.
In case of bundles isPackage is true.

Related

How to Trash items that are not owned by the current user, the same way the Finder does?

I am writing a tool that offers the option to trash selected items (files, folders). Usually, I'd call -[NSFileManager trashItemAtURL:...] for each of those items, as it's also explained in this and in this SO question.
However, these do not work when trying to delete files from a directory owned by a different user, such as root. My tool shall offer the same option as the Finder in this case, i.e. ask the user to authorize the operation by providing the credentials of an Admin user, and then my app would move the items to the Trash like the Finder does.
I've tried solving this by using a privileged helper, as outline by the EvenBetterAuthorizationSample example code, using launchd, SMJobBless and XPC Services.
The problem with that is, however, that the privileged helper runs as the root user, without knowledge of the current user my app runs under. The result is that, when it trashes a file, it ends up in the root user's Trash folder and not, as the Finder would do it, in the user's Trash folder.
How do I solve this, i.e. how do I move items not owned by the user to the current user's trash instead of the root user's Trash?
Is there some trick I can use that would let me keep using one of the existing trash oder recycle functions?
Doing the move myself is not going to work properly because for Put Back to work, the Trash's .DS_Store file would need to be updated, and there's no API for that, AFAIK.
I have almost found a solution:
Analysis
When the helper is run, e.g. from launchd, or via AuthorizationExecuteWithPrivileges (under macOS 10.15), it may be running as root, with no knowledge of the logged-in user, hence it cannot determine the user's Trash folder.
Oddly, the Environment variables (see man env) may even show the current user's name and home dir, yet the real user id, which one can query with getuid(), will return 0 (root), which also results in NSUserName()and NSHomeDirectory() returning the root user's information. And it appears that trashItemAtURL and related functions rely on NSHomeDirectory() to determine the Trash folder location.
Half-working solution
Fortunately, there is a way to change the real user id, with setreuid.
Therefore, in my testing, when I call setreuid (501, 0) (501 being the uid of the currently logged-in user), then trashItemAtURL does move the file to the user's Trash folder, indeed, along with automatic renaming where necessary.
However, this does not make the Put Back work, the way it would when trashing the same file using the Finder.
Making Put Back work
Looks like the reason for Put Back not working comes from a deeper issue: It appears to be a long-standing bug in the macOS framework, see this bug report.
Which basically means: This is the best we can get out of it until Apple fixes the underlying bug.
The only working alternative to make Put Back work is to ask the Finder to trash the items using AppleEvents / AppleScript.

Can an app-scoped security scoped bookmark be copied from one Mac to another?

I have a sandboxed application that uses a document format which can contain embedded filenames. E.g. some of these referenced files are for image files which the user selects in order to associate the image file with data stored in the document. Whilst such images will sometimes be located in the users pictures folder, sometimes they are elsewhere. The document format itself cannot be changed for portability reasons (it is shared with an existing Windows version of the app).
In order for the app to be able to access the files whose names are embedded within the document, when the user selects a filename (using nsopenpanel) to be stored in the document like this, the app also creates an app-scoped security scoped bookmark for each such stored filename. It then stores these bookmarks by serialising them to another file. When the app runs again it loads its previously serialised bookmarks and uses them when accessing the 'embedded' filename and that works fine.
But when I copy such a document (and its associated serialised bookmarks file) from one Mac to another, it doesnt work, even though all the files the bookmarks refer to are known to exist on both Macs. What happens is that whilst the app opens the document file ok (after the user selected it with an nsopenpanel), and successfully reads in the serialised bookmarks from its associated serialised bookmarks file (which again the user has selected using nsopenpanel), and even though the exact same filenames that the bookmarks refer to are known to exist on the other Mac (and can be accessed by the user through finder etc), the sandboxed app still cannot access them. Resolving the bookmarks seems to fail.
The question is: are app-scoped bookmarks restricted to only working on the Mac on which they were created? If I cannot move an app-scoped bookmark from one system to another, how else can I achieve the effect I want without forcing the user to have to manually re-select every such 'embedded' filename with an nsopenpanel?
Tried to find the answer to this question in the Apple docs without success.
I take it it goes without saying that security-scoped bookmarks can only be used by the app that creates them.
No, because if this were possible, developers could save security-scoped bookmarks to sensitive files/directories on their own computers and then deploy their apps and have access to those same sensitive files/directories on other peoples' computers.

How do I link directly to an alias through afp?

I'm working on an intranet web application with a file sharing server set up using AFP.
My goal is to create a link on the page that will open up Finder to a specific folder on the share network, but it has to go through an alias. I think it'd be easier to explain with an example.
For this share, there is a folder called Objects that contains a bunch of folders with unpredictable names, and a folder called Alias that contains a bunch of aliases to folders in Objects. So a link to afp://server/share/Alias/obj1 should open the folder at afp://server/share/Objects/unpredictableName, where obj1 is an alias pointing to unpredicableName.
On OSX 10.8 this works as expected, however on 10.9 and later that link opens the Finder at the Alias folder, instead of actually going into unpredictableName. What changed, and is there any way to restore the previous behavior? Thanks.

How do I set the default location?

When I go to upload a file with Uploadify, it automatically opens the directory
C:\Program Files (x86)\Google\Chrome\Application\33.0.1750.117
And of course nobody stores any files there. This seems like a bad place for the user to start.
What do I need to do to change which directory uploadify opens by default?
The location that this defaults to is browser-dependent, and as far as I can tell, there is no way of setting a preferred working directory.
Also, it would be very difficult to guess which directory you would want to start it, considering that you may get a user with any of a number platforms.
From http://www.irt.org/script/1154.htm:
Because of security implications (scripts setting the value, and then attempting to retrieve files of your computer) the value of the fileupload form field is read only. Therefore you cannot set, or reset the value.

"Virtual Files" in OSX Finder that only appear when my Application runs, possible?

is there a way to "hook" into the OSX Finder to perform the following:
When my Application starts, the User sees a Folder in his Finder which is created by my application. Inside this Folder the User sees Files from several Folders...a unified view to several Files in several Folders that the User specified in my Application.
So, in this "Unified Folder" are not the real Files, they are still in there original Folder but the User sees them in this one Folder as if there were all his real Files in this new Folder. So there is no copying or moving involved.
To be honest, I've no Idea if it's possible and what I should looking for inside the Cocoa SDK. Maybe there is an API for the Finder itself or some other way?!
Regards
twickl
First option is your application could create aliases to the original files. The Finder will show these with a small arrow "badge" over the icon, so it is clear they are not the original files but aliases of them.
If you don't like the badges on the icons creating hard links may give you what you want.
Mac OS X presents a view of the HFS+ (Mac) filesystem which matches the UFS (Unix) one and you have access to hard and symbolic links. The latter are treated by the Finder similar to aliases but the former are indistinguishable from the original files as they are the original files - under the Unix filesystem a file in a directory is just a reference (the inode number) to the real file, each entry in a directory is just a hard link to the actual file, and a file can have any number of hard links to it (a file is deleted when the link count drops to 0, think of the retain/release model if that helps).
At the Cocoa level NSFileManager has methods to create hard links, or you can use the Unix level link(2) function.

Resources