diff --git a/SabreTools.Serialization/Deserializers/PKZIP.cs b/SabreTools.Serialization/Deserializers/PKZIP.cs
index 8c48226d..8fec2abf 100644
--- a/SabreTools.Serialization/Deserializers/PKZIP.cs
+++ b/SabreTools.Serialization/Deserializers/PKZIP.cs
@@ -138,6 +138,26 @@ namespace SabreTools.Serialization.Deserializers
#endregion
+ #region Archive Extra Data Record
+
+ // Find the archive extra data record
+ long aedrOffset = SearchForArchiveExtraDataRecord(data, cdrOffset);
+ if (aedrOffset >= 0 && aedrOffset < data.Length)
+ {
+ // Seek to the archive extra data record
+ data.Seek(aedrOffset, SeekOrigin.Begin);
+
+ // Read the archive extra data record
+ var aedr = ParseArchiveExtraDataRecord(data);
+ if (aedr == null)
+ return null;
+
+ // Assign the archive extra data record
+ archive.ArchiveExtraDataRecord = aedr;
+ }
+
+ #endregion
+
#region Local File
// Setup all of the collections
@@ -260,7 +280,6 @@ namespace SabreTools.Serialization.Deserializers
#endregion
// TODO: Handle archive decryption header
- // TODO: Handle archive extra data record
return archive;
}
@@ -467,6 +486,68 @@ namespace SabreTools.Serialization.Deserializers
return header;
}
+ ///
+ /// Search for the archive extra data record
+ ///
+ /// Stream to parse
+ /// Offset to the first central directory record
+ /// Position of the archive extra data record, -1 on error
+ public static long SearchForArchiveExtraDataRecord(Stream data, long centralDirectoryoffset)
+ {
+ // Cache the current offset
+ long current = data.Position;
+
+ // Seek to the minimum size of the record from the central directory
+ data.Seek(centralDirectoryoffset - 8, SeekOrigin.Begin);
+
+ // Attempt to find the end of central directory signature
+ while (data.Position > 0)
+ {
+ // Read the potential signature
+ uint possibleSignature = data.ReadUInt32();
+ if (possibleSignature == ArchiveExtraDataRecordSignature)
+ {
+ long signaturePosition = data.Position - 4;
+ data.Seek(current, SeekOrigin.Begin);
+ return signaturePosition;
+ }
+
+ // Seek backward 5 bytes, if possible
+ data.Seek(-5, SeekOrigin.Current);
+ }
+
+ // No signature was found
+ data.Seek(current, SeekOrigin.Begin);
+ return -1;
+ }
+
+ ///
+ /// Parse a Stream into an archive extra data record
+ ///
+ /// Stream to parse
+ /// Filled archive extra data record on success, null on error
+ public static ArchiveExtraDataRecord? ParseArchiveExtraDataRecord(Stream data)
+ {
+ // TODO: Use marshalling here instead of building
+ var record = new ArchiveExtraDataRecord();
+
+ record.Signature = data.ReadUInt32();
+ if (record.Signature != ArchiveExtraDataRecordSignature)
+ return null;
+
+ record.ExtraFieldLength = data.ReadUInt32();
+ if (record.ExtraFieldLength > 0)
+ {
+ byte[] extraBytes = data.ReadBytes((int)record.ExtraFieldLength);
+ if (extraBytes.Length != record.ExtraFieldLength)
+ return null;
+
+ record.ExtraFieldData = extraBytes;
+ }
+
+ return record;
+ }
+
///
/// Parse a Stream into a local file header
///