Property list

Last updated

Property List
Filename extension
.plist
Internet media type
application/x-plist
Uniform Type Identifier (UTI) com.apple.property-list
Developed by Apple Computer and GNUstep,
formerly NeXT
Type of format Serialization of dictionary objects.

In the macOS, iOS, NeXTSTEP, and GNUstep programming frameworks, property list files are files that store serialized objects. Property list files use the filename extension .plist, and thus are often referred to as p-list files.

Contents

Property list files are often used to store a user's settings. They are also used to store information about bundles and applications, a task served by the resource fork in the old Mac OS.

Property lists are also used for localization strings for development. These files use the .strings or .stringsdict extensions. The former is a "reduced" old-style plist containing only one dictionary without the braces (see propertyListFromStringsFileFormat), [1] while the latter is a fully-fledged plist. Xcode also uses a .pbxproj extension for old-style plists used as project files.

Representations

Since the data represented by property lists is somewhat abstract, the underlying file format can be implemented many ways. Namely, NeXTSTEP used one format to represent a property list, and the subsequent GNUstep and macOS frameworks introduced differing formats.

NeXTSTEP

Under NeXTSTEP, property lists were designed to be human-readable and edited by hand, serialized to ASCII in a syntax somewhat like a programming language. This same format was used by OPENSTEP.

One limitation of the original NeXT property list format is that it could not represent an NSValue (number, Boolean, etc.) object. As a result, these values would have to be converted to string, and "fuzzily" recovered by the application. [2] Another limitation is that there is no official 8-bit encoding defined. [3]

The defaults utility, introduced in OPENSTEP (1996), can be used to manipulate plist files used for storage of preferences (known as defaults in NeXTSTEP, hence the name) on the command line via their preferences domain, and this utility can be used to edit arbitrary plist files. This utility superseded three older commands (dread, dwrite, and dremove). [4]

GNUstep

GNUstep adopts the NeXTSTEP format, with additions for representing NSValue and NSDate data types. The new typed entries have the form <*T...>, where T is a one-letter type code. For example, an NSValue of Boolean YES is represented as <*BY> and NSDate objects are represented as <*DYYYY-MM-DD HH:MM:SS +ZZZZ>. [5] [6] Binary data can also use the more efficient base64 format as <[ b64... ]>. The 8-bit problem is implicitly solved as well, as most deployments use UTF-8.

GNUstep also has its own binary format, NSPropertyListGNUstepBinaryFormat, implemented in NSSerialization. This format is defined recursively like the textual formats, with a single-byte type marker preceding some data. A form of string interning is supported via a GS-extension shouldBeCompact switch. [7]

Two relative independent plist handlers are found in GNUstep: the CFPropertyList in libs-core-base (CoreFoundation), and the NSPropertyList in libs-base (Foundation Kit). Both support the binary and XML forms used by macOS to some degree, but the latter is a lot more complete. For example, the two GNUstep-specific formats are only handled in the latter. [8]

GNUstep provides a set of plist command-line tools based on NSPropertyList, including a version of pl [9] and defaults. [4]

macOS

While macOS can also read the NeXTSTEP format, Apple sets it aside in favor of two new formats of its own, one XML-based and the other binary. Apple also has a partially-compatible JSON format (NSJSONSerialization).

History

In Mac OS X 10.0, the NeXTSTEP format was deprecated, and a new XML format was introduced, with a public DTD defined by Apple. The XML format supports non-ASCII characters and storing NSValue objects (which, unlike GNUstep's ASCII property list format, Apple's ASCII property list format does not support). [10]

Since XML files, however, are not the most space-efficient means of storage, Mac OS X 10.2 introduced a new format where property list files are stored as binary files. Starting with Mac OS X 10.4, this is the default format for preference files. In Mac OS X 10.7, support for reading and writing files in JSON format was introduced. JSON and property lists are not fully compatible with each other, though. For example, property lists have native date and data types, which the JSON format does not support. Conversely, JSON permits null values while property lists do not support explicit nulls.

Tooling

The old defaults tool from NeXTSTEP remains available. The /usr/libexec/PlistBuddy command provides an interactive plist editor. It can also be scripted. [11]

The plutil utility (introduced in Mac OS X 10.2) can be used to check the syntax of property lists, or convert a property list file from one format to another. It also supports converting plists to Objective-C or Swift object literals. [12] Like the Cocoa NSPropertyListSerialization it is built on, it takes "old-style" inputs, but does not convert to this type. (The Cocoa NSSerializer from before Mac OS X 10.2 emits old-styled output.)

