From b160e99b637de37abd6c0b5f3ca98001c21d1d03 Mon Sep 17 00:00:00 2001 From: Nik Date: Wed, 21 Dec 2022 11:27:58 +0100 Subject: [PATCH] patterns/sit5: Added StuffItV5 archive pattern --- README.md | 1 + patterns/sit5.hexpat | 115 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 patterns/sit5.hexpat diff --git a/README.md b/README.md index 81b2f3d..4f9af26 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ Hex patterns, include patterns and magic files for the use with the ImHex Hex Ed | TAR | `application/x-tar` | [`patterns/tar.hexpat`](patterns/tar.hexpat) | Tar file format | | CPIO | `application/x-cpio` | [`patterns/cpio.hexpat`](patterns/cpio.hexpat) | Old Binary CPIO Format | | FDT | | [`patterns/fdt.hexpat`](patterns/fdt.hexpat) | Flat Linux Device Tree blob | +| StuffItV5 | `application/x-stuffit` | [`patterns/sit5.hexpat`](patterns/sit5.hexpat) | StuffIt V5 archive | ### Scripts diff --git a/patterns/sit5.hexpat b/patterns/sit5.hexpat new file mode 100644 index 0000000..b79216d --- /dev/null +++ b/patterns/sit5.hexpat @@ -0,0 +1,115 @@ +// Based on https://github.com/mietek/theunarchiver/wiki/StuffIt5Format and https://github.com/ParksProjets/Maconv/blob/master/docs/stuffit/Stuffit_v5.md + +#pragma endian big +#pragma MIME application/x-stuffit + +#include +#include + +namespace v5 { + + bitfield Flags1 { + padding : 1; + folder : 1; + encrypted : 1; + padding : 5; + } [[left_to_right]]; + + bitfield Flags2 { + padding : 7; + resource_fork : 1; + padding : 8; + } [[left_to_right]]; + + using MacOSHFSPlusDate = u32 [[format("v5::format_macos_date")]]; + + fn format_macos_date(MacOSHFSPlusDate date) { + return std::time::format(std::time::to_utc(date - 2082844800)); + }; + + struct Header { + char magic[0x50]; + u32 unknown1; + u32 archiveSize; + u32 entriesOffset; + u32 unknown2; + }; + + struct EntryHeader { + u32 magic; + u8 version; + u8 unknown1; + u16 headerSize; + u8 unknown2; + Flags1 flags; + MacOSHFSPlusDate creationDate, modificationDate; + u32 prevEntryOffset, nextEntryOffset, parentEntryOffset; + u16 nameSize; + u16 headerChecksum; + + u32 dataForkUncompressedLength, dataForkCompressedLength; + u16 dataForkChecksum; + u16 unknown3; + }; + + enum CompressionMethod : u8 { + None = 0x00, // No compression + Rle90 = 0x01, // Run length encoding + Compress = 0x02, // Compress LZW algorithm, 14 bit max code length, block mode + StuffIt3 = 0x03, // Simple Huffman encoding for individual bytes + StuffIt5 = 0x05, // LZAH + StuffIt8 = 0x08, // Miller-Wegman + StuffIt13 = 0x0D, // LZSS and Huffman + Stuffit14 = 0x0E, // Unknown + StuffItArsenic = 0x0F // BWT and arithmetic coding + }; + + struct Entry { + EntryHeader header; + if (header.flags.folder) { + u16 numFiles; + + if (header.dataForkUncompressedLength) + std::print("Folder entry {} is special!", std::core::array_index()); + } else { + CompressionMethod compressionMethod; + } + + u8 passwordDataLength; + u8 passwordInformation[passwordDataLength]; + char fileName[header.nameSize]; + u16 commentSize; + u16 unknown2; + char comment[commentSize]; + + if (!header.flags.folder) { + Flags2 flags; + u16 unknown3; + char fileType[4]; + u32 fileCreator; + u16 macOSFinderFlags; + u32 unknown4; + u32 unknown5; + u8 unknown6[6]; + + if (header.version == 1) + u32 unknown7; + + u8 compressedData[header.dataForkCompressedLength] [[sealed]]; + + if (header.nextEntryOffset == 0x00) + break; + else + $ = header.nextEntryOffset; + } + }; + + struct StuffIt { + Header header; + + Entry entries[while(true)] @ header.entriesOffset; + }; + +} + +v5::StuffIt stuffIt @ 0x00; \ No newline at end of file