Save Data Within Signed App - macos

I am distributing my OS X application on individual USBs and, for this reason, everything must be self contained.
The app itself lets users input information and then saves this information to an existing text file (specifically an ObjectDB database). Herein is my problem.
I'd like to keep this text file inside the app itself (i.e. inside the Content folder) so it's out of the way and can't be deleted by the average user. But once the app is signed, it seems the text file can't be altered with any new information without getting flagged by Gatekeeper. Is this really the case? There's no way to store data files within apps now?
I'd appreciate any suggestions. Thanks.

Yes, you are correct. If you modify the application package, the signed package is no longer valid. That's kind of the purpose of signing a package.
Your options are to store the text file in a temporary folder on the user's computer, or to instruct your users to disable gatekeeper (don't do this).

Related

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 can I associate a file with my app?

I have a Cocoa app "PDFHistory" on Mac OS X that uses the NSDocument architecture to save and load PDF files that are internally formatted specially for my app. I want to make it so whenever I save a file (e.g., "mydoc.pdf") from PDFHistory, then subsequently double-clicking on mydoc.pdf will automatically open it in PDFHistory.app. However, I don't want to make it so all .pdf files are automatically opened in PDFHistory, but rather use the system default (probably Preview.app). The .pdf suffix is a requirement, though, since I need the user to be able to e-mail the files to other users who can view the file in their default PDF viewer.
The problem is that if I set the LSHandlerRank to "Owner", then all .pdf files will be opened with PDFHistory, which is bad (since I only understand the internals of the .pdf file that PDFHistory wrote out). But if I set LSHandlerRank to "Alternate", then all .pdf files will be opened to the system default app (Preview.app), which is confusing for the user who had just created the file using my app.
Once upon a time, "creator codes" could be used to implement this sort of capability, but launch services started ignoring them back in Snow Leopard (see http://tidbits.com/article/10537). UTIs are not a substitute that provide this capability (see http://boredzo.org/blog/archives/2009-09-22/how-not-to-use-utis).
Using Finder to get info on the file allows the user to specify a specific app to use to open the specific file. This supposedly works by setting a "usro" property in a the file's resource. There is some open-source code to mimic this behavior (https://github.com/AlanQuatermain/SetAppAffinity), but is uses deprecated functions, and so would cause Apple to reject the app from the App Store. Similarly, people have posted AppleScript to set this property (https://discussions.apple.com/thread/2597365), but sandboxing would prevent me from invoking it.
Although the .pdf suffix is a requirement in order to be able to send the files to users on other systems/platforms, I considered trying to have the suffix registered with two extensions as ".phistory.pdf", which would allow "file.phistory.pdf" to be opened in PDFHistory, but "file.pdf" would be opened in the default PDF viewer. However, this simply didn't work: it appears that the final suffix is the only one used by launch services, and everything before that is ignored.
So is there any way to have my app be the default app for opening files that it created itself?

I need info on using NSUserDefaults in Xcode

I came across this information in the posting of a question I found on here:
"Apple has added an extra rule for apps being submitted to the app store.
We can no longer store arbitrary data files in the Documents folder. Only content generated by the user like a text file they manually typed and saved or a photo they took with the camera can be saved in the Documents folder.
We are now expected to store our app generated files in the Library/Cache folder instead of the Documents folder. In addition, we should mark the files we don't want to be sync to iCloud with the skip backup attribute.
Failure to comply with this will result in an app being rejected by Apple.
Reason: The Documents folder is now used for syncing to iCloud. iCloud does a sync every few minutes and if we were to have megabytes of our app generated files stored in the Documents folder, it would get mixed up with the user's own iCloud synced files."
This makes me wonder if the way I have used NSUserDefaults in my app is "legal" in the eyes of apple.
I'm making a simple app that takes user input in about five different places. I'm saving these simple strings in NSUserDefault variables.
My question to anyone that fully understands the statements made within the quotes above is:
Am I saving data in a way that is no longer allowed by apple?
I'm new to the development game, and the information within quotes doesn't make it clear to me (in the context of my app's situation) whether I'm in the wrong or not.
Thanks for the help!
NSUserDefault is the official, supported way of storing user preferences. If that's what you're storing, then it's the correct way to do it.

Where is the correct place to store a Mac application's database?

I'm building an application that I hope to submit to the Mac App Store. The app has an SQL database that stores all of the items that the user has created.
Does anyone know where I should be storing this to comply with Apple's guidelines? Should it go in Application Support, the Documents folder, the Library or somewhere else??
Generally, you shouldn't automatically create file in the user home directory, except in ~/Library/Application Support/<Application>. So either let the user choose where to store the information (if it is document centric), or store it in Application Support.
See the question: What location do OSX/Cocoa applications generally use to store data files?

AquaticPrime "Regular" License?

I am looking at using AquaticPrime for my key generator for a Cocoa shareware app. For those of you who don't know about it, you can check it out here: http://aquaticmac.com/. However, I am running into a problem when I attempt to implement it. I don't want my users to have to copy and paste a whole dictionary into my app (or select it from a file browser), I just want them to have some code like: 1111-1111-1111-1111-1111 that will unlock the app for them. Is there some way to do this in AquaticPrime? But assuming that it can't, is there some other framework that does do this or would I just have to hard code it?
The reason it uses license files is to make it cryptographically hard to make up licenses—you can't just write a keygen like you can with license numbers.
You can make this easy by making a custom file type for license files in your application's Info.plist. (This must be app-specific. When you begin your second product, you'll need to make a new type.) This type will have a custom, app-specific filename extension with it.
Then, when the user double-clicks on the license file (possibly in Mail), the OS will open it with your app. You'll handle this, probably in your app delegate, by feeding the license file to AquaticPrime to validate.
This way, the user does not even have to summon a dialog box, copy the license number, and paste it. All they have to do is double-click on the license file.
Thus, the license file makes it easier to register your application, not harder.
If you have a trial version of your application that is unlocked then you can do the following.
1) Create a custom url scheme.
Follow the instructions on this posting but instead of http and https make your application respond to something like activate-com-mycompany-myproduct.
Once the user has run your application once any link in a browser like activate-com-mycompany-myproduct://somedata will automatically open your application.
2) Provide a product activation link in your final buy page of your web store and your email receipt. To make it simple for the user and not for you, append a unique id to the URL. Map the ID in a database, generate a license plist on the fly and push it to the user seamlessly.
In case someone else stumbles on this question: you might also want to take a look at CocoaFob. The keys it generates are rather long, but closer to the format you were after and still easy enough to cut and paste.

Resources