« Installing Cacti on Mac OS X 10.5 Server | Main | Oh Cthulu, here we go »

UTI's don't work if you don't set them correctly [UPDATES]

So, the latest brou-ha-ha over Mac OS X 10.6 is APPLE HAS ABANDONED CREATOR CODES AND NOW YOU CAN'T ASSIGN DOCUMENTS TO OPEN IN THEIR CREATING APPLICATION AND OMG STEVE JUST ROBBED MY HOUSE!

UPDATES AT BOTTOM

Okay, the last bit, about Steve robbing the house is hyperbole, but, the general tone of what I'm reading is pretty much nailed there. Daring Fireball, rosscarter.com, and (the most sober of the bunch), TidBITS have all gotten on the "Apple has abandoned creator codes, now we're screwed, damn you Apple" bandwagon. They're all right about one thing: Apple has dumped creator codes in Snow.

So before you panic, there's a replacement mechanism, the UTI, or Universal Type Identifier. (Is it just me or does Apple consistently come up with some bad acronyms. The acronym for AppleScript Studio. UTI. Seriously bad acronyms here.) The idea here is that instead of a cryptic 4-character code, (Seriously, "8BIM". "WDBN". There's nothing intuitive about that), you instead use a plist-style convention. So, say I create a CSS file in Coda. Of course, Coda will give it a .css file extension, but that's not going to bind that CSS file to Coda in and of itself. Instead, it's going to bind it to whatever the default application for .css files are on my system. On my Mac, the default for .css files is BBEdit. So sans creator codes, if all the OS has to go on are file extensions, unless I specifically change the default, .css files will open in BBEdit.

That's not broken mind you, that's just how it works when all you have is a file extension. Now, with a creator code, (in this case, Coda's is "TStu". See, how could you not just know that stands for Coda?), this is easy. Coda attaches that creator code to the file, and even though the default is BBEdit, it opens in Coda.

Since I'm on Snow, that won't work. So there's a third option, the UTI. Ideally, Coda should assign an application-specific UTI for CSS files it creates. As it turns out, Coda is a UTI-aware application, and according to Coda's info.plist file, that identifier is com.panic.coda.css. More verbose than a creator code, but infinitely more readable and useful.

So what's happening in Snow? Why is all of this failing? Why did Apple screw us all over.

Well, as it turns out, it's not all Apple. It's partially Apple, but not all Apple.

As a test, I mimic'd what Ross Carter did and created some files. A .txt in BBEdit, a .html in Coda, .css in Coda and a .PNG in Photoshop. So we have a good mix of old and new, Carbon and Cocoa.

.txt opened in BBEdit.
.html opened in Safari.
.css opened in BBEdit
.png opened in preview

Ross's experiment replicated nicely on a different machine with different applications. Looking at the settings for my OS in RCDefaultApp, this is as expected for the extension.

But what about the UTI?

Hm...okay, let's look at those. A bit of AppleScript to pull the type identifier for the file:

set theFile to choose file

tell application "System Events"
     set theProps to properties of theFile
end tell

So let's take a look at the file properties for those four files, according to System Events. (Keep in mind, I'm assuming that what SE is showing me is the truth. If it's showing bad info, then all my conclusions are bad as well.)

BBEdit Text File props:

class:alias,
short version:"",
container:folder "Habu:Users:jwelch:Desktop:UTI Test:" of application "System Events",
path:"Habu:Users:jwelch:Desktop:UTI Test:test.txt",
file type:"TEXT",
volume:"Habu",
physical size:4096,
URL:"file://localhost/Users/jwelch/Desktop/UTI%20Test/test.txt",
id:"test.txt,-100,200367325",
displayed name:"test.txt",
busy status:false,
kind:"BBEdit text document",
creator type:"R*ch",
version:"",
name extension:"txt",
POSIX path:"/Users/jwelch/Desktop/UTI Test/test.txt",
name:"test.txt",
modification date:date "Monday, September 21, 2009 12:40:09 PM",
size:20,
type identifier:"com.apple.traditional-mac-plain-text",
package folder:false,
stationery:false,
creation date:date "Monday, September 21, 2009 12:40:09 PM",
visible:true,
product version:""

Coda HTML file props

class:alias,
short version:"",
container:folder "Habu:Users:jwelch:Desktop:UTI Test:" of application "System Events",
path:"Habu:Users:jwelch:Desktop:UTI Test:test.html",
file type:"TEXT",
volume:"Habu",
physical size:20480,
URL:"file://localhost/Users/jwelch/Desktop/UTI%20Test/test.html",
id:"test.html,-100,200367398",
displayed name:"test.html",
busy status:false,
kind:"HTML document",
creator type:"TStu",
version:"",
name extension:"html",
POSIX path:"/Users/jwelch/Desktop/UTI Test/test.html",
name:"test.html",
modification date:date "Monday, September 21, 2009 12:42:34 PM",
size:18832,
type identifier:"com.apple.traditional-mac-plain-text",
package folder:false,
stationery:false,
creation date:date "Monday, September 21, 2009 12:42:34 PM",
visible:true,
product version:""

Coda CSS file props:

class:alias,
short version:"",
container:folder "Habu:Users:jwelch:Desktop:UTI Test:" of application "System Events",
path:"Habu:Users:jwelch:Desktop:UTI Test:test.css",
file type:"TEXT",
volume:"Habu",
physical size:4096,
URL:"file://localhost/Users/jwelch/Desktop/UTI%20Test/test.css",
id:"test.css,-100,200367430",
displayed name:"test.css",
busy status:false,
kind:"BBEdit text document",
creator type:"TStu",
version:"",
name extension:"css",
POSIX path:"/Users/jwelch/Desktop/UTI Test/test.css",
name:"test.css",
modification date:date "Monday, September 21, 2009 12:43:58 PM",
size:100,
type identifier:"com.apple.traditional-mac-plain-text",
package folder:false,
stationery:false,
creation date:date "Monday, September 21, 2009 12:43:58 PM",
visible:true,
product version:""

Photoshop PNG file

class:alias,
short version:"",
container:folder "Habu:Users:jwelch:Desktop:UTI Test:" of application "System Events",
path:"Habu:Users:jwelch:Desktop:UTI Test:test.png",
file type:"PNGf",
volume:"Habu",
physical size:1490944,
URL:"file://localhost/Users/jwelch/Desktop/UTI%20Test/test.png",
id:"test.png,-100,200367506",
displayed name:"test.png",
busy status:false,
kind:"Portable Network Graphics image",
creator type:"8BIM",
version:"",
name extension:"png",
POSIX path:"/Users/jwelch/Desktop/UTI Test/test.png",
name:"test.png",
modification date:date "Monday, September 21, 2009 12:46:45 PM",
size:1489781,
type identifier:"public.png",
package folder:false,
stationery:false,
creation date:date "Monday, September 21, 2009 12:46:29 PM",
visible:true,
product version:""

So now we see a problem. All the text-ish files have the same type identifier: com.apple.traditional-mac-plain-text. The Photoshop PNG file is typed as public.png. For all three text-based files, they all have the same file type, "TEXT", they all have the same UTI, com.apple.traditional-mac-plain-text. The only two things the OS has going for it are the extensions and the creator code. If you take away the creator code, you're screwed, because all you have are the extensions.

While I agree that this is frustrating, why aren't any of these applications doing the right things? Pages '09 does. It sets the type for .pages files to "com.apple.iwork.pages.pages". Unsurprisingly, it doesn't even have a creator code. There are only two bits of data to work with, the UTI and the file extension. In fact, playing around a bit, I found that in general, Mac OS X pays attention to the UTI rather nicely. For example, when I export an OmniOutliner file as HTML, the UTI is set to "public.html" and on my machine, the default for that was Safari. Even thought the default for the .html extension is BBEdit, the UTI overrode that. When I changed the handler for public.html to BBEdit, then the file opened in BBEdit. That's exactly the behavior I'd expect, and it matches what you got with Creator Codes.

However, there's more to the algorithm than that, as the handler for "com.apple.traditional-mac-plain-text" is BBEdit, yet the HTML file opened in Safari, which was the handler for .html. Clearly there's some subtleties to the UTI-extension interaction that need to be better documented. (Gee, there's a shock, Apple's documentation not complete.)

Thus far, the issues here are many. Yes, Apple did abruptly kill off Creator Codes, however, they've been warning about that for some time now. UTIs are the future, go there. Out of the three applications I used to create the files, only one, Coda, even has UTI support in its info.plist file. Neither BBEdit 9.2.1 nor Photoshop CS4 even hint at them. According to RCDefaultApp, which lists all the UTIs registered on my system, the only Bare Bones application with UTI support, out of the three on my Mac, is Yojimbo. Adobe only supports UTIs for EPS, Flash, Illustrator, PDF, native Photoshop, a few different kinds of postscript listings and RAW. So out of all of them, only Coda even had a chance to use UTIs for its files, and even though it supports UTIs for .css files, it doesn't set them correctly. If it had, the type identifier for that CSS file should have been "com.panic.coda.css". Now, I know that 'simple' is a big fat lie when it comes to application development, however, at some point during the 10.5 lifecycle, all these applications should have been updated to not only support UTIs, but to use them. Instead, they all relied overmuch on FIle Types/Creator Codes, and now that those are gone, well, the OS does what it can with the information it has available.

As we see by the examples I cited, when the information is properly used, the OS tends to do the right thing. But you have to at least try here folks. Computers suck at guessing, and without a UTI, that's what you get: a computer's best guess.

So it's clearly not Apple's fault? Welllllll...no, that's not completely correct.

What happens if you delete the extension? What should happen is nothing. The UTI should remain, and the file should open correctly. What actually happens is quite a bit different, it all sucks, and this suckage is Apple's fault. For example, what happens when you delete the file extension on a Pages '09 file? Well, the UTI changes to "dyn.age8u", and the default application in the "Get Info" changes to TextEdit, but when you double-click the file, it gets passed to Archive Utility. That makes sense in one small way, as Pages '09 files are technically zipfiles. But that's really stupid, because the file hasn't changed, just some user-modifiable metadata. If you remove the .oo3 extension from an OmniOutliner file, the OS or the Finder, (not sure which here, and I admit, I don't really care), decides that because it's a bundle file, (a folder masquerading as a single file), that in spite of the fact that the UTI clearly indicates what file it is, if you remove the extension, obviously you wanted it to become a folder again. That's stupid on a really, really stupid level. It wraps back around and laps itself, that's how stupid this is. What should happen, from the human perspective, is...nothing. The UTI wasn't changed, just the file extension, and in this case, that is not the user indicating they want to radically change how the file is opened. The only exception is where there is no UTI information for the file. In that case the user should get the "Hey, you're removing the extension, and weird stuff might happen if you do" dialog.

