GuiKit File Format Specifications
4/23/2007 - Updated to reflect Unicode variation descriptions.
The GUIKit file format is used by Unsanity and Geekspiff in their theme products, such as ShapeShifter and ThemePark. This document is only offered as a guide to parsing .guiKit files and offers no guarantee that the format will not change in the future. Because we have no control over the format itself, we cannot guarantee that the format will not change.
Notes about guiKitLib's implementation of a specific feature will be found in blue boxes such as this one.
The guiKit file format is a popular format for desktop themes used in the programs above. There has been expressed considerable interest in reverse engineering the format recently. Some reasons for this interest include:
Decompression of a guiKit file in order to extract the images and resources from within the guiKit file. Unsanity provided tools to do so at one time, but these tools have not been updated in recent history and do not work with any themes currently.
Application of guiKit themes without the use of ShapeShifter, using instead a shell script or other free software solution.
The ability to transcode guiKit theme files to another more open theme format, that can be used with other software, such as ThemeChanger.
To this end, we have created guiKitLib, a framework written in C that provides easy access to the contents of a guiKit file. GuiKitLib currently provides read support, and write support for guiKit files will be provided in a future release.
In addition, this document is being made available to anyone who wants to build their own guiKit file reader in the future.
GuiKitLib currently does not have any support for transcoding guiKit files from one format to another. Transcoding will be supported by the next release of ThemeKit code named "Metro". ThemeKit is a Cocoa framework that supports working with themes using object oriented programming.
GuiKit Format Basics
(Note: The basic format of a guiKit file is a tree. For the purposes of this document, what are referred to as attributes are essentially nodes in the tree.)
The guiKit file format is structurally very similar to a zip file. A file consist of groups of attributes. Each attribute generally shares the same format. The first four bytes of an attribute are the attribute's name. Attribute names are always made up of four characters.
Reading Attribute Names
Attribute names are always four characters. The best way to read an attribute name is to set the value of a 32 bit integer to the bytes of the attribute name. Of note, attributes are four bytes long and four characters, so they will not be null terminated.
After the attribute name usually comes four more bytes containing the length of the attribute, including the attribute name and the bytes containing the length of the attribute. Attributes that have fixed lengths, such as the CHSM (checksum) attribute will not contain a length. In cases such as the CHSM attribute, the developer should not read bytes 4-7 as the length. This does mean anyone implementing the guiKit format will have to hard code reading of specific attributes.
In, addition, attributes may contain other attributes. There is no convention for telling which attributes contain binary data and which attributes actually contain other attributes. Developers will again have to hard code which attributes have sub-attributes, and which attributes contain binary data.
Attributes within attributes follow the same format as their parents. In order to find sub attributes, being reading the parent attribute immediately after the length.
GuiKit File Attribute Types
CHSM - Checksum
The checksum attribute is the value of an Alder32 hash using the data from after the hash attribute to the end of the file. The checksum attribute is always found at the first byte of the file, and is always 12 bytes long (including the name).
The length of CHSM is fixed, and as such will not contain a length.
Checksums in guiKitLib
The function GKDoCheckSum(guiKitRef gkRef) will return 1 if the checksum for the passed theme file is valid, otherwise it will return 0.
VERS - Version
This attribute is 16 bytes long and is always found at byte 12. It is assumed to be the version of the guiKit serializer used to create the file.
Although the length is currently 16 bytes long, it does appear the length is variable.
THME - Themes
The THME attribute is an attribute that contains all the theme variation attributes. THME has a variable length.
TVAR - Theme Variation
A theme variation contains a set of images for a system theme. The parent attribute of a theme variation is a theme attribute, and a theme can contain multiple variations for the user to select from.
A TVAR has a variable length.
Variations in guiKitLib
GuiKitLib can fetch variations from a guiKit using two functions, int GKPatchCountForVariation(gkAttribRef gkRef), and gkPatchRef GKPatchForVariationAtIndex(int index, gkAttribRef gkRef) methods.
NAME - Attribute Name
NAME is an attribute found inside a variation that holds the name of the variation. The name is a zipped Unicode string.
NAME has a variable length.
Variation Names in guiKitLib
GuiKitLib can fetch names of attributes using the function CFStringRef GKCopyNameOfAttribute(gkAttribRef gkRef) methods.
DESC - Attribute Description
DESC is an attribute found inside a variation that holds a rich test description of the variation. The description is zipped rich text, and can be found in a sub attribute called "RTFD" or a sub attribute called "UNIC". "RTFD" will contain compressed RTF data, "UNIC" will contain a compressed Unicode string.
DESC has a variable length.
Variation Descriptions in guiKitLib
GuiKitLib can fetch descriptions of attributes using the function CFAttributedStringRef GKCopyDescriptionOfAttribute(gkAttribRef gkRef) methods.
PRVW - Preview Picture
PRVW is an attribute found inside a variation that holds a preview picture of the variation. The description is zipped image data, and can be found in a sub attribute called "DATA".
PRVW has a variable length.
Variation Preview Pictures in guiKitLib
GuiKitLib can fetch preview pictures of attributes using the function CFDataRef GKCopyImagePreviewOfAttribute(gkAttribRef gkRef) methods.
PTCS - Patches
Actual files in guiKit are contained in "patches", which are held inside a variation.
PTCS has a variable length.
Variation Patches in guiKitLib
GuiKitLib can fetch patches from a variation using the GKPatchCountForVariation(gkAttribRef gkRef) and gkPatchRef GKPatchForVariationAtIndex(int index, gkAttribRef gkRef) methods.
PTCH - Patch
A patch contains three important pieces of information, the application identifier of the application the guiKit wants to target, the specific path of the file to replace in the file system, and the data of the file that should replace the target file. These sub attributes are named PATH, APID, and FILE. All are zipped, and both PATH and APID are unicode strings, while FILE is binary data.
PTCH has a variable length.
Retrieving Patch Attributes in guiKitLib
GuiKitLib can fetch attributes from a patch from a variation using the CFStringRef GKCopyPathOfPatch(gkAttribRef gkRef), CFDataRef GKCopyFileOfPatch(gkAttribRef gkRef) and CFStringRef GKCopyApplicationIDOfPatch(gkAttribRef gkRef) methods.
The design of the guiKit format makes it hard to simply build a guiKit file browser. A lot of hard coding is necessary to distinguish which attributes contain other attributes, and which attributes simply contain flat data. In addition, there is no convention for telling which attributes have a length, and which attributes have fixed length. Despite these issues, a guiKit parser is fairly simple to implement.
This document will be revised as guiKitLib supports more features of the guiKit format, such as reading icon sets.