From 044e4c4c75577856007013a74a17c1d4610adf9e Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Wed, 27 Aug 2025 21:48:01 -0400 Subject: [PATCH] Fill out remaining models, add printing --- .../Deserializers/PKZIP.cs | 166 +++++++++++- SabreTools.Serialization/Printers/PKZIP.cs | 240 +++++++++++++++++- 2 files changed, 389 insertions(+), 17 deletions(-) diff --git a/SabreTools.Serialization/Deserializers/PKZIP.cs b/SabreTools.Serialization/Deserializers/PKZIP.cs index b4e5d23f..cdb4ec7b 100644 --- a/SabreTools.Serialization/Deserializers/PKZIP.cs +++ b/SabreTools.Serialization/Deserializers/PKZIP.cs @@ -618,8 +618,11 @@ namespace SabreTools.Serialization.Deserializers /// /// Byte array to parse /// Array of data fields on success, null otherwise - public static ExtensibleDataField[]? ParseExtraFields(CentralDirectoryFileHeader header, byte[] data) + public static ExtensibleDataField[]? ParseExtraFields(CentralDirectoryFileHeader header, byte[]? data) { + if (data == null) + return null; + List fields = []; int offset = 0; @@ -644,13 +647,13 @@ namespace SabreTools.Serialization.Deserializers HeaderID.PKCSStore => ParsePKCS7Store(data, ref offset), HeaderID.X509IndividualFile => ParseX509IndividualFile(data, ref offset), HeaderID.X509CentralDirectory => ParseX509CentralDirectory(data, ref offset), - HeaderID.StrongEncryptionHeader => ParseUnknownExtraField(data, ref offset), // TODO: Implement + HeaderID.StrongEncryptionHeader => ParseStrongEncryptionHeader(data, ref offset), HeaderID.RecordManagementControls => ParseRecordManagementControls(data, ref offset), HeaderID.PKCSCertificateList => ParsePKCS7EncryptionRecipientCertificateList(data, ref offset), HeaderID.Timestamp => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.PolicyDecryptionKey => ParsePolicyDecryptionKeyRecordExtraField(data, ref offset), - HeaderID.SmartcryptKeyProvider => ParseUnknownExtraField(data, ref offset), // TODO: Implement - HeaderID.SmartcryptPolicyKeyData => ParseUnknownExtraField(data, ref offset), // TODO: Implement + HeaderID.SmartcryptKeyProvider => ParseKeyProviderRecordExtraField(data, ref offset), + HeaderID.SmartcryptPolicyKeyData => ParsePolicyKeyDataRecordRecordExtraField(data, ref offset), HeaderID.IBMS390AttributesUncompressed => ParseAS400ExtraFieldAttribute(data, ref offset), HeaderID.IBMS390AttributesCompressed => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.POSZIP4690 => ParseUnknownExtraField(data, ref offset), // TODO: Implement @@ -665,7 +668,7 @@ namespace SabreTools.Serialization.Deserializers HeaderID.VMCMS => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.MVS => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.THEOSold => ParseUnknownExtraField(data, ref offset), // TODO: Implement - HeaderID.FWKCSMD5 => ParseUnknownExtraField(data, ref offset), // TODO: Implement + HeaderID.FWKCSMD5 => ParseFWKCSMD5ExtraField(data, ref offset), HeaderID.OS2AccessControlList => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.InfoZIPOpenVMS => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.MacintoshSmartzip => ParseUnknownExtraField(data, ref offset), // TODO: Implement @@ -682,8 +685,8 @@ namespace SabreTools.Serialization.Deserializers HeaderID.ASiUNIX => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.InfoZIPUNIXNew => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.InfoZIPUNIXNewer => ParseUnknownExtraField(data, ref offset), // TODO: Implement - HeaderID.DataStreamAlignment => ParseUnknownExtraField(data, ref offset), // TODO: Implement - HeaderID.MicrosoftOpenPackagingGrowthHint => ParseUnknownExtraField(data, ref offset), // TODO: Implement + HeaderID.DataStreamAlignment => ParseDataStreamAlignment(data, ref offset), + HeaderID.MicrosoftOpenPackagingGrowthHint => ParseMicrosoftOpenPackagingGrowthHint(data, ref offset), HeaderID.JavaJAR => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.AndroidZIPAlignment => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.KoreanZIPCodePage => ParseUnknownExtraField(data, ref offset), // TODO: Implement @@ -706,8 +709,11 @@ namespace SabreTools.Serialization.Deserializers /// /// Byte array to parse /// Array of data fields on success, null otherwise - public static ExtensibleDataField[]? ParseExtraFields(LocalFileHeader header, byte[] data) + public static ExtensibleDataField[]? ParseExtraFields(LocalFileHeader header, byte[]? data) { + if (data == null) + return null; + List fields = []; int offset = 0; @@ -732,13 +738,13 @@ namespace SabreTools.Serialization.Deserializers HeaderID.PKCSStore => ParsePKCS7Store(data, ref offset), HeaderID.X509IndividualFile => ParseX509IndividualFile(data, ref offset), HeaderID.X509CentralDirectory => ParseX509CentralDirectory(data, ref offset), - HeaderID.StrongEncryptionHeader => ParseUnknownExtraField(data, ref offset), // TODO: Implement + HeaderID.StrongEncryptionHeader => ParseStrongEncryptionHeader(data, ref offset), HeaderID.RecordManagementControls => ParseRecordManagementControls(data, ref offset), HeaderID.PKCSCertificateList => ParsePKCS7EncryptionRecipientCertificateList(data, ref offset), HeaderID.Timestamp => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.PolicyDecryptionKey => ParsePolicyDecryptionKeyRecordExtraField(data, ref offset), - HeaderID.SmartcryptKeyProvider => ParseUnknownExtraField(data, ref offset), // TODO: Implement - HeaderID.SmartcryptPolicyKeyData => ParseUnknownExtraField(data, ref offset), // TODO: Implement + HeaderID.SmartcryptKeyProvider => ParseKeyProviderRecordExtraField(data, ref offset), + HeaderID.SmartcryptPolicyKeyData => ParsePolicyKeyDataRecordRecordExtraField(data, ref offset), HeaderID.IBMS390AttributesUncompressed => ParseAS400ExtraFieldAttribute(data, ref offset), HeaderID.IBMS390AttributesCompressed => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.POSZIP4690 => ParseUnknownExtraField(data, ref offset), // TODO: Implement @@ -753,7 +759,7 @@ namespace SabreTools.Serialization.Deserializers HeaderID.VMCMS => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.MVS => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.THEOSold => ParseUnknownExtraField(data, ref offset), // TODO: Implement - HeaderID.FWKCSMD5 => ParseUnknownExtraField(data, ref offset), // TODO: Implement + HeaderID.FWKCSMD5 => ParseFWKCSMD5ExtraField(data, ref offset), HeaderID.OS2AccessControlList => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.InfoZIPOpenVMS => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.MacintoshSmartzip => ParseUnknownExtraField(data, ref offset), // TODO: Implement @@ -770,8 +776,8 @@ namespace SabreTools.Serialization.Deserializers HeaderID.ASiUNIX => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.InfoZIPUNIXNew => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.InfoZIPUNIXNewer => ParseUnknownExtraField(data, ref offset), // TODO: Implement - HeaderID.DataStreamAlignment => ParseUnknownExtraField(data, ref offset), // TODO: Implement - HeaderID.MicrosoftOpenPackagingGrowthHint => ParseUnknownExtraField(data, ref offset), // TODO: Implement + HeaderID.DataStreamAlignment => ParseDataStreamAlignment(data, ref offset), + HeaderID.MicrosoftOpenPackagingGrowthHint => ParseMicrosoftOpenPackagingGrowthHint(data, ref offset), HeaderID.JavaJAR => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.AndroidZIPAlignment => ParseUnknownExtraField(data, ref offset), // TODO: Implement HeaderID.KoreanZIPCodePage => ParseUnknownExtraField(data, ref offset), // TODO: Implement @@ -1106,6 +1112,30 @@ namespace SabreTools.Serialization.Deserializers return obj; } + /// + /// Parse a Stream into a StrongEncryptionHeader + /// + /// Byte array to parse + /// Offset into the byte array + /// Filled StrongEncryptionHeader on success, null on error + private static StrongEncryptionHeader? ParseStrongEncryptionHeader(byte[] data, ref int offset) + { + var obj = new StrongEncryptionHeader(); + + obj.HeaderID = (HeaderID)data.ReadUInt16LittleEndian(ref offset); + if (obj.HeaderID != HeaderID.StrongEncryptionHeader) + return null; + + obj.DataSize = data.ReadUInt16LittleEndian(ref offset); + obj.Format = data.ReadUInt16LittleEndian(ref offset); + obj.AlgID = data.ReadUInt16LittleEndian(ref offset); + obj.Bitlen = data.ReadUInt16LittleEndian(ref offset); + obj.Flags = data.ReadUInt16LittleEndian(ref offset); + obj.CertData = data.ReadBytes(ref offset, obj.DataSize - 8); + + return obj; + } + /// /// Parse a Stream into an RecordManagementControls /// @@ -1188,12 +1218,56 @@ namespace SabreTools.Serialization.Deserializers return obj; } + /// + /// Parse a Stream into a KeyProviderRecordExtraField + /// + /// Byte array to parse + /// Offset into the byte array + /// Filled KeyProviderRecordExtraField on success, null on error + private static KeyProviderRecordExtraField? ParseKeyProviderRecordExtraField(byte[] data, ref int offset) + { + var obj = new KeyProviderRecordExtraField(); + + obj.HeaderID = (HeaderID)data.ReadUInt16LittleEndian(ref offset); + if (obj.HeaderID != HeaderID.SmartcryptKeyProvider) + return null; + + obj.DataSize = data.ReadUInt16LittleEndian(ref offset); + obj.TData = data.ReadBytes(ref offset, obj.DataSize); + + return obj; + } + + /// + /// Parse a Stream into a PolicyKeyDataRecordRecordExtraField + /// + /// Byte array to parse + /// Offset into the byte array + /// Filled PolicyKeyDataRecordRecordExtraField on success, null on error + private static PolicyKeyDataRecordRecordExtraField? ParsePolicyKeyDataRecordRecordExtraField(byte[] data, ref int offset) + { + var obj = new PolicyKeyDataRecordRecordExtraField(); + + obj.HeaderID = (HeaderID)data.ReadUInt16LittleEndian(ref offset); + if (obj.HeaderID != HeaderID.SmartcryptPolicyKeyData) + return null; + + obj.DataSize = data.ReadUInt16LittleEndian(ref offset); + obj.TData = data.ReadBytes(ref offset, obj.DataSize); + + return obj; + } + /// /// Parse a Stream into a AS400ExtraFieldAttribute /// /// Byte array to parse /// Offset into the byte array /// Filled AS400ExtraFieldAttribute on success, null on error + /// + /// This header ID is shared with MVSExtraField, OS400ExtraField, and ZOSExtraFieldAttribute. + /// This code makes an assumption that it's always AS400ExtraFieldAttribute. + /// private static AS400ExtraFieldAttribute? ParseAS400ExtraFieldAttribute(byte[] data, ref int offset) { var obj = new AS400ExtraFieldAttribute(); @@ -1289,6 +1363,27 @@ namespace SabreTools.Serialization.Deserializers return obj; } + /// + /// Parse a Stream into a FWKCSMD5ExtraField + /// + /// Byte array to parse + /// Offset into the byte array + /// Filled FWKCSMD5ExtraField on success, null on error + private static FWKCSMD5ExtraField? ParseFWKCSMD5ExtraField(byte[] data, ref int offset) + { + var obj = new FWKCSMD5ExtraField(); + + obj.HeaderID = (HeaderID)data.ReadUInt16LittleEndian(ref offset); + if (obj.HeaderID != HeaderID.FWKCSMD5) + return null; + + obj.DataSize = data.ReadUInt16LittleEndian(ref offset); + obj.Preface = data.ReadBytes(ref offset, 3); + obj.MD5 = data.ReadBytes(ref offset, 16); + + return obj; + } + /// /// Parse a Stream into a InfoZIPUnicodeCommentExtraField /// @@ -1335,6 +1430,49 @@ namespace SabreTools.Serialization.Deserializers return obj; } + /// + /// Parse a Stream into a DataStreamAlignment + /// + /// Byte array to parse + /// Offset into the byte array + /// Filled DataStreamAlignment on success, null on error + private static DataStreamAlignment? ParseDataStreamAlignment(byte[] data, ref int offset) + { + var obj = new DataStreamAlignment(); + + obj.HeaderID = (HeaderID)data.ReadUInt16LittleEndian(ref offset); + if (obj.HeaderID != HeaderID.DataStreamAlignment) + return null; + + obj.DataSize = data.ReadUInt16LittleEndian(ref offset); + obj.Alignment = data.ReadUInt16LittleEndian(ref offset); + obj.Padding = data.ReadBytes(ref offset, obj.DataSize - 2); + + return obj; + } + + /// + /// Parse a Stream into a MicrosoftOpenPackagingGrowthHint + /// + /// Byte array to parse + /// Offset into the byte array + /// Filled MicrosoftOpenPackagingGrowthHint on success, null on error + private static MicrosoftOpenPackagingGrowthHint? ParseMicrosoftOpenPackagingGrowthHint(byte[] data, ref int offset) + { + var obj = new MicrosoftOpenPackagingGrowthHint(); + + obj.HeaderID = (HeaderID)data.ReadUInt16LittleEndian(ref offset); + if (obj.HeaderID != HeaderID.MicrosoftOpenPackagingGrowthHint) + return null; + + obj.DataSize = data.ReadUInt16LittleEndian(ref offset); + obj.Sig = data.ReadUInt16LittleEndian(ref offset); + obj.PadVal = data.ReadUInt16LittleEndian(ref offset); + obj.Padding = data.ReadBytes(ref offset, obj.DataSize - 2); + + return obj; + } + #endregion #region Helpers diff --git a/SabreTools.Serialization/Printers/PKZIP.cs b/SabreTools.Serialization/Printers/PKZIP.cs index 0f0a0d58..1a58b449 100644 --- a/SabreTools.Serialization/Printers/PKZIP.cs +++ b/SabreTools.Serialization/Printers/PKZIP.cs @@ -8,7 +8,7 @@ namespace SabreTools.Serialization.Printers { /// public void PrintInformation(StringBuilder builder, Archive model) - => Print(builder, model); + => Print(builder, model); public static void Print(StringBuilder builder, Archive archive) { @@ -87,7 +87,9 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(localFileHeader.FileNameLength, " [Local File Header] File name length"); builder.AppendLine(localFileHeader.ExtraFieldLength, " [Local File Header] Extra field length"); builder.AppendLine(localFileHeader.FileName, " [Local File Header] File name"); - builder.AppendLine(localFileHeader.ExtraField, " [Local File Header] Extra field"); + + var extraFields = Deserializers.PKZIP.ParseExtraFields(localFileHeader, localFileHeader.ExtraField); + Print(builder, " [Local File Header] Extra Fields", extraFields); if (encryptionHeader == null) { @@ -236,8 +238,10 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(entry.ExternalFileAttributes, " External file attributes"); builder.AppendLine(entry.RelativeOffsetOfLocalHeader, " Relative offset of local header"); builder.AppendLine(entry.FileName, " File name"); - builder.AppendLine(entry.ExtraField, " Extra field"); builder.AppendLine(entry.FileComment, " File comment"); + + var extraFields = Deserializers.PKZIP.ParseExtraFields(entry, entry.ExtraField); + Print(builder, " Extra Fields", extraFields); } builder.AppendLine(); @@ -259,5 +263,235 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(record.ExtraFieldData, " Extra field data"); builder.AppendLine(); } + + #region Extras Fields + + private static void Print(StringBuilder builder, string title, ExtensibleDataField[]? entries) + { + builder.AppendLine(title); + builder.AppendLine(" -------------------------"); + + if (entries == null || entries.Length == 0) + { + builder.AppendLine(" No extra fields"); + builder.AppendLine(); + return; + } + + for (int i = 0; i < entries.Length; i++) + { + var entry = entries[i]; + + builder.AppendLine($" Extra Field {i}:"); + builder.AppendLine($" Header ID: {entry.HeaderID} (0x{(byte)entry.HeaderID:X4})"); + builder.AppendLine(entry.DataSize, " Data size"); + switch (entry) + { + case Zip64ExtendedInformationExtraField field: Print(builder, field); break; + case OS2ExtraField field: Print(builder, field); break; + case NTFSExtraField field: Print(builder, field); break; + case OpenVMSExtraField field: Print(builder, field); break; + case UnixExtraField field: Print(builder, field); break; + case PatchDescriptorExtraField field: Print(builder, field); break; + case PKCS7Store field: Print(builder, field); break; + case X509IndividualFile field: Print(builder, field); break; + case X509CentralDirectory field: Print(builder, field); break; + case StrongEncryptionHeader field: Print(builder, field); break; + case RecordManagementControls field: Print(builder, field); break; + case PKCS7EncryptionRecipientCertificateList field: Print(builder, field); break; + case PolicyDecryptionKeyRecordExtraField field: Print(builder, field); break; + case KeyProviderRecordExtraField field: Print(builder, field); break; + case PolicyKeyDataRecordRecordExtraField field: Print(builder, field); break; + case AS400ExtraFieldAttribute field: Print(builder, field); break; + case ZipItMacintoshExtraField field: Print(builder, field); break; + case ZipItMacintoshShortFileExtraField field: Print(builder, field); break; + case ZipItMacintoshShortDirectoryExtraField field: Print(builder, field); break; + case FWKCSMD5ExtraField field: Print(builder, field); break; + case InfoZIPUnicodeCommentExtraField field: Print(builder, field); break; + case InfoZIPUnicodePathExtraField field: Print(builder, field); break; + case DataStreamAlignment field: Print(builder, field); break; + case MicrosoftOpenPackagingGrowthHint field: Print(builder, field); break; + + default: Print(builder, entry); break; + } + } + + builder.AppendLine(); + } + + private static void Print(StringBuilder builder, Zip64ExtendedInformationExtraField field) + { + builder.AppendLine(field.OriginalSize, " Original size"); + builder.AppendLine(field.CompressedSize, " Compressed size"); + builder.AppendLine(field.RelativeHeaderOffset, " Relative header offset"); + builder.AppendLine(field.DiskStartNumber, " Disk start number"); + } + + private static void Print(StringBuilder builder, OS2ExtraField field) + { + builder.AppendLine(field.BSize, " Uncompressed block size"); + builder.AppendLine(field.CType, " Compression type"); + builder.AppendLine(field.EACRC, " CRC-32"); + builder.AppendLine(field.Var, " Data"); + } + + private static void Print(StringBuilder builder, NTFSExtraField field) + { + builder.AppendLine(field.Reserved, " Reserved"); + builder.AppendLine(field.Tags, " Tags"); + builder.AppendLine(field.Size, " Size"); + builder.AppendLine(field.Vars, " Vars"); + } + + private static void Print(StringBuilder builder, OpenVMSExtraField field) + { + builder.AppendLine(field.CRC, " CRC-32"); + builder.AppendLine(field.Tags, " Tags"); + builder.AppendLine(field.Size, " Size"); + builder.AppendLine(field.Vars, " Vars"); + } + + private static void Print(StringBuilder builder, UnixExtraField field) + { + builder.AppendLine(field.Atime, " File last access time"); + builder.AppendLine(field.Mtime, " File last modification time"); + builder.AppendLine(field.Uid, " File user ID"); + builder.AppendLine(field.Gid, " File group ID"); + builder.AppendLine(field.Var, " Data"); + } + + private static void Print(StringBuilder builder, PatchDescriptorExtraField field) + { + builder.AppendLine(field.Version, " Version"); + builder.AppendLine($" Flags: {field.Flags} (0x{field.Flags:X8})"); + builder.AppendLine(field.OldSize, " Old size"); + builder.AppendLine(field.OldCRC, " Old CRC-32"); + builder.AppendLine(field.NewSize, " New size"); + builder.AppendLine(field.NewCRC, " New CRC-32"); + } + + private static void Print(StringBuilder builder, PKCS7Store field) + { + builder.AppendLine(field.TData, " Data"); + } + + private static void Print(StringBuilder builder, X509IndividualFile field) + { + builder.AppendLine(field.TData, " Data"); + } + + private static void Print(StringBuilder builder, X509CentralDirectory field) + { + builder.AppendLine(field.TData, " Data"); + } + + private static void Print(StringBuilder builder, StrongEncryptionHeader field) + { + builder.AppendLine(field.Format, " Format"); + builder.AppendLine(field.AlgID, " Algorithm ID"); + builder.AppendLine(field.Bitlen, " Bit length"); + builder.AppendLine(field.Flags, " Flags"); + builder.AppendLine(field.CertData, " Data"); + } + + private static void Print(StringBuilder builder, RecordManagementControls field) + { + builder.AppendLine(field.Tags, " Tags"); + builder.AppendLine(field.Size, " Size"); + builder.AppendLine(field.Vars, " Vars"); + } + + private static void Print(StringBuilder builder, PKCS7EncryptionRecipientCertificateList field) + { + builder.AppendLine(field.Version, " Version"); + builder.AppendLine(field.CStore, " Data"); + } + + private static void Print(StringBuilder builder, PolicyDecryptionKeyRecordExtraField field) + { + builder.AppendLine(field.TData, " Data"); + } + + private static void Print(StringBuilder builder, KeyProviderRecordExtraField field) + { + builder.AppendLine(field.TData, " Data"); + } + + private static void Print(StringBuilder builder, PolicyKeyDataRecordRecordExtraField field) + { + builder.AppendLine(field.TData, " Data"); + } + + private static void Print(StringBuilder builder, AS400ExtraFieldAttribute field) + { + builder.AppendLine(field.FieldLength, " Field length"); + builder.AppendLine($" Field code: {field.FieldCode} (0x{field.FieldCode:X8})"); + builder.AppendLine(field.Data, " Data"); + } + + private static void Print(StringBuilder builder, ZipItMacintoshExtraField field) + { + builder.AppendLine(field.ExtraFieldSignature, " Extra field signature"); + builder.AppendLine(field.FnLen, " Filename length"); + builder.AppendLine(field.FileName, " Filename"); + builder.AppendLine(field.FileType, " File type"); + builder.AppendLine(field.Creator, " Creator"); + } + + private static void Print(StringBuilder builder, ZipItMacintoshShortFileExtraField field) + { + builder.AppendLine(field.ExtraFieldSignature, " Extra field signature"); + builder.AppendLine(field.FileType, " File type"); + builder.AppendLine(field.Creator, " Creator"); + builder.AppendLine(field.FdFlags, " Flags"); + builder.AppendLine(field.Reserved, " Reserved"); + } + + private static void Print(StringBuilder builder, ZipItMacintoshShortDirectoryExtraField field) + { + builder.AppendLine(field.ExtraFieldSignature, " Extra field signature"); + builder.AppendLine(field.FrFlags, " Flags"); + builder.AppendLine($" Field code: {field.View} (0x{field.View:X8})"); + } + + private static void Print(StringBuilder builder, FWKCSMD5ExtraField field) + { + builder.AppendLine(field.Preface, " Preface"); + builder.AppendLine(field.MD5, " MD5"); + } + + private static void Print(StringBuilder builder, InfoZIPUnicodeCommentExtraField field) + { + builder.AppendLine(field.Version, " Version"); + builder.AppendLine(field.ComCRC32, " Comment CRC-32"); + builder.AppendLine(field.UnicodeCom, " Unicode comment"); + } + + private static void Print(StringBuilder builder, InfoZIPUnicodePathExtraField field) + { + builder.AppendLine(field.Version, " Version"); + builder.AppendLine(field.NameCRC32, " Name CRC-32"); + builder.AppendLine(field.UnicodeName, " Unicode name"); + } + + private static void Print(StringBuilder builder, DataStreamAlignment field) + { + builder.AppendLine(field.Alignment, " Alignment"); + builder.AppendLine(field.Padding, " Padding"); + } + + private static void Print(StringBuilder builder, MicrosoftOpenPackagingGrowthHint field) + { + builder.AppendLine(field.Sig, " Signature"); + builder.AppendLine(field.PadVal, " Initial padding value"); + builder.AppendLine(field.Padding, " Padding"); + } + + private static void Print(StringBuilder builder, ExtensibleDataField field) + { + // TODO: Print byte data here + } + + #endregion } }