192 lines
6.2 KiB
C++
192 lines
6.2 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
|
|
constexpr uint32_t PK_SIGNATURE_LF_HEADER = 0x04034b50; // PK + 0x0403
|
|
constexpr uint32_t PK_SIGNATURE_CENT_DIR = 0x02014b50; // PK + 0x0201
|
|
constexpr uint32_t PK_SIGNATURE_EO_CDR = 0x06054b50; // PK + 0x0605
|
|
constexpr uint16_t METHOD_UNCOMPRESSED = 0;
|
|
|
|
/** Overall .ZIP file format:
|
|
|
|
[local file header 1] -> "PK" + 0x4b50 + ...
|
|
[encryption header 1]
|
|
[file data 1]
|
|
[data descriptor 1]
|
|
.
|
|
.
|
|
.
|
|
[local file header n] -> "PK" + 0x4b50 + ...
|
|
[encryption header n]
|
|
[file data n]
|
|
[data descriptor n]
|
|
[archive decryption header]
|
|
[archive extra data record]
|
|
[central directory header 1]
|
|
.
|
|
.
|
|
.
|
|
[central directory header n] -> "PK" + 0x4b50
|
|
[zip64 end of central directory record]
|
|
[zip64 end of central directory locator]
|
|
[end of central directory record] <- 필수 포함 (단 한개)
|
|
*/
|
|
|
|
/** Local file header:
|
|
|
|
local file header signature 4 bytes (0x04034b50)
|
|
version needed to extract 2 bytes
|
|
general purpose bit flag 2 bytes
|
|
compression method 2 bytes
|
|
last mod file time 2 bytes
|
|
last mod file date 2 bytes
|
|
crc-32 4 bytes
|
|
compressed size 4 bytes
|
|
uncompressed size 4 bytes
|
|
file name length 2 bytes -> Variable
|
|
extra field length 2 bytes -> Variable
|
|
|
|
file name (variable size)
|
|
extra field (variable size)
|
|
*/
|
|
|
|
#pragma pack(push, 1)
|
|
constexpr int LOCAL_FILE_HEADER_BYTE = 30;
|
|
|
|
struct LocalFileHeader {
|
|
uint32_t signature;
|
|
uint16_t versionNeededToExtract;
|
|
uint16_t generalBitFlag;
|
|
uint16_t compressionMethod; // no compression == 0
|
|
uint16_t lastModTime; // 압축 시점의 시간 (1980년 기준 시간, DOS TIME)
|
|
uint16_t lastModDate; // 압축 시점의 날짜 (1980년 기준 연도, DOS TIME)
|
|
uint32_t crc32;
|
|
uint32_t sizeOfCompressed; // same as unCompression (cuz no compreesion)
|
|
uint32_t sizeOfUncompressed;
|
|
uint16_t lengthOfFileName;
|
|
uint16_t lengthOfExtraField;
|
|
|
|
// var[lengthOfFileName] fileName
|
|
// var[lengthOfExtraField] extraField
|
|
};
|
|
|
|
// 정적 메모리 사이즈 검사
|
|
static_assert(sizeof(LocalFileHeader) == LOCAL_FILE_HEADER_BYTE, "LocalFileHeader Size is mismatch");
|
|
|
|
/** Central directory structure:
|
|
|
|
[central directory header 1]
|
|
.
|
|
.
|
|
.
|
|
[central directory header n]
|
|
[digital signature]
|
|
|
|
File header:
|
|
|
|
central file header signature 4 bytes (0x02014b50)
|
|
version made by 2 bytes
|
|
version needed to extract 2 bytes
|
|
general purpose bit flag 2 bytes
|
|
compression method 2 bytes
|
|
last mod file time 2 bytes
|
|
last mod file date 2 bytes
|
|
crc-32 4 bytes
|
|
compressed size 4 bytes
|
|
uncompressed size 4 bytes
|
|
file name length 2 bytes
|
|
extra field length 2 bytes
|
|
file comment length 2 bytes
|
|
disk number start 2 bytes
|
|
internal file attributes 2 bytes
|
|
external file attributes 4 bytes
|
|
relative offset of local header 4 bytes
|
|
|
|
file name (variable size)
|
|
extra field (variable size)
|
|
file comment (variable size)
|
|
*/
|
|
|
|
constexpr int CENTRAL_DIRECTORY_BYTE = 46;
|
|
struct CentralDirectory {
|
|
uint32_t signature;
|
|
uint16_t versionMadeBy;
|
|
uint16_t versionNeededToExtract;
|
|
uint16_t generalBitFlag;
|
|
uint16_t compressionMethod; // no compression == 0
|
|
uint16_t lastModTime; // 압축 시점의 시간 (1980년 기준 시간)
|
|
uint16_t lastModDate; // 압축 시점의 날짜 (1980년 기준 연도)
|
|
uint32_t crc32;
|
|
uint32_t sizeOfCompressed; // same as unCompression (cuz no compreesion)
|
|
uint32_t sizeOfUncompressed;
|
|
uint16_t lengthOfFileName;
|
|
uint16_t lengthOfExtraField;
|
|
uint16_t lengthOfFileComment;
|
|
|
|
uint16_t diskNumStart;
|
|
uint16_t attributeInternal;
|
|
uint32_t attributeExternal;
|
|
uint32_t offsetLocalFileHeader;
|
|
|
|
// var[lengthOfFileName] fileName
|
|
// var[lengthOfExtraField] extraField
|
|
// var[lengthOfFileComment] fileComment
|
|
};
|
|
|
|
// 정적 메모리 사이즈 검사
|
|
static_assert(sizeof(CentralDirectory) == CENTRAL_DIRECTORY_BYTE, "CentralDirectory Size is mismatch");
|
|
|
|
/** End of central directory record:
|
|
|
|
end of central dir signature 4 bytes (0x0605 + 4b50)
|
|
number of this disk 2 bytes
|
|
|
|
// 중앙 디렉터리가 시작되는 디스크의 번호.
|
|
number of the disk with the
|
|
start of the central directory 2 bytes
|
|
|
|
// 이 디스크에 있는 중앙 디렉터리 항목의 수
|
|
total number of entries in the
|
|
central directory on this disk 2 bytes
|
|
|
|
// .ZIP 파일 내 전체 파일 수
|
|
total number of entries in
|
|
the central directory 2 bytes
|
|
|
|
size of the central directory 4 bytes
|
|
|
|
// 중앙 디렉터리가 시작되는 디스크 상에서 중앙 디렉터리 시작 지점의 오프셋
|
|
offset of start of central
|
|
directory with respect to
|
|
the starting disk number 4 bytes
|
|
|
|
.ZIP file comment length 2 bytes
|
|
.ZIP file comment (variable size)
|
|
*/
|
|
constexpr int EOCD_BYTE = 22;
|
|
struct EoCDRecord {
|
|
uint32_t signature;
|
|
|
|
// central directory end record을 포함하는 이 디스크의 번호
|
|
uint16_t diskNumber;
|
|
|
|
// 중앙 디렉터리가 시작되는 디스크의 번호.
|
|
uint16_t diskNumber_CentralDirStart;
|
|
|
|
// 이 디스크에 있는 중앙 디렉터리 항목의 수
|
|
uint16_t numOfCentralDir;
|
|
|
|
// .ZIP 파일 내 전체 파일 수
|
|
uint16_t numOfEntries;
|
|
uint32_t sizeOfCentralDir;
|
|
uint32_t offsetCentralDir;
|
|
uint16_t lengthOfCommentLength;
|
|
|
|
// var[LengthOfCommentLength] zipFileComment
|
|
};
|
|
|
|
// 정적 메모리 사이즈 검사
|
|
static_assert(sizeof(EoCDRecord) == EOCD_BYTE, "EoCDRecord Size is mismatch");
|
|
|
|
#pragma pack(pop)
|