#pragma once #include "tl/flag_set.h" #include "fs/Api.h" namespace fs { class FS_API ZipBase { public: enum class GeneralBitFlag : uint16_t { Encrypted = 1 << 0, CompressionMethodSpecific1 = 1 << 1, CompressionMethodSpecific2 = 1 << 2, DataDescriptorNeeded = 1 << 3, StrongEncryption = 1 << 6, LanguageEncodingFlag = 1 << 11, LocalHeaderFieldsMasked = 1 << 13, }; typedef tl::flag_set GeneralBitFlags; enum class CompressionMethod : uint16_t { Store = 0, Shrunk = 1, Reduced1 = 2, Reduced2 = 3, Reduced3 = 4, Reduced4 = 5, Implode = 6, //Reserved = 7, Deflate = 8, Deflate64 = 9, PKWareImplode = 10, //Reserved = 11, BZip2 = 12, //Reserved = 13, LZMA = 14, //Reserved = 15, //Reserved = 16, //Reserved = 17, Terse = 18, LZ77 = 19, LZ4 = 20, // non-standard ZStd = 21, // non-standard WavPack = 97, PPMd = 98, }; protected: ////////////////////////////////////////////////////////////////////////// //These structs follow pretty closely the https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT standard #pragma pack(push, 1) struct LocalFileHeader { static constexpr uint32_t k_signature = 0x04034b50u; uint32_t signature = k_signature; uint16_t versionNeededToExtract = 0; uint16_t generalBitFlag = 0; uint16_t compressionMethod = 0; uint16_t lastModFileTime = 0; uint16_t lastModFileDate = 0; uint32_t crc32 = 0; uint32_t compressedSize = 0; uint32_t uncompressedSize = 0; uint16_t filenameLength = 0; uint16_t extraFieldLength = 0; }; struct DataDescriptor { uint32_t crc32 = 0; uint32_t compressedSize = 0; uint32_t uncompressedSize = 0; }; struct CentralDirectoryFileHeader { static constexpr uint32_t k_signature = 0x02014b50u; uint32_t signature = k_signature; uint16_t versionMadeBy = 0; uint16_t versionNeededToExtract = 0; uint16_t generalBitFlag = 0; uint16_t compressionMethod = 0; uint16_t lastModFileTime = 0; uint16_t lastModFileDate = 0; uint32_t crc32 = 0; uint32_t compressedSize = 0; uint32_t uncompressedSize = 0; uint16_t filenameLength = 0; uint16_t extraFieldLength = 0; uint16_t fileCommentLength = 0; uint16_t diskNumberStart = 0; uint16_t internalFileAttributes = 0; uint32_t externalFileAttributes = 0; uint32_t localHeaderOffset = 0; }; struct EndOfCentralDirectoryRecord { static constexpr uint32_t k_signature = 0x06054b50u; uint32_t signature = k_signature; uint16_t diskNumber = 0; uint16_t centralDirectoryStartDiskNumber = 0; uint16_t centralDirectoryRecordCountOnThisDisk = 0; uint16_t centralDirectoryRecordCount = 0; uint32_t centralDirectorySize = 0; uint32_t centralDirectoryOffset = 0; uint16_t zipFileCommentLength = 0; }; struct ExtendedInformationExtraField64 { static constexpr uint32_t k_tag = 0x0001; uint16_t tag = k_tag; uint16_t size = 0; uint64_t originalSize = 0; uint64_t compressedSize = 0; uint64_t localHeaderOffset = 0; uint32_t diskNumber = 0; }; struct EndOfCentralDirectoryRecord64 { static constexpr uint32_t k_signature = 0x06064b50u; uint32_t signature = k_signature; uint64_t endOfCentralDirectorySize = 0; uint16_t versionMadeBy = 0; uint16_t versionNeededToExtract = 0; uint32_t diskNumber = 0; uint32_t centralDirectoryStartDiskNumber = 0; uint64_t centralDirectoryRecordCountOnThisDisk = 0; uint64_t centralDirectoryRecordCount = 0; uint64_t centralDirectorySize = 0; uint64_t centralDirectoryOffset = 0; }; struct EndOfCentralDirectoryLocator64 { static constexpr uint32_t k_signature = 0x07064b50u; uint32_t signature = k_signature; uint32_t centralDirectoryStartDiskNumber = 0; uint64_t endOfCentralDirectoryRecordOffset = 0; uint32_t diskCount = 0; }; #pragma pack(pop) static void computeMsDosTime(time_t time, uint16_t& o_date, uint16_t& o_time); static CentralDirectoryFileHeader computeCentralDirectoryFileHeader(const LocalFileHeader& header, bool zip64); }; }