The pl utility is introduced in Mac OS X v10.5. It takes any input and tries to generate "old-style" plists. [13] [lower-alpha 1] Like the GNUstep version, it appears to use the description property of Foundation types found in plists, which Apple has specified to produce valid old-style plists. [lower-alpha 2]

In terms of the internals, Apple provides an open source parser for old style, XML, and binary formats in their C Core Foundation code as CFPropertyList. However, all the utilities and most parts of the system use the closed-source NSPropertyList parser from the Obj-C Foundation Kit. The Swift reimplementation is open source, but is not guaranteed to be identical.

Format

XML and JSON property lists are hand-editable in any text editor. Additionally, Apple provides support in Xcode for editing property lists in a hierarchical viewer/editor that can handle plists formatted in binary or XML, but not JSON. As of Mac OS X 10.4, Apple provides an AppleScript interface for reading property list files through the System Events application. As of Mac OS X 10.5, Apple provides an AppleScript interface for editing, creating and writing property list files as well. [14]

For the XML format, the tags, related Foundation classes and CoreFoundation types, and data storage formats are as follows:

Foundation classCoreFoundation typeXML TagStorage format
NSStringCFString<string>UTF-8 encoded string
NSNumberCFNumber<real>, <integer>Decimal string; reals can have exponents, or be Infinity (inf) or NaN (nan).
NSNumberCFBoolean<true/>, <false/>No data (tag only)
NSDateCFDate<date> ISO 8601 formatted string
NSDataCFData<data> Base64 encoded data
NSArrayCFArray<array>Can contain any number of child elements. Can be empty.
NSDictionaryCFDictionary<dict>Alternating <key> tags and plist element tags. Can be empty.

The binary file format is documented in a comment block in the Core Foundation C code source file (CF/CFBinaryPList.c) for Apple's open sourced implementation of binary plists in its Foundation library. [15] Apple describes the implementation as opaque in its plist(5) manual page documentation, [16] which means that reliance on the format is discouraged. In the binary file format the magic number (the first few bytes of the file which indicate that it's a valid plist file) is the text bplist, followed by two bytes indicating the version of the format.

The binary file can store some information that cannot be captured in the XML or JSON file formats. The array, set and dictionary binary types are made up of pointers - the objref and keyref entries - that index into an object table in the file. This means that binary plists can capture the fact that - for example - a separate array and dictionary serialized into a file both have the same data element stored in them. This cannot be captured in an XML file. Converting such a binary file will result in a copy of the data element being placed into the XML file. Additionally the binary file has a UID type that is used to identify data items when serialized. The complete list of data that can be stored taken from the C code source file is as follows:

Binary plist object formats (as of CoreFoundation 1153) [15]
Foundation classCoreFoundation typeObject typeMarker byteEncoded data
nilnilnull (v"1?"+)0000 0000
NSNumberCFBooleanbool0000 1000 (false)
0000 1001 (true)
NSURLCFURLurl (v"1?"+)0000 1100 (base string)
0000 1101 (string)
string: URL string in recursive encoding (as in "string object format?"); base string: the same, but with a base URL encoded first.
NSUUIDCFUUIDuuid (v"1?"+)0000 111016 bytes of UUID
fill0000 1111nothing - just a padding
NSNumberCFNumberint0001 nnnn# of bytes is 2^nnnn, big-endian bytes (1, 2, 4, or 8)
NSNumberCFNumberreal0010 nnnn# of bytes is 2^nnnn, big-endian bytes (4 or 8)
NSDateCFDatedate0011 00118 byte float follows, big-endian bytes; seconds from 1/1/2001 (Core Data epoch)
NSDataCFDatadata0100 nnnn [int]nnnn is number of bytes unless 1111 then int count follows, followed by bytes
NSStringCFStringstring0101 nnnn [int]ASCII string, nnnn is # of chars, else 1111 then int count, then bytes
NSStringCFStringstring0110 nnnn [int]Unicode string, nnnn is # of chars, else 1111 then int count, then big-endian 2-byte uint16_t
NSStringCFStringstring (v"1?"+)0111 nnnn [int]UTF-8 string, nnnn is # of chars, else 1111 then int count, then bytes
UID1000 nnnnnnnn+1 is # of big-endian bytes (1, 2, 4, or 8). Unsigned int, only produced by NSKeyedArchiver (see below). [17]
NSArrayCFArrayarray1010 nnnn [int]objref* nnnn is count, unless '1111', then int count follows
NSOrderedSetordset (v"1?"+)1011 nnnn [int]objref* nnnn is count, unless '1111', then int count follows
NSSetCFSetset (v"1?"+)1100 nnnn [int]objref* nnnn is count, unless '1111', then int count follows
NSDictionaryCFDictionarydict1101 nnnn [int]keyref* objref* nnnn is count, unless '1111', then int count follo

