159 lines
3.9 KiB
C++
159 lines
3.9 KiB
C++
#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<GeneralBitFlag> 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);
|
|
};
|
|
|
|
}
|