Content types understood by an application - objective-c

Given an application path (or NSBundle to an application, etc), is there a way to easily/efficiently determine what content types that application can open?
My initial attempt was to read the application's Info.plist file and extract the content types listed under the kUTExportedTypeDeclarationsKey key. However, there are some flaws with this approach which I haven't been able to work around.
Not all applications use this key. For example, BBEdit does not, but instead lists a whole bunch of recognized file extensions.
UTIs are case-sensitive. Pages, for example, lists com.apple.iWork.Pages.pages as an exported content type, yet no Pages document actually has that type listed in its content type tree. Documents use com.apple.iwork.pages.pages, which is defined by the iWork quicklook generator (at /Library/QuickLook/iWork.qlgenerator).
In know that with some of the LaunchServices functions (LSCopyApplicationURLsForURL(), LSCopyApplicationForMIMEType(), etc), I can get the applications that can open a file (or a file type), but I'd like to do the inverse. (Perhaps I'll have to resort to parsing the output of lsregister -dump?)
Perhaps a simpler way to phrase the question would be: Given an application, what's the easiest way to find all files that it can open?
Any suggestions?

Take a look at LaunchServices and the provided LSCanRefAcceptItem() API.

It seems using the LSItemContentTypes key is the preferred method post-10.4.
Apple: Document-Based Applications

Related

Get file type of given file - based on contents

OK, it may sound fairly straightforward but I'm still not sure how to go about it.
I know it's possible to check file type based on file extensions, using UTIs (e.g. Get the type of a file in Cocoa).
However, I need to be able to get the file type (in more general terms, like "text", "image", "else"), depending on the content.
Is that possible?
Any ideas?
One route forward is to call the file command and parse its output, but that is fairly horrible, and I wouldn't do that as it's slow and you are susceptible to changes in the output.
The file command uses a pretty extensive database of byte patterns to test the contents of the file and I would be tempted to implement my own internal version of it, or use this library (which I think might need some work before it works under OSX).

Can I write to the resource fork using NSDocument?

I'd like to store some additional information along with a document, but I can't use bundles or packages, and I cannot store it inside the document itself.
The application is a text editor, and I'd like it to store code folding and bookmark locations with the document, but obviously this cannot be embedded into the code directly, and I don't want to alter the code with ugly comments.
Can I use NSDocument to store information in the resource fork of a document? If so, how can I do this? Should I directly write to <filename>/..namedfork/rsrc or is there an API available?
First, don't use the resource fork. It's virtually deprecated. Instead, use extended attributes. They can be set programmatically at the BSD level via setxattr and getxattr. Extended attributes are used in many places... for example, in the latest OS X, the resource fork itself is implemented as a special type of extended attributes.
For example, the Cocoa text system automatically adds an extended attribute to a file to specify the encoding.
I thought NSFileManager and NSFileWrapper supported extended attributes since Snow Leopard, but I can't find any documentation :p You can always use the BSD level functions, though.
Does the state need to move with the file if it's copied to another computer? If not, you could do a lot worse than emulating the way Bare Bones handles document state with BBEdit. They store state for all documents in ~/Library/Preferences/com.barebones.bbedit.PreferenceData/Document State.plist.
The resource fork documentation is here. But it contains plenty of suggestions to not use the resource fork.
I have a class on my web site for reading and writing resource forks, which I have never got around to moving to my GitHub repository because, as Yuji points out, they are not really used any more.
I was going to say alias files and web Internet location file are the only places they are used, but I used and tested it on Mac OS X v10.7 (Lion), and they are not even used there any more; they may still be used for custom icons. I didn't test for that exclusively. I will have to see how that affect my NDAlias class on 10.7.
ndresourcefork

Providing an embedded webkit with resources from memory

I'm working on an application that embeds WebKit (via the Gtk bindings). I'm trying to add support for viewing CHM documents (Microsoft's bundled HTML format).
HTML files in such documents have links to images, CSS etc. of the form "/blah.gif" or "/layout.css" and I need to catch these to provide the actual data. I understand how to hook into the "resource-request-starting" signal and one option would be to unpack parts of the document to temporary files and change the uri at this point to point at these files.
What I'd like to do, however, is provide WebKit with the relevant chunk of memory. As far as I can see, you can't do this by catching resource-request-starting, but maybe there's another way to hook in?
An alternative is to base64-encode the image into a data: URI. It's not exactly better than using a temporary file, but it may be simpler to code.

Use ZIP-archives to store NSDocument data

I noticed that Apple started using zip archives to replace document packages (folders appearing as a single file in Finder) in the iWork applications. I'm considering doing the same as I keep getting support emails related to my document packages getting corrupted when copying them to a windows fileserver.
My questions is what would be the best way to do this in a NSDocument-based application?
I guess the easiest way would be to create a directory file wrapper, create an archive of it and return it in NSDocument's
- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError
But I fail to understand how to create a zip archive of the NSFileWrapper.
If you just want to make a zip file your format (ie, "mydoc.myextension" is actually a zip file), there's no convenient, built-in Cocoa mechanism for creating zip archives with code. Take a look at this Google Code project: ziparchive I don't believe a file wrapper will help in that case, though.
Since you cited iWork, I don't own iWork 09, but previous versions use a package format (ie, NSFileWrapper would be ideal) but zip the XML that describes the document's structure, while keeping attachments (like embedded media, images, etc.) in a resource folder, all within the package. I assume they do this because XML can be quite large for large, complicated documents, but compresses very well because it's text. This results in an overall smaller document.
If indeed Apple has moved to making the entire document one big zip archive (which I would find odd), they'd either be extracting necessary resources to a temp folder somewhere or loading the whole thing into memory (a step backward from their package-based approach, IMO). These are considerations you'll need to take into account as well.
You’ll want to take the data from the file wrapper and feed it into something like ziparchive.
Pierre-Olivier Latour has written an extension to NSData that deals with zip compression. You can get it here: http://code.google.com/p/polkit/
I know this is a little late to the party but I thought I'd offer up another link that could help anyone that comes across this post.
Looks like the ZipBrowser sample from Apple would be a good start http://developer.apple.com/library/mac/#samplecode/ZipBrowser/Introduction/Intro.html
HTH

How to decide on document file extension?

I'm writing a new document-based cross-platform chemistry application (Win, Mac, Unix), which saves files in its own format (no standard format exists for this field). I'm trying to decide on a file extension for the saved files. My questions are:
How important is it nowadays to stick to 3 characters?
Where can you check how much this file extension is already used? (Google helps, of course, but it does not tell me how much a given app is popular)
Do I really need to use a file-specific extension? My save format is gzip'ed XML, so I could name it .xml.gz, but I fear it would confuse beginning users (i.e. when you see it, it does not immediately "ring a bell").
Finally, do you have other important guidelines when choosing for your own programs?
PS: I tried to keep the right balance between "giving too little information" and "being too specific to be really useful to others". I'll happily provide more information in comments if the need arises.
FileInfo.com lists a lot of file extensions along with their own estimation of how much it is ued.
I suggest a unique extension (rather then xml.gz) so that the OS can identify the file type to users when looking at a file listing or whatever. 'Ringing a bell' is important, especially if you will have less sophisticated users.
I don't see any need to stick to 3 characters, but I wouldn't go bigger than 5 (I don't suppose I have a real reason for this, other than personal preference).
How important is it nowadays to stick to 3 characters?
It's not unless you have to support older operating systems. All current OSes handle >3 char file extensions without any problems. Think of .html, .config, .resx, and I'm sure there are more.
Where can you check how much this file extension is already used?
check out FileExt.
Do I really need to use a file-specific extension? My save
format is gzip'ed XML, so I could name
it .xml.gz, but I fear it would
confuse beginning users (i.e. when you
see it, it does not immediately "ring
a bell").
Remember that windows (and windows users) associate files with applications by extension, so using something too generic like .xml.gz may cause problems. You are probably better coming up with something that is more specific to your file type or application. Users don't care weather your format is gzipped xml internally, they care about what is in the file. Think about abstraction layers, your users will think of it as a file containing chemistry info not gzipped xml, so .chem is far more appropriate than .xml.gz
Some suggestions of things to thing about:
Obviously, don't clash with anything big - Don't use .doc, .xls, .exe, etc.
Don't clash with anything common in your industry domain that your user demographic is likely to have installed. For example, if you are writing a programming tool, don't use .cs or .cpp. You probably know your domain best, so write a list of all the apps you and your users are likely to have installed, and any of their competitors and avoid them.
Make sure your app includes the options to register and unregister the extension. don't just automatically do it in the installation, make sure it's an option.
Remember unix/linux and Mac are case sensitive, so consider sticking to always all lower case by default.
Remember CD/DVD file naming rules are stricter, so don't use non alpha numeric characters.
Finally, remember that most non-tech users are going to have file extensions turned off, so don't stress about it too much.
There is more info here.
Wikipedia has lists of files extensions here (by type) and here (alphabetical), and also some general information
Depends on the platform, but in general, not very important for newer Operating Systems. Check the documentation for the platforms you're targeting.
I'm not aware of better alternatives to Google. Hopefully someone else has a better suggestion for this one.
Not unless you have some reason to do so. Examples would be "I want to ensure that Windows always opens this program with my app". I'm not sure that your users need to be concerned with the extension anyway. The default configuration on Windows, for example, is to hide extensions for known file types. BUT if you have a compelling reason (such as allowing your program to easily identify files it should be able to handle, for example) then you could use the extension, or you could come up with something else.
I have only ever once written a program where I thought I needed to come up with my own extension. I used my initials. Then later I realized I didn't really need a special extension and reverted to ".xml". However, most extensions seem to be something that seems to mean something. (.doc for documents, etc.) so something meaningful is a good idea if you do need to go this route.
It sure depends on the OSes you want to support, but people have globally moved over the 3-characters extension limit these days: .html is well used for webpages, for example.
Of course, if you go to much longer extensions, people will stop visually recognizing it as a file extension, I think...
Barring your needing to be compatible with a specific OS that you know still has the three-letter limitation, no need to keep it to three characters. It may be useful to have a three-character version of it if you end up supporting those platforms.
The Wikipedia list of file formats is pretty good. Some mime mapping lists will list common extensions associated with those mappings. Ray already mentioned FileInfo.com.
It's a convenience thing; I'd probably go with your own but document the fact that they're just gzipped XML files conforming to a specific DTD and make it easy for users to use .xml.gz instead. Be sure that your software doesn't care about the extension, so that users could even choose their own if they wanted, although I'd tend to avoid encouraging them to by providing a reasonable default.
I'd go for typeability, clarity, uniqueness, and brevity -- in that order. For instance, .config is a lot easier to type than .q2z but it falls down on uniqueness. (I'm not suggesting it for your app; it's an example.) Similarly, .q2z is just a pain. :-) So for instance, .chemstuff is easy to type and probably not in wide use elsewhere. (Again, not a suggestion, just an example.)
Have it as document_name.app_name.xml.gz where document_name and app_name are variables, the latter some easily readable and recognisable short string of your application's title.
Modern systems are quite flexible, and there is absolutely no need to drag the 3-character extensions further along in time with us.
I agree that .xml.gz would confuse users, however keep in mind that modern systems are moving into recognizing files not based on extensions but by probing their headers and even contents instead. In fact, users do not often even see the extensions. For gzipped XML files, a system may decide to first unpack the file stream in memory, then find out it is a literal XML file, then it may take its 'xmlns' as the application identifier. However, such systems are not yet widespread use. In any case, don't make the mistake of only opening files by extension - be smart and raise the bar - do exactly the above to find out if the file can be considered a document for your application.