Note the v"1?"+ note in many types. This means that the marker byte is only found in files with a format version no lower than the "1?" magic number. The precise way to parse them is more nebulous than the way to parse legacy types, since the CFBinaryPlist implementation only handles version "0?". In practice, these types are never encountered, since NSKeyedArchiver is already capable of capturing these information.

A table of offsets follow the object table, which is then followed by a trailer containing information on the size and location of the two tables.

Serializing to plist

Since property lists do not capture all the information and data types required to describe an arbitrary object, an extra layer of encoding and decoding is often done. The OpenStep specification abstracts the operation of serializing any NSObject under the NSCoding protocol. Any class implementing this protocol can have its instances serialized by a NSCoder subclass to some other format. [18] Two main coders exist for the purpose of serializing objects to plists:

Among other things, using an archiver allows for new datatypes to be encoded without changing the plist format itself and it is the preferred way for Apple to encode things like NSSets and null values. Parsing the formats do prove a bit harder, since one more layer must be followed even for some classes plists were supposed to support. Like the binary format which also has an object table, it is possible to create circular references in NSKeyedArchiver. Since there is not a UID data type in XML, the integers are stored in a dictionary under the key "CF$UID". [19]

Apple publishes an open-source NSKeyedArchiver in Swift Corelibs Foundation; like the closed-source Apple Foundation, it restricts output formats to binary and XML only. It also has some test cases showing the results of serialization. [20] GNUstep also has a compatible implementation, which does not limit output formats. [21]

Path language

There is not a single, standardized path language for property lists like XPath does for XML, but informal conventions used by various programs exist.

Neither format is able to express a key with the separator character in it.

Other platforms

Windows

Although best known on Apple or Darwin systems, including iOS and macOS, plist files are also present on Windows computers when Apple software, such as iTunes [22] or Safari [23] are installed. On Windows, the files are typically binary files, [24] although some applications may generate PLIST files in the other formats.

On Windows the Apple plist files are stored in the user's home directory under %USERPROFILE%\AppData\Roaming\Apple Computer. These plist files on Windows typically store preferences and other information, rather than using the Windows registry.

Options for editing PLIST files on Windows are not as extensive as on macOS. If the file is in the XML or JSON format with care a text editor such as Notepad++ can be used. Apple ships a plutil.exe within its "Apple Application Support" package (which is part of iTunes), and it is identical to its macOS counterpart.

NetBSD

Introduced in 2006 and first released with NetBSD#4.0 (2007) is a proplib library, which can be used for serialising data between the kernel and userland. It implements part of the XML plist language. [25]

One of the sample users of proplib is the second revision of the sysmon envsys framework for system monitoring.

NetBSD's proplib library has also been ported to DragonFly in 2010, and is available since DragonFly BSD#2.8. [26]

Cross-platform

See also

Notes

  1. A quirk of macOS pl is that it puts a stray "D" character into the stdout if one manually typed the standard input and terminated it with ^D.
  2. The description in Obj-C Foundation NSData is buggy in that it returns a dictionary representation. The open source Swift Foundation has no such issue.

Related Research Articles

<span class="mw-page-title-main">Serialization</span> Conversion process for computer data

In computing, serialization is the process of translating a data structure or object state into a format that can be stored or transmitted and reconstructed later. When the resulting series of bits is reread according to the serialization format, it can be used to create a semantically identical clone of the original object. For many complex objects, such as those that make extensive use of references, this process is not straightforward. Serialization of objects does not include any of their associated methods with which they were previously linked.

<span class="mw-page-title-main">NeXTSTEP</span> Operating system from NeXT Computer

NeXTSTEP is a discontinued object-oriented, multitasking operating system based on the Mach kernel and the UNIX-derived BSD. It was developed by NeXT Computer, founded by Steve Jobs, in the late 1980s and early 1990s and was initially used for its range of proprietary workstation computers such as the NeXTcube. It was later ported to several other computer architectures.

