Last active
December 20, 2023 17:13
-
-
Save DHowett/d63ecdb8cdc4c85b3b5391fc42951d16 to your computer and use it in GitHub Desktop.
ImHex zip.hexpat with local header support
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma description End of Central Directory Header, Central Directory File Headers | |
#pragma MIME application/zip | |
#include <std/mem.pat> | |
#include <std/math.pat> | |
struct EndOfCentralDirectory { | |
u32 headerSignature [[color("00000000")]]; | |
u16 diskNum [[comment("Number of this disk "), name("Disk Number")]]; | |
u16 diskStart [[comment("Disk where central directory starts "), name("Central Directory Disk Number")]]; | |
u16 CDRCount [[comment("Number of central directory records on this disk"), name("Central Directory Entries")]]; | |
u16 CentralDirectoryRecordCount [[comment("Total number of entries in the central directory"), name("Total Central Directory Entries")]]; | |
u32 CDSize [[comment("Size of central directory (bytes)"), name("Central Directory Size")]]; | |
u32 CDOffset [[comment("Offset of start of central directory, relative to start of archive"), name("Central Directory Offset")]]; | |
u16 commentLength [[color("00000000")]]; | |
char coment[commentLength] [[name("Comment")]]; | |
}; | |
fn find_eocd() { | |
// If there is no zip comment, which is the common case, | |
// the end-of-central-directory record will be 22 bytes long | |
// at the end of the file; check if size-22 has the signature. | |
if (std::mem::read_unsigned(std::mem::size()-22, 4, std::mem::Endian::Little) == 0x06054B50) { | |
return std::mem::size()-22; | |
} else { | |
// If it's not there, then there's probably a zip comment; | |
// search the last 64KB of the file for the signature. | |
// This is not entirely reliable, since the signature could | |
// randomly appear in compressed data before the actual EOCD, | |
// but it should be good enough... | |
u128 last64k = std::math::max(0, std::mem::size()-65536-22); | |
return std::mem::find_sequence_in_range(0, last64k, std::mem::size(), 0x50,0x4B,0x05,0x06); | |
} | |
}; | |
EndOfCentralDirectory fileInfo @ find_eocd() [[name("End of Central Directory Record")]]; | |
struct CentralDirectoryFileHeader { | |
u32 headerSignature [[color("00000000")]]; | |
u16 versionMade [[comment("Version file made by")]]; | |
u16 versionExtract [[comment("Minimum version needed to extract")]]; | |
u16 generalFlag [[comment("General purpose bit flag"), color("00000000")]]; | |
u16 compressionMethod; | |
u16 fileLastModifyTime [[comment("File last modification time")]]; | |
u16 fileLastModifyDate [[comment("File last modification date")]]; | |
u32 crc32 [[comment("CRC-32 of uncompressed data"), color("00000000")]]; | |
u32 compressedSize; | |
u32 uncompressedSize; | |
u16 fileNameLength [[color("00000000")]]; | |
u16 extraFieldLength [[color("00000000")]]; | |
u16 fileCommentLength [[color("00000000")]]; | |
u16 diskNumber [[comment("Disk number where file starts")]]; | |
u16 internalFileAttributes; | |
u32 externalFileAttributes; | |
u32 fileOffset [[comment("Offset of local file header, relative to the start of the first disk on which the file occurs.")]]; | |
char fileName[fileNameLength]; | |
u8 extraField[extraFieldLength]; | |
char comment[fileCommentLength]; | |
}; | |
struct DataDescriptor { | |
u32 trailingHeader; | |
u32 actualCrc32; | |
u32 actualCompressedSize; | |
u32 actualUncompressedSize; | |
}; | |
struct LocalFileHeader { | |
u32 headerSignature [[color("00000000")]]; | |
u16 versionExtract [[comment("Minimum version needed to extract")]]; | |
u16 generalFlag [[comment("General purpose bit flag"), color("00000000")]]; | |
u16 compressionMethod; | |
u16 fileLastModifyTime [[comment("File last modification time")]]; | |
u16 fileLastModifyDate [[comment("File last modification date")]]; | |
if (!(generalFlag & 0x8)) { | |
u32 crc32 [[comment("CRC-32 of uncompressed data"), color("00000000")]]; | |
} else { | |
u32 crc32 [[name("**IGNORED** CRC-32")]]; | |
} | |
u32 compressedSize; | |
u32 uncompressedSize; | |
u16 fileNameLength [[color("00000000")]]; | |
u16 extraFieldLength [[color("00000000")]]; | |
char fileName[fileNameLength]; | |
u8 extraField[extraFieldLength]; | |
u8 data[while(std::mem::read_unsigned($, 4) != 0x08074b50)] [[color("00000000")]]; | |
if (generalFlag & 0x8) { | |
DataDescriptor dataDescriptor; | |
} | |
}; | |
CentralDirectoryFileHeader centralDirHeaders[fileInfo.CDRCount] @ (fileInfo.CDOffset) [[name("Files")]]; | |
LocalFileHeader zipEntriesStartingFromBeginning[while(std::mem::read_unsigned($, 4) != 0x02014b50)] @ 0 [[name("Local Headers")]]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment