Inside Application Bundles
Reprinted from Hacking Mac OS X Tiger, copyright 2005, Wiley Publishing, Inc.
Continued from Page 1
What's What in Application Bundles
In this section, you take a closer look at the files and folders you discovered inside the application bundle. You see what all the pieces are for and how you might play around with them.
This folder almost always contains a single file whose name is the same as the application. This file contains the code that Mac OS X executes when you run the application. Although the vast majority of applications have only one executable in the MacOS folder, it's not a requirement. For example, older versions of Calculator (before Tiger) have two executables in the MacOS folder, Calculator and CalcEngine. Calculator is the application; CalcEngine is a helper program that does the math for Calculator.
The Resources folder in an application bundle has all the miscellaneous stuff the application needs in order to run, besides the code (which you found in the MacOS folder). This includes graphics displayed by the application (including icons, image files, bitmaps, and so on), human-readable text, sounds, and anything else the application developer wants to stash. If the application has any sort of associated files that should always stay with it, even when it's copied or moved, the Resources folder is like a safe deposit box for hiding these.
TextEdit and most other application bundles include everything they need to work in various human languages. The process of making an application run in different human languages is called localization. The Resources folder usually contains a bunch of folders whose names end in
lproj (localized project). TextEdit includes localizations for 15 different languages, including English, Japanese, Finnish, and Korean.
Any kinds of files can be buried in a bundle-even documentation. The Xcode application bundle includes a file that describes how to create a data display plug-in for the gdb debugger that comes with Apple's developer tools.
In various chapters earlier in this book, you edited preferences property list files to change the behavior of applications. A second important kind of property list is associated with every application: the information property list file (known to its friends as Info.plist). The Info.plist file tells all about the bundle. This file is mainly used by the Finder and the operating system to learn important information about the application, such as what kinds of files it supports and where to find its icons.
As with preferences property lists, every item in an information property list contains a key, which is the name of the item, and a valuefor the item. You can edit information property lists with a text editor or with the Property List Editor application.
Editing information property list keys is a great way to learn about how applications work with the Finder and the rest of Mac OS X, but it's also an efficient technique for making your application unusable. To be safe, you should make a copy of your application before fooling around with it.
Here's a list of Info.plist keys, what they're for, and their values in the TextEdit bundle, presented in several groups of related keys.
The keys in this group identify the bundle to the Finder and to parts of the system that need to know about applications, such as the Launch Services framework.
- CFBundleDevelopmentRegion. The default language for the application. For TextEdit and other applications in the U.S. distribution of Mac OS X, this is English.
- CFBundleDisplayName. The localized name of the application as displayed in the Finder. TextEdit's name is TextEdit, of course.
- CFBundleExecutable. This one is important: It gives the name of the executable file inside the bundle. For TextEdit, this key contains the value TextEdit, because that's the name of the executable.
- CFBundleIdentifier. This key contains a string that distinguishes the application from every other application in the world. How is that possible? Mac OS X takes advantage of Internet-style domain name rules to construct unique names for bundles. To make a bundle identifier, an application developer starts with a domain name and then reverses the order of the words, adding the name of the application on the end. So, for example, applications created by Apple have identifiers that start with com.apple. The identifier for TextEdit is com.apple.TextEdit. This weird-looking but clever reverse domain name business ensures that the parts of identifier names go from most general to most specific.
- CFBundleInfoDictionaryVersion. This key is created automatically when a developer builds an application. It contains the version number of the information property list structure-the very thing discussed here. By putting a version number in the property list, Apple provides a way to add features in the future while still making sure that old applications don't suddenly blow up when that happens. TextEdit (and all other Tiger applications) have 6.0, the current version number, in this key.
- CFBundleName. This key contains the name of the application, as displayed in the menu bar, next to the Apple menu (Figure 11-6). Like other values in the Info.plist, this one can be localized by values in the InfoPlist.strings file inside a localized project (lproj) folder, so if you try to change this value, take a look there as well. TextEdit, of course, has a CFBundleName of TextEdit.
Figure 11-6: Change the name the application displays in the menu bar.
- CFBundlePackageType. In another homage to the bygone days of Mac OS 9, this key contains a four-character value that indicates the type of the bundle. For TextEdit and all other applications, this key contains APPL, which by sheer coincidence is similar to (but not exactly the same as) Apple's stock market ticker symbol (AAPL).
- CFBundleSignature. In Mac OS 9 days, files were identified by type and creator codes. This key holds the four-character Mac OS 9-style creator code for the bundle, which used to be the way that applications were uniquely identified. For TextEdit, this is set to
ttxt , the creator code for the old TeachText application that was TextEdit's great grandapp.
- CFBundleShortVersionString. The application displays this string as the version number in its About box. Most applications use a numeric scheme with one or more decimals TextEdit is version 1.4. But this key is a string, so there's nothing to prevent you from using any characters you want, as demonstrated in Figure 11-7.
Figure 11-7: The version string in the About box need not be a number.
- CFBundleVersion. This key typically holds the application's build number, which by default is displayed in parentheses following the version number in the About box.
Many property list keys are used to specify the connections between applications and documents.
- CFBundleDocumentTypes. This key says which kinds of documents are supported by the application. Each type is represented by a property list data structure called a dictionary. TextEdit is prolific in its support: It can handle seven different kinds of documents. Most applications support fewer (Mail has five, iChat two), although some can handle even more types (iTunes supports 23 different kinds of documents). Here you see the kinds of information you can find about each type (not every file type has all these keys):
- CFBundleTypeExtensions. The file extensions (such as .txt) supported by this application. TextEdit supports rtf, doc, rtfd, txt, html, htm, and webarchive extensions. Web archiving is a new feature of Safari 2.0 (which comes with Mac OS X Tiger) that provides a way to save all the contents of a Web page.
- CFBundleTypeIconFile. This key gives the name of the file containing icons for the given file type. TextEdit's property list includes rtf.icns, txt.icns, and several others.
- CFBundleTypeMIMETypes. MIME is an international standard for encoding various types of information as text. (MIME stands for Multipurpose Internet Mail Extensions, which was the original intended use for this standard.) An application can specify a MIME type for the documents it supports instead of or in addition to the other kinds of identifying information in its property list. TextEdit supports MIME types text/plain and text/rtf.
- CFBundleTypeName. This key contains a name for the document type. This is either a nice human-friendly name like Apple HTML Document or a Cocoa type like NSStringPboardType. TextEdit handles these type names: Microsoft Word Document, Apple SimpleText Document, Apple HTML Document, Apple Web archive, NSRTFPboardType, NSTRFDPboardType, and NSStringPboardType.
- CFBundleTypeOSTypes. This key is a blast from the past. Back in the Mac OS 9 days, each file's type was specified by a four-character string. This key specifies the four-character strings for the file types the application supports. TextEdit names RTF (that's RTF followed by a blank, to make four characters), W8BN, W6BN (not weird radio stations but actually files created by older versions of Microsoft Word), TEXT, sEXT, and ttro.
- CFBundleTypeRole. This one is pretty cool: It specifies what this application knows how to do with documents of this type. There are four possible values: Editor, Viewer, Shell, and None. (Specifying None means the bundle is declaring information about a type, such as an icon, but doesn't know how to handle the documents.) TextEdit is a viewer for some documents, an editor for others.
- LSTypeIsPackage. This rarely used key specifies if the specified document type is to appear as a package. Few applications have this key, but TextEdit is one of them, because it bundles up RTF documents with images, so this key is set to
true for rtfd files.
- NSDocumentClass. Cocoa apps can use this key to give the name of the NSDocument subclass that should be instantiated to create documents of this type. TextEdit doesn't use this one.
- LSIsAppleDefaultForType. This key declares that the application is the default for opening documents of a particular type. TextEdit names itself the default for txt, rtf, rtfd, and ttro documents.
An application's property list includes a few entries that tie the application to various kinds of files.
- CFBundleHelpBookFolder. This key points at the location of the application's Help files. This name is assumed to be a folder inside the lproj folders that contains the localized versions of the application. TextEdit's help folder is called TextEditHelp, naturally.
- CFBundleHelpBookName. This key contains the name of the Help book as it will appear in the Help viewer (see Figure 11-8). TextEdit's is called TextEdit Help. Most applications name their help books after themselves.
Figure 11-8: CFBundleHelpBookName shows up in the Help viewer.
- CFBundleIconFile. Here's where the developer gets to specify a custom icon for the bundle. This key contains the name of a file in the bundle's Resources folder that holds the icons. TextEdit keeps its icon in a file called Edit.icns file, but there's no rule about what the name of the file must be.
Charles Finley? Cold Fusion? Cruel Fish?
No doubt you noticed that most of the keys in Info.plist start with CF. So what's CF? It stands for CoreFoundation, which sounds like an Isaac Asimov novel but is actually the basic framework of code that OS X applications use. Anything that starts with CF is a constant, class, or other element defined by CoreFoundation. And by the way, the LS prefix is for the LaunchServices framework, which launches applications and associates documents with applications. You might already know that the NS prefix stands for NeXTStep, the system from NeXT, Inc. that was the original source of much of the foundation of Mac OS X.
This section lists a few other property list keys that don't fit neatly into any of the preceding categories.
- NSAppleScriptEnabled. This value indicates whether users can control the application via AppleScript. TextEdit supports AppleScript, as all good applications should, so this key is set to
- NSHumanReadableCopyright. This key, beloved by lawyers everywhere, provides a textual copyright for the application. TextEdit sets this value to
Copyright 1995-2005, Apple Computer, Inc.
- NSMainNibFile. This key contains the name of the application's main nib file. Nib files are created by Interface Builder and furnish the blueprint for the application's user interface features, such as windows, menus, and controls. The main nib file is usually localized and kept in the lproj folder. TextEdit sets this key to
Edit, because its main nib file is named Edit.nib.
- NSPrincipalClass. The application's main class, usually a subclass of NSApplication or NSApplication itself, it kept in this key. TextEdit has NSApplication in this key.
- NSServices. Applications use this key to tell Mac OS X about services they provide to other programs. These services are listed in the Application @@> Services menu of other applications. TextEdit contributes two services: New Window Containing Selection and Open Selected File.
Apple provides the Property List Editor application for examining and changing Info.plist files and other property lists. For a more structured look at some of the keys described in this section, check out the freeware application AppHack, written by Sveinbjorn Thordarson. You can download AppHack at http://www.sveinbjorn.vefsyn.is/apphack.
The last item inside the application bundle is the version.plist file. This file contains version strings and other information for use by the Mac OS X Installer.
As you saw in the previous section, applications can be customized for various countries and languages by including localized project (lproj) folders inside the application bundle. Files that are outside any of the lproj folders are considered nonlocalized: They can be used no matter what language the application is running in.
The much-discussed Info.plist file is in the main Contents folder of the bundle, outside the localized projects, but developers can still localize the contents of Info.plist by including a file named InfoPlist.strings in an lproj folder. Any strings defined in an InfoPlist.strings file take precedence over the values from the application's Info.plist file. That's how TextEdit can have TextEdit Help in English, AideTextEdit in French, and Ajuda Editor de Texto in Portuguese.
The Do-it-Yourself Bundle
You can play around with bundles by creating your own bundle in the Finder. There's no practical reason to do this-it's just for fun and experimentation. In practice, bundles are created by development systems like XCode as a part of the process of building software. You can create your own bundle using only the Finder. Here's how:
- In the Finder, choose File>New Folder to get an ordinary, everyday folder.
- Click the new folder to make sure it's selected (it might already be selected).
- Now that the folder is selected, click its name to select the text for editing.
- Type a new name for the folder. Use any name you want, as long as you put .wdgt at the end (Figure 11-9). Press Return when you're done editing.
- The Finder will warn you that you're about to do something really interesting by adding .wdgt to the name. Click Add to let the Finder know you really want to do this.
Figure 11-9: You can create your own bundle in the Finder just by renaming a folder.
Instantly, your innocent folder takes on a new appearance: It now has the generic Dashboard widget icon. You've convinced the Finder that you have a widget bundle, just by renaming the file to add .wdgt to the end. Kind of shocking, isn't it? You can get the same effect (with a different icon) by using a different suffix, such as .app, instead of .wdgt. You can now do all the normal bundle things with your fake widget, including choosing Show Package Contents from the Action menu (Figure 11-10). Of course, when you do, you'll see that the bundle-ized folder is still empty.
Figure 11-10: It's not really a Dashboard widget, but it really is a package.
Now you can rename the bundle again, this time removing the magical .wdgt suffix. After another confirmation dialog from the Finder, your folder is once again a folder.
To make the widget back into a folder:
- In the Finder, select the folder-that-thinks-it's-a-widget.
- Choose File>Get Info.
- Make sure the disclosure triangle in the Name & Extension section is open (Figure 11-11).
Figure 11-11 Finder Info window.
- Remove the .wdgt extension from the name and close the Info window.
- When you get the Are You Sure? warning, click OK.
The widget is now a folder again.
Applications and other Mac OS X bundles are intricate, complex creatures. When you find out what lives inside an application, it creates a new appreciation for how well all this stuff works. With the knowledge and tools provided in this chapter, you can peek and poke around your applications all you want. Just be sure to back up before trying anything really crazy.