If the user changes the extension to something else, and that new extension is not one the current default application can handle then what should happen is a dialog that says "Hey, you're changing the extension to one that <current default application> doesn't handle. Do you want this to be opened in <new default application> instead?" That at least warns the user in a case where a warning makes sense, because they're taking an action that normally indicates they want to change what opens the file.

So in this case, there's plenty of fault to go around. Applications have to start supporting and correctly using UTI information. Apple has to fix the OS so that removing and/or modifying extensions is handled correctly by deferring to the UTI whenever possible, and Apple really has to better document UTI interaction. (Even if they make existing documentation easier to find. Hard to find docs help no one.)

Oh, and what about when you change a file association in the Finder? Well, unsurprisingly, the Finder cheats. It adds a resource fork to the file with the path to the desired application coded within. Along with better handling of filename extension vs. UTI issues, maybe the Finder could start doing the right thing too?

UPDATE

It turns out that I was the victim of an erroneous, albeit understandable assumption, namely that Apple allows you to set the UTI for a file. You can't. What you have to do is declare a UTI that corresponds to the extension/mime type/OStype of the file.

So basically, the only way, from what I can tell, based on the info I'm getting to 'set' a file's opening application in Snow is:

  1. Create a unique extension for every file your application normally creates, using 'standard' extensions only for 'exporting' files, even if you're exporting a text file to a text file.

  2. Create a resource fork entry for your file that manages to create a path to the opening application

If this is really the direction Apple is taking for Snow and Beyond, well, I have a word..no, two words for it:

Fucking Stupid

It is Fucking Stupid to do this. If the only way to have a unique UTI associated to a file is for that file to use a completely unique file extension, then WHAT THE FUCK GOOD ARE UTIS? Fucking seriously, why the FUCK bother? BBEdit creates TEXT FILES. Does Apple seriously expect that Bare Bones, to properly use UTIs, is going to now create a .bbedittext extension, a .bbedithtml extension, a .bbeditohmyfuckinggodwhatthefuckisgoingon extension, then make you EXPORT to 'standard' extensions, just so you can know a file created in BBEdit will open in it?

If this is what Apple is pushing, non-settable UTIs that are only 'inferred' because of (now) one piece of data, the filename extension, this is fucking inane. Like "stop huffing model glue" inane. Jesus, does someone have to write userspace trojans that blow out filename extensions on login or at random times, under snow, just to watch people be unable to fucking work before the NeXTards at Apple STOP FUCKING JIZZING ON THE FILENAME AS THE ONLY RELIABLE WAY TO ASSOCIATE THE FUCKING FILE TO THE APP?

If this is what Apple is pushing, then everyone who signed off on non-settable UTIs is a fucking idiot, and Cthulu below, I would LOVE to be wrong here, and have someone point me to the docs where you can set UTIs on a file manually.

Categories:     Mac Matters
Posted by John C. Welch at 14:07 | Permalink



Comments

Warning for Notes users: The commenting system uses HTML.
I know this will be scary for some of you, especially Notes fans. However, open standards, rah-rah.
If you want to use less-than or greater-than signs, or other similar charachters that HTML reserves,
you'll simply have to learn to do it the HTML way. Luckily, HTML is kind of popular, no matter what
your re-educators have told you, and you can easily find help on the intertubes.
digital.forest Where Internet solutions grow

There, a PayPal Button.

 
Use this code for your Macworld tickets!
Family
The Artwork of Melissa Findley
Diane Francis @ the National Post Eric Francis @ the Calgary Sun

Apple Amazon Links
Apple Mac OS X Server 10.5 [Unlimited]

Apple Mac OS X Server 10.5 [10-Client]

Apple Mac OS X 10.5 Leopard

Apple Mac OS X 10.5 Leopard [5-User Family Pack]

Amazon Book Links
Legacy of Ashes: The History of the CIA

The Donnas: Bitchin'

Wizards at War (The Young Wizards, Book 8)

The Demon's Sermon on the Martial Arts

The Collected Stories of Arthur C. Clarke

JavaScript and Ajax for the Web, Sixth Edition

Awakening Warrior: Revolution in the Ethics of Warfare

FOB Links

Mac Web Writers

Techie Links

Review Victims