<span class="mw-page-title-main">TextEdit</span> Open-source word processor and text editor

TextEdit is an open-source word processor and text editor, first featured in NeXT's NeXTSTEP and OPENSTEP. It is now distributed with macOS since Apple Inc.'s acquisition of NeXT, and available as a GNUstep application for other Unix-like operating systems such as Linux. It is powered by Apple Advanced Typography.

Cocoa is Apple's native object-oriented application programming interface (API) for its desktop operating system macOS.

<span class="mw-page-title-main">GNUstep</span> Open source widget toolkit and application development tools

GNUstep is a free software implementation of the Cocoa Objective-C frameworks, widget toolkit, and application development tools for Unix-like operating systems and Microsoft Windows. It is part of the GNU Project.

The Foundation Kit, or just Foundation for short, is an Objective-C framework in the OpenStep specification described by NeXT Computer, Inc.. It provides basic classes such as wrapper classes and data structure classes. This framework uses the prefix NS. It is also part of Cocoa and of the Swift standard library.

<span class="mw-page-title-main">WebObjects</span> Java web application server and framework originally developed by NeXT Software

WebObjects is a discontinued Java web application server and a server-based web application framework originally developed by NeXT Software, Inc.

YAML is a human-readable data serialization language. It is commonly used for configuration files and in applications where data are being stored or transmitted. YAML targets many of the same communications applications as Extensible Markup Language (XML) but has a minimal syntax that intentionally differs from Standard Generalized Markup Language (SGML). It uses Python-style indentation to indicate nesting and does not require quotes around most string values.

<span class="mw-page-title-main">Configuration file</span> Software file used to configure the initial settings for a computer program

In computing, configuration files are files used to configure the parameters and initial settings for some computer programs or applications, server processes and operating system settings.

JSON is an open standard file format and data interchange format that uses human-readable text to store and transmit data objects consisting of attribute–value pairs and arrays. It is a commonly used data format with diverse uses in electronic data interchange, including that of web applications with servers.

<span class="mw-page-title-main">Interface Builder</span> Developer Application for MacOS

Interface Builder is a software development application for Apple's macOS operating system. It is part of Xcode, the Apple Developer developer's toolset. Interface Builder allows Cocoa and Carbon developers to create interfaces for applications using a graphical user interface. The resulting interface is stored as a .nib file, short for NeXT Interface Builder, or more recently, as an XML-based .xib file.

The Extensible Metadata Platform (XMP) is an ISO standard, originally created by Adobe Systems Inc., for the creation, processing and interchange of standardized and custom metadata for digital documents and data sets.

Core Data is an object graph and persistence framework provided by Apple in the macOS and iOS operating systems. It was introduced in Mac OS X 10.4 Tiger and iOS with iPhone SDK 3.0. It allows data organized by the relational entity–attribute model to be serialized into XML, binary, or SQLite stores. The data can be manipulated using higher level objects representing entities and their relationships. Core Data manages the serialized version, providing object lifecycle and object graph management, including persistence. Core Data interfaces directly with SQLite, insulating the developer from the underlying SQL.

In NeXTSTEP, OPENSTEP, and their lineal descendants macOS, iOS, iPadOS, tvOS, watchOS, and visionOS, and in GNUstep, a bundle is a file directory with a defined structure and file extension, allowing related files to be grouped together as a conceptually single item.

defaults is a command line utility that manipulates plist files. Introduced in 1998 OPENSTEP, defaults is found in the system's descendants macOS and GNUstep.

This is a comparison of data serialization formats, various ways to convert complex objects to sequences of bits. It does not include markup languages used exclusively as document file formats.

Universal Binary JSON (UBJSON) is a computer data interchange format. It is a binary form directly imitating JSON, but requiring fewer bytes of data. It aims to achieve the generality of JSON, combined with being much easier to process than JSON.

Objective-C is a high-level general-purpose, object-oriented programming language that adds Smalltalk-style message passing (messaging) to the C programming language. Originally developed by Brad Cox and Tom Love in the early 1980s, it was selected by NeXT for its NeXTSTEP operating system. Due to Apple macOS’s direct lineage from NeXTSTEP, Objective-C was the standard language used, supported, and promoted by Apple for developing macOS and iOS applications from 1997, when Apple purchased NeXT until the introduction of the Swift language in 2014.

