Each .iwa (iWork Archive) file in a Pages document holds one component
of the document’s object graph: a stream of Protocol Buffers messages, compressed with
Snappy. This page follows the iWorkFileFormat project; Apple has published none of
it.
Chunk framing
The file is a run of chunks, each with a 4-byte header. It is close to Snappy’s framing format, but iWork leaves out the stream identifier chunk and the CRC-32C checksums.
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 1 | Chunk type | Always 0 in iWork files: a Snappy-compressed chunk. |
1 | 3 | Length | 24-bit little-endian length of the chunk data, not counting this header. |
4 | length | Data | One Snappy-compressed block. |
Decompress each chunk and join the results to get the object stream.
Snappy blocks
A Snappy block (Google’s published format) starts with the uncompressed length as a varint, then a series of elements. The low two bits of each element’s tag byte give its kind:
| Tag bits 0–1 | Element | Layout |
|---|---|---|
00 | Literal | Bits 2–7 hold length − 1 (0–59); 60, 61, 62 and 63 mean the length − 1 follows in 1, 2, 3 or 4 little-endian bytes. Then the literal bytes. |
01 | Copy, 1-byte offset | Bits 2–4: length − 4 (4–11 bytes). Bits 5–7: the top three bits of an 11-bit offset, whose low eight bits are the next byte. |
10 | Copy, 2-byte offset | Bits 2–7: length − 1 (1–64). Then a 16-bit little-endian offset. |
11 | Copy, 4-byte offset | Bits 2–7: length − 1. Then a 32-bit little-endian offset. |
A copy repeats length bytes starting offset bytes back in the output; the ranges may overlap.
Object stream
The decompressed data is a sequence of objects. Each is a varint giving the length of
an ArchiveInfo message, that message, and then the payloads it
describes:
varint archiveInfoLength
ArchiveInfo (archiveInfoLength bytes)
payload 1 (MessageInfo[0].length bytes)
… (in practice there is one payload per object)
message ArchiveInfo {
optional uint64 identifier = 1; // unique across the document
repeated MessageInfo message_infos = 2;
}
message MessageInfo {
required uint32 type = 1; // which message the payload is
repeated uint32 version = 2 [packed = true]; // format version, 1.0.5 when documented
required uint32 length = 3; // payload length in bytes
repeated FieldInfo field_infos = 4; // not seen in practice
repeated uint64 object_references = 5 [packed = true];
repeated uint64 data_references = 6 [packed = true];
}
identifieris how other objects refer to this one, across all the.iwafiles of the document.object_referenceslists the identifiers this object points to, anddata_referencesthe data files (inData/) it uses; both are bookkeeping for cross-references.- The payload is a Protocol Buffers message whose type is given by
type. Protocol Buffers are not self-describing, so a reader must know each message’s definition; iWorkFileFormat recovered the definitions from the iWork programs with itsproto-dumptool.
Message types
Each iWork program maps type numbers to messages in its TSPRegistry;
the shared frameworks use the same numbers in Pages, Keynote and Numbers, and each
program adds its own. The numbers below are those iWorkFileFormat extracted from the
2013 programs; later versions add more.
| Prefix | Framework | Type numbers |
|---|---|---|
TP | Pages itself | 7 and 10000–10157 (47 types) |
TSK | Kit: document, commands, undo, annotation authors | 200–215 and a few more (16 types) |
TSS | Styles and themes | 400–418 (12) |
TSA | Application | 600–602 (3) |
TSWP | Word processing: text storages, paragraph and character styles, lists | 2001–2406 (67) |
TSD | Drawables: shapes, images, movies, groups | 3002–3060 (49) |
TSCE | Calculation engine | 4000–4005 (6) |
TSCH | Charts | 5000–5132 (47) |
TST | Tables | 6000–6256 (133) |
TSP | Persistence: package metadata, object containers | 11000–11008 (4) |
| Type | Message |
|---|---|
| 10000 | TP.DocumentArchive: the root object of a Pages document |
| 10001 | TP.ThemeArchive |
| 10010 | TP.FloatingDrawablesArchive |
| 10011 | TP.SectionArchive |
| 10012 | TP.SettingsArchive |
| 10015 | TP.DrawablesZOrderArchive |
| 7 | TP.PlaceholderArchive |
| 200 | TSK.DocumentArchive |
| 401 | TSS.StylesheetArchive |
| 2001 | TSWP.StorageArchive: a run of text with its styles |
| 3002 | TSD.DrawableArchive |
| 3005 | TSD.ImageArchive |
| 6000 | TST.TableInfoArchive |
| 11006 | TSP.PackageMetadata: the list of data files |
| 11008 | TSP.ObjectContainer |
Most of the other TP types (10101 and up) are undo commands, such as
TP.InsertDrawablesCommandArchive (10101) and
TP.InsertFootnoteCommandArchive (10113). Every number is listed on
message type numbers.
The text of the document is in TSWP.StorageArchive objects. The fields
of the messages are on document
messages, text and styles
and drawables.