Cocoa Property Lists

Most of the configuration files present on Apple's devices are stored as serialized Objective-C data structures known as "property lists". Over the history of these files, Apple has provided multiple formats for these files, from highly verbose XML to dense binary. Apple provides an Introduction to Property Lists on their developer website. Substrate uses these these property lists for its extension configuration.

OpenStep Property List

This format is the most common used by developers of Substrate extensions. Strings are encoded as either bare identifiers or surrounded with quotation marks, arrays are comma-separated lists within parentheses, and dictionaries are semicolon-terminated name-equal-value pairs within curly braces. The outermost scope, if a dictionary, can optionally leave off the braces.

Unlike the other formats, Apple does not provide a serializer for OpenStep property lists: there is only a parser. You thereby cannot convert files into this format using plutil. Additionally, not all primitive types are capable of being represented with this format (numbers as CFNumber or NSNumber being the primary example of this limitation).

# cat WinterBoard.plist
Filter = {
    Bundles = ("com.apple.UIKit");
    Executables = ("lsd", "mediaserverd");
    Mode = "Any";
};

XML Property List

When Apple deprecated the OpenStep format, they replaced it with a more "modern" XML-based configuration. The various types are represented as elements and text nodes: attributes are not used by this format except to specify the version number on the top-level <plist> element.

It should be noted that these files are parsed using the system's fully-featured XML parser, and are therefore fairly slow to process. It has been reported that parsing XML configuration files can add noticeable startup performance cost to applications, so developers are encouraged to avoid this format.

Also, it should be made clear that due to these files being parsed by a real XML parser, they can be formatted arbitrarily, use XML namespaces and comments, and generally support anything normally associated with an XML document. Developers who believe they can parse these files using regular expressions are therefore sadly mistaken.

Therefore, if you need to programmatically load or edit one of these files, you should always use Apple's libraries as opposed to attempting "simple patches". The +dictionaryWithContentsOfFile: and -writeToFile:atomically: methods of NSDictionary are very simple to use, and make modifying these files quite simple.

# plutil -convert xml1 Veency.plist
Converted 1 files to XML format

# cat Veency.plist 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Filter</key>
    <dict>
        <key>Bundles</key>
        <array>
            <string>com.apple.springboard</string>
        </array>
    </dict>
</dict>
</plist>

Binary Property List

The binary1 property list format is a nearly ideal tradeoff between performance and functionality: it supports all of the possible serialization types, and is by far the fastest to both load and save from disk.

The format, however, is highly opaque, and almost all of the existing parsers are written by Apple (making them somewhat difficult to generate on other platforms). This aside, it is recommended that all Substrate projects use the binary format for the final production deployment of their extension configuration files.

# plutil -convert binary1 Veency.plist 
Converted 1 files to binary format

# od -t x1 Veency.plist 
0000000 62 70 6c 69 73 74 30 30 d1 01 02 56 46 69 6c 74
0000020 65 72 d1 03 04 57 42 75 6e 64 6c 65 73 a1 05 5f
0000040 10 15 63 6f 6d 2e 61 70 70 6c 65 2e 73 70 72 69
0000060 6e 67 62 6f 61 72 64 08 0b 12 15 1d 1f 00 00 00
0000100 00 00 00 01 01 00 00 00 00 00 00 00 06 00 00 00
0000120 00 00 00 00 00 00 00 00 00 00 00 00 37
0000135