JData is a light-weight data annotation and exchange open-standard designed to represent general-purpose and scientific data structures using human-readable (text-based) JSON and (binary) UBJSON formats. JData specification specifically aims at simplifying exchange of hierarchical and complex data between programming languages, such as MATLAB, Python, JavaScript etc. It defines a comprehensive list of JSON-compatible "name":value constructs to store a wide range of data structures, including scalars, N-dimensional arrays, sparse/complex-valued arrays, maps, tables, hashes, linked lists, trees and graphs, and support optional data grouping and metadata for each data element. The generated data files are compatible with JSON/UBJSON specifications and can be readily processed by most existing parsers. JData-defined annotation keywords also permit storage of strongly-typed binary data streams in JSON, data compression, linking and referencing.

References

  1. "NSString class reference: propertyListFromStringsFileFormat". GNUstep. Retrieved February 17, 2020.
  2. 1 2 "Package plist". godoc.org. When Unmarshal encounters an OpenStep property list, it will enter a relaxed parsing mode: OpenStep property lists can only store plain old data as strings, so we will attempt to recover integer, floating-point, boolean and date values wherever they are necessary.
  3. "Old-Style ASCII Property Lists". Apple Developer (Property List Programming Guide). Retrieved February 16, 2020.
  4. 1 2 defaults(1)    Linux General Commands Manual
  5. Frith-Macdonald, Richard (2004). "NSPropertyListSerialization class documentation". GNUstep.
  6. "Property Lists". GNUstepWiki.
  7. "NSSerialization documentation". GNUstep. source code
  8. "Types and Constants: NSPropertyListFormat". gnustep.org.
  9. pldes(1)    Linux General Commands Manual
  10. "appleexaminer.com: "PLIST files"". Archived from the original on February 19, 2014. Retrieved February 27, 2014.
  11. 1 2 PlistBuddy(8)    Darwin and macOS System Manager's Manual
  12. 1 2 plutil(1)    Darwin and macOS General Commands Manual
  13. pl(1)    Darwin and macOS General Commands Manual
  14. "AppleScript: Property Lists". April 24, 2009. Archived from the original on April 24, 2009.
  15. 1 2 "CF/CFBinaryPList.c". Apple Open Source. Retrieved January 6, 2020.
  16. plist(5)    Darwin and macOS File Formats Manual
  17. 1 2 Caithness, Alex (April 4, 2012). "Geek post: NSKeyedArchiver files – what are they, and how can I use them?". Digital Investigation. The CF$UID data type in Listing 2 is a dictionary with a single key ("CF$UID") which is followed by an integer number (this layout is what you will see when the property list is represented in XML; in the raw binary format the "UID" data type is a separate entity which doesn't require the dictionary structure). These data types represent a reference to another entity in the "$objects" array. The number of the CF$UID gives the position of the array.
  18. "NSCoder.html". OpenStep specification.
  19. 1 2 CCLForensics Group (January 15, 2020). "cclgroupltd/ccl-bplist". GitHub.
  20. "apple/swift-corelibs-foundation: NSKeyedArchiver.swift". GitHub. December 14, 2021. tests
  21. "NSKeyedArchiver documentation". GNUstep documentation. Retrieved February 23, 2020. source code
  22. Hummert, Christian; Humphries, Georgina Louise (2022), Hummert, Christian; Pawlaszczyk, Dirk (eds.), "Property Lists", Mobile Forensics – The File Format Handbook: Common File Formats and File Systems Used in Mobile Devices, Cham: Springer International Publishing, pp. 157–165, doi: 10.1007/978-3-030-98467-0_6 , ISBN   978-3-030-98467-0 , retrieved March 12, 2024
  23. "How does the Apple Safari web-browser store its settings on Windows?". Super User.
  24. "GitHub - microsoft/NSPlist: NSPlist". May 3, 2019 via GitHub.
  25. Jason R. Thorpe. "proplib — property container object library". NetBSD.
  26. Jason R. Thorpe. "proplib — property container object library". DragonFly BSD.
  27. "facebook/xcbuild/Libraries/plist". GitHub. Retrieved February 17, 2020.
  28. "plistlib — Generate and parse Mac OS X .plist files". Python 3 documentation. Retrieved January 6, 2020.
  29. "corpnewt/ProperTree: Cross platform GUI plist editor written in python". GitHub. February 17, 2020. Retrieved February 17, 2020.
  30. "propertylistserialization | Dart package". Dart packages. Retrieved September 14, 2024.