From 70bd26b971c22008114a6a09e3d62993a3ed52f5 Mon Sep 17 00:00:00 2001 From: Pasquale Ambrosini Date: Wed, 8 Jun 2016 16:40:58 +0400 Subject: [PATCH 1/3] Added CONTRIBUTORS.md --- CONTRIBUTORS.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 CONTRIBUTORS.md diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 0000000..4c4da28 --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +Sean Patrick O'Brien (http://obriensp.com) +Pasquale Ambrosini (http://pasqualeambrosini.net) From df83e2658df564a8b6492f4df8d67bc5c969cebc Mon Sep 17 00:00:00 2001 From: Pasquale Ambrosini Date: Wed, 8 Jun 2016 16:57:03 +0400 Subject: [PATCH 2/3] Added README --- .DS_Store | Bin 0 -> 6148 bytes CONTRIBUTORS.md | 1 + Docs/2013.md | 114 ++++++++++++++++ Docs/2015.md | 124 ++++++++++++++++++ Docs/index.md | 116 +--------------- .../UserInterfaceState.xcuserstate | Bin 0 -> 7912 bytes .../xcschemes/xcschememanagement.plist | 19 +++ 7 files changed, 262 insertions(+), 112 deletions(-) create mode 100644 .DS_Store create mode 100644 Docs/2013.md create mode 100644 Docs/2015.md create mode 100644 iWorkFileInspector/iWorkFileInspector.xcodeproj/project.xcworkspace/xcuserdata/pascal.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 iWorkFileInspector/iWorkFileInspector.xcodeproj/xcuserdata/pascal.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..fe6069fb381dc452c5b62d277cf1d7dd20fa78ef GIT binary patch literal 6148 zcmeH~&1%~~5XWZ|rIlR>YT7`c7hMZExQUCeisJ@yC>T^?N>f}Z67f=@HIf_?j6sK< z`WX3Y-XpZ{&`0U5GrQ}M)CujSCJ8$*`=9+7E&7Sw)dB!(4x(284glEbq*fJ+8;ttN zr)*BQSg4Gi5f1Zyn1~STzotf;21CFQxN8Jx?OM;puQ=~<}(>S}5 zy4&GtB!*2fNTYn$SI_J4sOWW_<#rYyU}`%^;~k#!kSDx2tf1MIuCp>4)$6rYcdbzy zuezf~1LOL7V?1`g*!GK;uQ%Sl?~lJ89iN<@eLKJSuD$@n4NKZHtrPiy!6lFbKT8vl z?qeH`UjhytM3up3*upr07`7pW9QqjTK|y_ghge03OLquj<-b7uCs=;~o_qwOvml_C zfc<0^lbJaT0Yl(k5up9SMJM&NmP+N;frY#Rpwe%IG>qvkK{>8gPiv_Zd(fClMOCRx zUon_U$97kb^R$*qRXQ+z`Cxixrf(=r&W_J_<#1r0Qd1fNhQM_K^Q!95`Tyqj`~USM zQ!@k%fd@r^SuMZS#8=X1>(tB9S?i*ILMNkfrBa!Kg+7jDKu7Tkx-{%_DM0nKmP)Y& P&HM;R45lyyW=h~UT7kqS literal 0 HcmV?d00001 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 4c4da28..09c089f 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,2 +1,3 @@ Sean Patrick O'Brien (http://obriensp.com) + Pasquale Ambrosini (http://pasqualeambrosini.net) diff --git a/Docs/2013.md b/Docs/2013.md new file mode 100644 index 0000000..e4b02e3 --- /dev/null +++ b/Docs/2013.md @@ -0,0 +1,114 @@ +#iWork '13 File Format + +## Overview +The iWork '13 format is a [bundle](https://developer.apple.com/library/mac/documentation/corefoundation/conceptual/cfbundles/DocumentPackages/DocumentPackages.html)-based format built on top of several open source projects. This document describes the physical layout of files contained in these bundles and the algorithms involved, but does not attempt to describe the nature of the represented object graph. + +## Bundle + +The organization of an iWork document bundle is fairly straightforward. Media such as images and videos are stored in the `Data` subdirectory, serialized objects are stored in [Index.zip](#index-zip), some light metadata is stored in the `Metadata` subdirectory, and a few preview images are stored in the top level of the bundle. + + Photo Essay.key/ + Data/ + 143917994_2881x1992-small.jpg + 143918632_1620x1622-small.jpg + 154121867_2447x1632-small.jpg + 154146989_2880x1920-small.jpg + ... + Index.zip + Metadata/ + BuildVersionHistory.plist + DocumentIdentifier + Properties.plist + preview-micro.jpg + preview-web.jpg + preview.jpg + +## Index.zip +A document's objects are organized into groups called Components. Each Component is serialized into the [IWA](#iwa) format and stored in Index.zip. + + Index/ + AnnotationAuthorStorage.iwa + CalculationEngine.iwa + Document.iwa + DocumentStylesheet.iwa + MasterSlide-1.iwa + MasterSlide-10.iwa + MasterSlide-11.iwa + ... + +Curiously, the zip implementation iWork uses for this file is extremely limited. It does not support any form of compression or extensions like Zip64. Simply expanding Index.zip and then recreating it with a standard zip utility will result in a document that iWork refuses to open. + +The iWork '13 applications contain a separate, more complete zip implementation used for reading and writing iWork '09 documents (which are bundles that have been zipped in their entirety), so I believe the choice to forgo compression for Index.zip is intentional. + +One possibility is that Index.zip is used to prevent the syncronization issues that would occur if reading and writing a document involved accessing many small files. Saving a document might involve writing out several Components, so instead of coordinating writes to the various individual .iwa files, only the Index.zip must be locked. Since the .iwa files are inherently compressed (see [Snappy Compression](#snappy-compression)), the zip implementation used for Index.zip could be designed to be minimial and efficient. + +## IWA + +Components are serialized into .iwa (iWork Archive) files, a custom format consisting of a [Protobuf](#protobuf) stream wrapped in a [Snappy](#snappy-compression) stream. + +### Snappy Compression +[Snappy](https://code.google.com/p/snappy/) is a compression format created by Google aimed at providing decent compression ratios at high speeds. IWA files are stored in Snappy's [framing format](https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt), though they do not adhere rigorously to the spec. In particular, they do not include the required Stream Identifier chunk, and compressed chunks do not include a CRC-32C checksum. + +The stream is composed of contiguous chunks prefixed by a 4 byte header. The first byte indicates the chunk type, which in practice is always 0 for iWork, indicating a Snappy compressed chunk. The next three bytes are interpreted as a 24-bit little-endian integer indicating the length of the chunk. The 4 byte header is not included in the chunk length. + +### Protobuf +The uncompresed IWA contains the Component's objects, serialized consecutively in a [Protobuf](https://code.google.com/p/protobuf/) stream. Each object begins with a [varint](https://developers.google.com/protocol-buffers/docs/encoding#varints) representing the length of the [ArchiveInfo](#archiveinfo) message, followed by the `ArchiveInfo` message itself. The `ArchiveInfo` includes a variable number of [MessageInfo](#messageinfo) messages describing the encoded [Payloads](#payload) that follow, though in practice iWork files seem to only have one payload message per `ArchiveInfo`. + + Object 0 varint archiveInfoLength + ArchiveInfo archiveInfo + (payload) + + Object 1 varint archiveInfoLength + ArchiveInfo archiveInfo + (payload) + + ... + + Object n varint archiveInfoLength + ArchiveInfo archiveInfo + (payload) + +### ArchiveInfo + +The `ArchiveInfo` message contains the object's `identifier` (unique across the document), as well as information about the encoded messages (see [MessageInfo](#messageinfo)). + + message ArchiveInfo { + optional uint64 identifier = 1; + repeated MessageInfo message_infos = 2; + } + +### MessageInfo + +The `MessageInfo` message describes the encoded payload that follows the `ArchiveInfo`. The `type` field indicates how the payload should be decoded (see [TSPRegistry](#tspregistry)), the `version` field indicates what format version was used to encode (currently 1.0.5), and the `length` field specifies how much data follows. The `field_infos` field would allow for deep introspection into the format of the payload, but it is absent from all archives I have inspected. It's possible that it is meant for backwards compatibility when new fields are introduced. The `object_references` and `data_references` fields are for bookkeeping/cross-referencing. + + message MessageInfo { + required uint32 type = 1; + repeated uint32 version = 2 [packed = true]; + required uint32 length = 3; + repeated FieldInfo field_infos = 4; + repeated uint64 object_references = 5 [packed = true]; + repeated uint64 data_references = 6 [packed = true]; + } + +### Payload +The format of the payload is determined by the `type` field of the associated `MessageInfo` message. The iWork applications manually map these integer values to their respective Protobuf message types, and the mappings vary slightly between Keynote, Pages and Numbers. This information can be recovered by inspecting the [TSPRegistry](#tspregistry) class at runtime. + +Because Protobuf is not a self-describing format, applications attempting to understand the payloads must know a great deal about the data types and hierarchy of the objects serialized by iWork. Fortunately, all of this information can be recovered from the iWork binaries using [proto-dump](https://github.com/obriensp/proto-dump). + +A full dump of the Protobuf messages can be found [here](../iWorkFileInspector/iWorkFileInspector/Messages/Proto/). + +### TSPRegistry +The mapping between an object's `MessageInfo.type` and its respective Protobuf message type must by extracted from the iWork applications at runtime. Attaching to Keynote via a debugger and inspecting `[TSPRegistry sharedRegistry]` shows: + + 0x102f24680 KN.ChartInfoGeometryCommandArchive + 147 -> 0x102f24650 KN.SlideCollectionCommandSelectionBehaviorArchive + 146 -> 0x102f24560 KN.CommandSlideReapplyMasterArchive + 145 -> 0x102f24420 KN.CommandMasterSetBodyStylesArchive + ... + +A full list of the type mappings can be found [here](../iWorkFileInspector/iWorkFileInspector/Persistence/MessageTypes/). + +## Encryption +If the document is locked with a password, nearly all files in the bundle are encrypted using [AES128](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard) encryption with [PKCS7](http://en.wikipedia.org/wiki/Padding_\(cryptography\)#PKCS7) padding. For a full description of the encryption format, see [iWork Encrypted Stream](iWork Encrypted Stream.md). \ No newline at end of file diff --git a/Docs/2015.md b/Docs/2015.md new file mode 100644 index 0000000..b8f7e5f --- /dev/null +++ b/Docs/2015.md @@ -0,0 +1,124 @@ +#iWork '15+ File Format + +## Overview +The iWork '15+ format is a [bundle](https://developer.apple.com/library/mac/documentation/corefoundation/conceptual/cfbundles/DocumentPackages/DocumentPackages.html)-based format built on top of several open source projects. This document describes the physical layout of files contained in these bundles and the algorithms involved, but does not attempt to describe the nature of the represented object graph. + +## Bundle + +The organization of an iWork document bundle is fairly straightforward. Media such as images and videos are stored in the `Data` subdirectory, serialized objects are stored in [Index](#index), some light metadata is stored in the `Metadata` subdirectory, and a few preview images are stored in the top level of the bundle. + + So basically the new format is the same of the 2013 but the `Photo Essay.key` is a zip file and Index is a folder and not a zip file + + Photo Essay.key/ + Data/ + 143917994_2881x1992-small.jpg + 143918632_1620x1622-small.jpg + 154121867_2447x1632-small.jpg + 154146989_2880x1920-small.jpg + ... + Index/ + AnnotationAuthorStorage.iwa + CalculationEngine.iwa + Document.iwa + DocumentStylesheet.iwa + MasterSlide-1.iwa + MasterSlide-10.iwa + MasterSlide-11.iwa + ... + Metadata/ + BuildVersionHistory.plist + DocumentIdentifier + Properties.plist + preview-micro.jpg + preview-web.jpg + preview.jpg + +## Index.zip +A document's objects are organized into groups called Components. Each Component is serialized into the [IWA](#iwa) format and stored in Index.zip. + + Index/ + AnnotationAuthorStorage.iwa + CalculationEngine.iwa + Document.iwa + DocumentStylesheet.iwa + MasterSlide-1.iwa + MasterSlide-10.iwa + MasterSlide-11.iwa + ... + +Curiously, the zip implementation iWork uses for this file is extremely limited. It does not support any form of compression or extensions like Zip64. Simply expanding Index.zip and then recreating it with a standard zip utility will result in a document that iWork refuses to open. + +The iWork '13 applications contain a separate, more complete zip implementation used for reading and writing iWork '09 documents (which are bundles that have been zipped in their entirety), so I believe the choice to forgo compression for Index.zip is intentional. + +One possibility is that Index.zip is used to prevent the syncronization issues that would occur if reading and writing a document involved accessing many small files. Saving a document might involve writing out several Components, so instead of coordinating writes to the various individual .iwa files, only the Index.zip must be locked. Since the .iwa files are inherently compressed (see [Snappy Compression](#snappy-compression)), the zip implementation used for Index.zip could be designed to be minimial and efficient. + +## IWA + +Components are serialized into .iwa (iWork Archive) files, a custom format consisting of a [Protobuf](#protobuf) stream wrapped in a [Snappy](#snappy-compression) stream. + +### Snappy Compression +[Snappy](https://code.google.com/p/snappy/) is a compression format created by Google aimed at providing decent compression ratios at high speeds. IWA files are stored in Snappy's [framing format](https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt), though they do not adhere rigorously to the spec. In particular, they do not include the required Stream Identifier chunk, and compressed chunks do not include a CRC-32C checksum. + +The stream is composed of contiguous chunks prefixed by a 4 byte header. The first byte indicates the chunk type, which in practice is always 0 for iWork, indicating a Snappy compressed chunk. The next three bytes are interpreted as a 24-bit little-endian integer indicating the length of the chunk. The 4 byte header is not included in the chunk length. + +### Protobuf +The uncompresed IWA contains the Component's objects, serialized consecutively in a [Protobuf](https://code.google.com/p/protobuf/) stream. Each object begins with a [varint](https://developers.google.com/protocol-buffers/docs/encoding#varints) representing the length of the [ArchiveInfo](#archiveinfo) message, followed by the `ArchiveInfo` message itself. The `ArchiveInfo` includes a variable number of [MessageInfo](#messageinfo) messages describing the encoded [Payloads](#payload) that follow, though in practice iWork files seem to only have one payload message per `ArchiveInfo`. + + Object 0 varint archiveInfoLength + ArchiveInfo archiveInfo + (payload) + + Object 1 varint archiveInfoLength + ArchiveInfo archiveInfo + (payload) + + ... + + Object n varint archiveInfoLength + ArchiveInfo archiveInfo + (payload) + +### ArchiveInfo + +The `ArchiveInfo` message contains the object's `identifier` (unique across the document), as well as information about the encoded messages (see [MessageInfo](#messageinfo)). + + message ArchiveInfo { + optional uint64 identifier = 1; + repeated MessageInfo message_infos = 2; + } + +### MessageInfo + +The `MessageInfo` message describes the encoded payload that follows the `ArchiveInfo`. The `type` field indicates how the payload should be decoded (see [TSPRegistry](#tspregistry)), the `version` field indicates what format version was used to encode (currently 1.0.5), and the `length` field specifies how much data follows. The `field_infos` field would allow for deep introspection into the format of the payload, but it is absent from all archives I have inspected. It's possible that it is meant for backwards compatibility when new fields are introduced. The `object_references` and `data_references` fields are for bookkeeping/cross-referencing. + + message MessageInfo { + required uint32 type = 1; + repeated uint32 version = 2 [packed = true]; + required uint32 length = 3; + repeated FieldInfo field_infos = 4; + repeated uint64 object_references = 5 [packed = true]; + repeated uint64 data_references = 6 [packed = true]; + } + +### Payload +The format of the payload is determined by the `type` field of the associated `MessageInfo` message. The iWork applications manually map these integer values to their respective Protobuf message types, and the mappings vary slightly between Keynote, Pages and Numbers. This information can be recovered by inspecting the [TSPRegistry](#tspregistry) class at runtime. + +Because Protobuf is not a self-describing format, applications attempting to understand the payloads must know a great deal about the data types and hierarchy of the objects serialized by iWork. Fortunately, all of this information can be recovered from the iWork binaries using [proto-dump](https://github.com/obriensp/proto-dump). + +A full dump of the Protobuf messages can be found [here](../iWorkFileInspector/iWorkFileInspector/Messages/Proto/). + +### TSPRegistry +The mapping between an object's `MessageInfo.type` and its respective Protobuf message type must by extracted from the iWork applications at runtime. Attaching to Keynote via a debugger and inspecting `[TSPRegistry sharedRegistry]` shows: + + 0x102f24680 KN.ChartInfoGeometryCommandArchive + 147 -> 0x102f24650 KN.SlideCollectionCommandSelectionBehaviorArchive + 146 -> 0x102f24560 KN.CommandSlideReapplyMasterArchive + 145 -> 0x102f24420 KN.CommandMasterSetBodyStylesArchive + ... + +A full list of the type mappings can be found [here](../iWorkFileInspector/iWorkFileInspector/Persistence/MessageTypes/). + +## Encryption +If the document is locked with a password, nearly all files in the bundle are encrypted using [AES128](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard) encryption with [PKCS7](http://en.wikipedia.org/wiki/Padding_\(cryptography\)#PKCS7) padding. For a full description of the encryption format, see [iWork Encrypted Stream](iWork Encrypted Stream.md). \ No newline at end of file diff --git a/Docs/index.md b/Docs/index.md index e4b02e3..1d0cd6d 100644 --- a/Docs/index.md +++ b/Docs/index.md @@ -1,114 +1,6 @@ -#iWork '13 File Format +#iWork File Format -## Overview -The iWork '13 format is a [bundle](https://developer.apple.com/library/mac/documentation/corefoundation/conceptual/cfbundles/DocumentPackages/DocumentPackages.html)-based format built on top of several open source projects. This document describes the physical layout of files contained in these bundles and the algorithms involved, but does not attempt to describe the nature of the represented object graph. +There are 2 file format of the iWork File: -## Bundle - -The organization of an iWork document bundle is fairly straightforward. Media such as images and videos are stored in the `Data` subdirectory, serialized objects are stored in [Index.zip](#index-zip), some light metadata is stored in the `Metadata` subdirectory, and a few preview images are stored in the top level of the bundle. - - Photo Essay.key/ - Data/ - 143917994_2881x1992-small.jpg - 143918632_1620x1622-small.jpg - 154121867_2447x1632-small.jpg - 154146989_2880x1920-small.jpg - ... - Index.zip - Metadata/ - BuildVersionHistory.plist - DocumentIdentifier - Properties.plist - preview-micro.jpg - preview-web.jpg - preview.jpg - -## Index.zip -A document's objects are organized into groups called Components. Each Component is serialized into the [IWA](#iwa) format and stored in Index.zip. - - Index/ - AnnotationAuthorStorage.iwa - CalculationEngine.iwa - Document.iwa - DocumentStylesheet.iwa - MasterSlide-1.iwa - MasterSlide-10.iwa - MasterSlide-11.iwa - ... - -Curiously, the zip implementation iWork uses for this file is extremely limited. It does not support any form of compression or extensions like Zip64. Simply expanding Index.zip and then recreating it with a standard zip utility will result in a document that iWork refuses to open. - -The iWork '13 applications contain a separate, more complete zip implementation used for reading and writing iWork '09 documents (which are bundles that have been zipped in their entirety), so I believe the choice to forgo compression for Index.zip is intentional. - -One possibility is that Index.zip is used to prevent the syncronization issues that would occur if reading and writing a document involved accessing many small files. Saving a document might involve writing out several Components, so instead of coordinating writes to the various individual .iwa files, only the Index.zip must be locked. Since the .iwa files are inherently compressed (see [Snappy Compression](#snappy-compression)), the zip implementation used for Index.zip could be designed to be minimial and efficient. - -## IWA - -Components are serialized into .iwa (iWork Archive) files, a custom format consisting of a [Protobuf](#protobuf) stream wrapped in a [Snappy](#snappy-compression) stream. - -### Snappy Compression -[Snappy](https://code.google.com/p/snappy/) is a compression format created by Google aimed at providing decent compression ratios at high speeds. IWA files are stored in Snappy's [framing format](https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt), though they do not adhere rigorously to the spec. In particular, they do not include the required Stream Identifier chunk, and compressed chunks do not include a CRC-32C checksum. - -The stream is composed of contiguous chunks prefixed by a 4 byte header. The first byte indicates the chunk type, which in practice is always 0 for iWork, indicating a Snappy compressed chunk. The next three bytes are interpreted as a 24-bit little-endian integer indicating the length of the chunk. The 4 byte header is not included in the chunk length. - -### Protobuf -The uncompresed IWA contains the Component's objects, serialized consecutively in a [Protobuf](https://code.google.com/p/protobuf/) stream. Each object begins with a [varint](https://developers.google.com/protocol-buffers/docs/encoding#varints) representing the length of the [ArchiveInfo](#archiveinfo) message, followed by the `ArchiveInfo` message itself. The `ArchiveInfo` includes a variable number of [MessageInfo](#messageinfo) messages describing the encoded [Payloads](#payload) that follow, though in practice iWork files seem to only have one payload message per `ArchiveInfo`. - - Object 0 varint archiveInfoLength - ArchiveInfo archiveInfo - (payload) - - Object 1 varint archiveInfoLength - ArchiveInfo archiveInfo - (payload) - - ... - - Object n varint archiveInfoLength - ArchiveInfo archiveInfo - (payload) - -### ArchiveInfo - -The `ArchiveInfo` message contains the object's `identifier` (unique across the document), as well as information about the encoded messages (see [MessageInfo](#messageinfo)). - - message ArchiveInfo { - optional uint64 identifier = 1; - repeated MessageInfo message_infos = 2; - } - -### MessageInfo - -The `MessageInfo` message describes the encoded payload that follows the `ArchiveInfo`. The `type` field indicates how the payload should be decoded (see [TSPRegistry](#tspregistry)), the `version` field indicates what format version was used to encode (currently 1.0.5), and the `length` field specifies how much data follows. The `field_infos` field would allow for deep introspection into the format of the payload, but it is absent from all archives I have inspected. It's possible that it is meant for backwards compatibility when new fields are introduced. The `object_references` and `data_references` fields are for bookkeeping/cross-referencing. - - message MessageInfo { - required uint32 type = 1; - repeated uint32 version = 2 [packed = true]; - required uint32 length = 3; - repeated FieldInfo field_infos = 4; - repeated uint64 object_references = 5 [packed = true]; - repeated uint64 data_references = 6 [packed = true]; - } - -### Payload -The format of the payload is determined by the `type` field of the associated `MessageInfo` message. The iWork applications manually map these integer values to their respective Protobuf message types, and the mappings vary slightly between Keynote, Pages and Numbers. This information can be recovered by inspecting the [TSPRegistry](#tspregistry) class at runtime. - -Because Protobuf is not a self-describing format, applications attempting to understand the payloads must know a great deal about the data types and hierarchy of the objects serialized by iWork. Fortunately, all of this information can be recovered from the iWork binaries using [proto-dump](https://github.com/obriensp/proto-dump). - -A full dump of the Protobuf messages can be found [here](../iWorkFileInspector/iWorkFileInspector/Messages/Proto/). - -### TSPRegistry -The mapping between an object's `MessageInfo.type` and its respective Protobuf message type must by extracted from the iWork applications at runtime. Attaching to Keynote via a debugger and inspecting `[TSPRegistry sharedRegistry]` shows: - - 0x102f24680 KN.ChartInfoGeometryCommandArchive - 147 -> 0x102f24650 KN.SlideCollectionCommandSelectionBehaviorArchive - 146 -> 0x102f24560 KN.CommandSlideReapplyMasterArchive - 145 -> 0x102f24420 KN.CommandMasterSetBodyStylesArchive - ... - -A full list of the type mappings can be found [here](../iWorkFileInspector/iWorkFileInspector/Persistence/MessageTypes/). - -## Encryption -If the document is locked with a password, nearly all files in the bundle are encrypted using [AES128](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard) encryption with [PKCS7](http://en.wikipedia.org/wiki/Padding_\(cryptography\)#PKCS7) padding. For a full description of the encryption format, see [iWork Encrypted Stream](iWork Encrypted Stream.md). \ No newline at end of file +[2013](2013) +[2015+](2015) \ No newline at end of file diff --git a/iWorkFileInspector/iWorkFileInspector.xcodeproj/project.xcworkspace/xcuserdata/pascal.xcuserdatad/UserInterfaceState.xcuserstate b/iWorkFileInspector/iWorkFileInspector.xcodeproj/project.xcworkspace/xcuserdata/pascal.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..f5d85f41e405a61eeff6240b697ddd1688c68116 GIT binary patch literal 7912 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 literal 0 HcmV?d00001 diff --git a/iWorkFileInspector/iWorkFileInspector.xcodeproj/xcuserdata/pascal.xcuserdatad/xcschemes/xcschememanagement.plist b/iWorkFileInspector/iWorkFileInspector.xcodeproj/xcuserdata/pascal.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..3c6a247 --- /dev/null +++ b/iWorkFileInspector/iWorkFileInspector.xcodeproj/xcuserdata/pascal.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,19 @@ + + + + + SuppressBuildableAutocreation + + 576B645D18228DDE005D22E3 + + primary + + + 576B648118228DDE005D22E3 + + primary + + + + + From cc9f2f177f8559af7110c993d62c1abac85a8d8e Mon Sep 17 00:00:00 2001 From: Pasquale Ambrosini Date: Wed, 8 Jun 2016 18:22:28 +0400 Subject: [PATCH 3/3] Updated the code and documentation for the new iWork format --- .DS_Store | Bin 6148 -> 6148 bytes Docs/2015.md | 23 ++--- Docs/index.md | 4 +- .../UserInterfaceState.xcuserstate | Bin 7912 -> 21615 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 5 + .../iWorkFileInspector/.DS_Store | Bin 0 -> 6148 bytes .../iWorkFileInspector/Bundle/IWBundle.h | 6 ++ .../iWorkFileInspector/Bundle/IWBundle.m | 43 +++++++-- .../iWorkFileInspector/Document/IWDocument.mm | 16 +--- .../Document/IWDocument.xib | 15 +-- .../Target/iWorkFileInspector-Info.plist | 88 ++++++++++++++++-- 11 files changed, 150 insertions(+), 50 deletions(-) create mode 100644 iWorkFileInspector/iWorkFileInspector.xcodeproj/xcuserdata/pascal.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 iWorkFileInspector/iWorkFileInspector/.DS_Store diff --git a/.DS_Store b/.DS_Store index fe6069fb381dc452c5b62d277cf1d7dd20fa78ef..ec17b682da4d0ae1957615768ef7719866c6ef89 100644 GIT binary patch delta 30 kcmZoMXffDujfKh7bh0d)$7BW8_{ml*bAa5Overview The iWork '15+ format is a [bundle](https://developer.apple.com/library/mac/documentation/corefoundation/conceptual/cfbundles/DocumentPackages/DocumentPackages.html)-based format built on top of several open source projects. This document describes the physical layout of files contained in these bundles and the algorithms involved, but does not attempt to describe the nature of the represented object graph. +## What does work + +It works in the same way of the old project, but now you can choose also to open the new file format (2015+) + +## What doesn't + +Documents protected with password, we need to investigate about this because something is changed in the new project format (there is no .iwph file) + ## Bundle The organization of an iWork document bundle is fairly straightforward. Media such as images and videos are stored in the `Data` subdirectory, serialized objects are stored in [Index](#index), some light metadata is stored in the `Metadata` subdirectory, and a few preview images are stored in the top level of the bundle. - So basically the new format is the same of the 2013 but the `Photo Essay.key` is a zip file and Index is a folder and not a zip file +So basically the new format is the same of the 2013 but the `Photo Essay.key` is a zip file and Index is a folder and not a zip file + Photo Essay.key/ Data/ @@ -33,18 +42,6 @@ The organization of an iWork document bundle is fairly straightforward. Media su preview-web.jpg preview.jpg -## Index.zip -A document's objects are organized into groups called Components. Each Component is serialized into the [IWA](#iwa) format and stored in Index.zip. - - Index/ - AnnotationAuthorStorage.iwa - CalculationEngine.iwa - Document.iwa - DocumentStylesheet.iwa - MasterSlide-1.iwa - MasterSlide-10.iwa - MasterSlide-11.iwa - ... Curiously, the zip implementation iWork uses for this file is extremely limited. It does not support any form of compression or extensions like Zip64. Simply expanding Index.zip and then recreating it with a standard zip utility will result in a document that iWork refuses to open. diff --git a/Docs/index.md b/Docs/index.md index 1d0cd6d..1d4b503 100644 --- a/Docs/index.md +++ b/Docs/index.md @@ -2,5 +2,5 @@ There are 2 file format of the iWork File: -[2013](2013) -[2015+](2015) \ No newline at end of file +[2013](2013.md) +[2015+](2015.md) \ No newline at end of file diff --git a/iWorkFileInspector/iWorkFileInspector.xcodeproj/project.xcworkspace/xcuserdata/pascal.xcuserdatad/UserInterfaceState.xcuserstate b/iWorkFileInspector/iWorkFileInspector.xcodeproj/project.xcworkspace/xcuserdata/pascal.xcuserdatad/UserInterfaceState.xcuserstate index f5d85f41e405a61eeff6240b697ddd1688c68116..84d58ce115c6b5c102da9ef5ade8ce5b3072c1fc 100644 GIT binary patch literal 21615 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�bPZCAan+O68F+NXL)bwG7g^^xk7>a^+;)dkg$s$W#U zsjjK9no+x{J=NaoFm<>(LLH?}QKzcY)EVl0b*cI;b$|6Bb)|ZgdW^bGU9UE(o76V- z95qqTS1(ZCr(UjJp+jL3}2jLlq{xi<63%#O_USqjL@=Vaw&>9V$G?aA7k^;Xu~ z*}2&z*=5;xW%tj1C;NEziR@F^XL1JQ)a2CWjLE6XIgoQA=Ty$=oU^%Oa!t9Db6axT za?j;n%Ds|%HTQb%jXWyPE6+F2KQAyZI4?9WE3Y0}Thcrht$2BK3A8XEN zzSLaST-9<~KW%_ENE@n+&?aaTwJF*(tx~Jj>a-Qw;o5rbWNoW+IzM4 zYah}s(yr7#sokvIq1~l@L;IHYZS4W=QSC?CQ`*zov)XgoZ?!*ZZ|K~0o;q)xuTG*1 z(?#lHbaA=_okFM7>2#&Kp}Jb#SlxJCgKmP(th4Cab<=b+b+dH~bc=P5>Ne;$>z>j* ztJ|jAu6slGk?srKFS_4!*K~j8qkKA_%lF9l&X3BE&5zGd$WP2q$xqK$PThOt!Pfsg1#5}Ug~?Lm?`!u4k(T(PAgUxXBOuaYl`!W zi;4#n4=%1Ot|}f;TvJ?IJf@g0-dOx$@ijfI_tH!CA^KQ-qCQQZuP@Y>>nrpF^n>&x z^po{1`Zm2)KUF_NKU+Uff46>t{(k*~`c?YX`p5N8l=zf{mqeCCm&BDUD|w=1T}fxj zhSJ2+?9$v)O=*7V&e8*=2TMOFJzQ2$R#7&fY*1Nc*`cyCWoOIIm3>iOQ$DHOT;ATD Qgrmg2+;^@?xbkWL2U|>$;Q#;t delta 5074 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 diff --git a/iWorkFileInspector/iWorkFileInspector.xcodeproj/xcuserdata/pascal.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/iWorkFileInspector/iWorkFileInspector.xcodeproj/xcuserdata/pascal.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..fe2b454 --- /dev/null +++ b/iWorkFileInspector/iWorkFileInspector.xcodeproj/xcuserdata/pascal.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/iWorkFileInspector/iWorkFileInspector/.DS_Store b/iWorkFileInspector/iWorkFileInspector/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4314f7e1b60adb568e681cb12f26cc9d06b7c131 GIT binary patch literal 6148 zcmeHKI|@QE5ZqM}!N$@uSMUZw^aOeU1;s`bM6F-txjdS)pGKc{+Q=+yCfV#HWQwi0p zHi3x1G^oI!YPJ{}bi_;M)x;(+=%U$tXx^;Zp{U=E^NXj8)i-=6 zq5pp-aYY5Fz+Wk#z1dc79(z*c6`Nzf VCN_aiN8IT^{tTEdG%E0G1s-d(6^8%- literal 0 HcmV?d00001 diff --git a/iWorkFileInspector/iWorkFileInspector/Bundle/IWBundle.h b/iWorkFileInspector/iWorkFileInspector/Bundle/IWBundle.h index 0d03232..9cc91fc 100644 --- a/iWorkFileInspector/iWorkFileInspector/Bundle/IWBundle.h +++ b/iWorkFileInspector/iWorkFileInspector/Bundle/IWBundle.h @@ -7,6 +7,11 @@ #import +typedef enum { + IWBundleType2015, + IWBundleType2013 +} IWBundleType; + @class IWBundleProperties, IWPasswordVerifier; @@ -16,6 +21,7 @@ - (instancetype)initWithURL:(NSURL *)fileURL decryptionKey:(NSData *)decryptionKey; @property(readonly) NSArray *componentNames; +@property (assign, readonly) IWBundleType bundleType; - (NSData *)dataForComponentName:(NSString *)componentName; diff --git a/iWorkFileInspector/iWorkFileInspector/Bundle/IWBundle.m b/iWorkFileInspector/iWorkFileInspector/Bundle/IWBundle.m index 702921e..787e321 100644 --- a/iWorkFileInspector/iWorkFileInspector/Bundle/IWBundle.m +++ b/iWorkFileInspector/iWorkFileInspector/Bundle/IWBundle.m @@ -36,7 +36,25 @@ - (instancetype)initWithURL:(NSURL *)fileURL decryptionKey:(NSData *)decryptionK return nil; } - _objectArchive = [[IWZipArchive alloc] initWithURL:[fileURL URLByAppendingPathComponent:IWBundleComponentZipFileName]]; + BOOL isDirectory; + + if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL.absoluteString stringByReplacingOccurrencesOfString:@"file://" withString:@"/"] isDirectory:&isDirectory]) { + if (!isDirectory) { + _bundleType = IWBundleType2015; + }else{ + _bundleType = IWBundleType2013; + } + + }else{ + return nil; + } + + if (self.bundleType == IWBundleType2013) { + _objectArchive = [[IWZipArchive alloc] initWithURL:[fileURL URLByAppendingPathComponent:IWBundleComponentZipFileName]]; + }else if (self.bundleType == IWBundleType2015) { + _objectArchive = [[IWZipArchive alloc] initWithURL:fileURL]; + } + if (_objectArchive == nil) { return nil; } @@ -91,12 +109,23 @@ - (NSData *)dataForComponentName:(NSString *)componentName + (BOOL)validBundleExistsAtURL:(NSURL *)fileURL { - if (!fileURL.isFileURL) { - return NO; - } - - NSURL *componentArchiveURL = [fileURL URLByAppendingPathComponent:IWBundleComponentZipFileName]; - return [componentArchiveURL checkResourceIsReachableAndReturnError:NULL]; + //For 2015+ + BOOL isDirectory; + if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL.absoluteString stringByReplacingOccurrencesOfString:@"file://" withString:@"/"] isDirectory:&isDirectory]) { + return NO; + + } + if (!isDirectory) { + IWZipArchive *tempArchive = [[IWZipArchive alloc] initWithURL:fileURL]; + if (tempArchive && [tempArchive dataForEntryName:@"Index/Document.iwa"]) { + return YES; + } + return NO; + + }else{ //For 2013 + NSURL *componentArchiveURL = [fileURL URLByAppendingPathComponent:IWBundleComponentZipFileName]; + return [componentArchiveURL checkResourceIsReachableAndReturnError:NULL]; + } } + (IWBundleProperties *)propertiesForBundleURL:(NSURL *)fileURL diff --git a/iWorkFileInspector/iWorkFileInspector/Document/IWDocument.mm b/iWorkFileInspector/iWorkFileInspector/Document/IWDocument.mm index 953c424..f3e13d6 100644 --- a/iWorkFileInspector/iWorkFileInspector/Document/IWDocument.mm +++ b/iWorkFileInspector/iWorkFileInspector/Document/IWDocument.mm @@ -76,12 +76,8 @@ - (void)showWindows - (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError { - if (!url.isFileURL) { - return NO; - } - - // Make sure it's an iWork '13 file. We don't support other iWork formats. - if (![IWBundle validBundleExistsAtURL:url]) { + // Make sure it's an iWork file (2013 or 2015) + if (![IWBundle validBundleExistsAtURL:url]) { return NO; } @@ -131,11 +127,9 @@ - (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)o // Load the messages from each component. for (NSString *componentName in _componentNames) { NSArray *documentMessages = [self readDocumentMessagesForComponentName:componentName messageTypeRegistry:messageTypeRegistry]; - if (documentMessages == nil) { - return NO; - } - - documentMessagesByComponentName[componentName] = documentMessages; + if (documentMessages != nil) { + documentMessagesByComponentName[componentName] = documentMessages; + } } _documentMessagesByComponentName = documentMessagesByComponentName; diff --git a/iWorkFileInspector/iWorkFileInspector/Document/IWDocument.xib b/iWorkFileInspector/iWorkFileInspector/Document/IWDocument.xib index aa5f51d..f16a07a 100644 --- a/iWorkFileInspector/iWorkFileInspector/Document/IWDocument.xib +++ b/iWorkFileInspector/iWorkFileInspector/Document/IWDocument.xib @@ -1,7 +1,8 @@ - + - + + @@ -14,7 +15,7 @@ - + @@ -42,7 +43,7 @@ - + @@ -90,7 +91,7 @@ - + @@ -128,6 +129,6 @@ - + - \ No newline at end of file + diff --git a/iWorkFileInspector/iWorkFileInspector/Target/iWorkFileInspector-Info.plist b/iWorkFileInspector/iWorkFileInspector/Target/iWorkFileInspector-Info.plist index 9bfa39b..6901fe0 100644 --- a/iWorkFileInspector/iWorkFileInspector/Target/iWorkFileInspector-Info.plist +++ b/iWorkFileInspector/iWorkFileInspector/Target/iWorkFileInspector-Info.plist @@ -8,11 +8,13 @@ CFBundleTypeIconFile - + KeyDocument CFBundleTypeName com.apple.iwork.keynote.document CFBundleTypeRole - Viewer + Editor + LSHandlerRank + Owner LSItemContentTypes com.apple.iwork.keynote.key @@ -21,39 +23,85 @@ IWDocument NSIsRelatedItemType + NSUbiquitousDocumentUserActivityType + com.apple.keynote.documentEditing CFBundleTypeIconFile - + KeyDocument CFBundleTypeName - com.apple.iwork.pages.document + com.apple.iwork.keynote.alt-document CFBundleTypeRole - Viewer + Editor + LSHandlerRank + Owner LSItemContentTypes - com.apple.iwork.pages.pages + com.apple.iwork.keynote.sffkey + com.apple.iwork.keynote.key-tef NSDocumentClass IWDocument NSIsRelatedItemType + NSUbiquitousDocumentUserActivityType + com.apple.keynote.documentEditing CFBundleTypeIconFile - + KeynoteTheme CFBundleTypeName - com.apple.iwork.numbers.document + com.apple.iwork.keynote.template CFBundleTypeRole - Viewer + Editor + LSHandlerRank + Owner LSItemContentTypes - com.apple.iwork.numbers.numbers + com.apple.iwork.keynote.kth + com.apple.iwork.keynote.sffkth NSDocumentClass IWDocument NSIsRelatedItemType + + CFBundleTypeName + com.apple.iwork.keynote.powerpoint + CFBundleTypeRole + Editor + LSHandlerRank + Default + LSItemContentTypes + + com.microsoft.powerpoint.ppt + org.openxmlformats.presentationml.presentation + org.openxmlformats.presentationml.presentation.macroenabled + com.microsoft.powerpoint.pps + org.openxmlformats.presentationml.slideshow + org.openxmlformats.presentationml.slideshow.macroenabled + com.microsoft.powerpoint.pot + org.openxmlformats.presentationml.template + org.openxmlformats.presentationml.template.macroenabled + + NSDocumentClass + IWDocument + + + CFBundleTypeName + com.apple.iwork.keynote.pd-import + CFBundleTypeRole + Editor + LSItemContentTypes + + com.apple.iwork.keynote.kpdc + + LSTypeIsPackage + 0 + NSDocumentClass + KNMacPresenterDisplayConfigurationDocument + CFBundleExecutable ${EXECUTABLE_NAME} @@ -101,6 +149,26 @@ + + UTTypeConformsTo + + com.apple.package + public.presentation + + UTTypeDescription + Keynote Presentation + UTTypeIconFile + KeyDocument + UTTypeIdentifier + com.apple.keynote.key + UTTypeTagSpecification + + public.filename-extension + + key + + + UTTypeConformsTo