-
-
Save fogmoon/84f4a1541afef8e596acbc1786ea96de to your computer and use it in GitHub Desktop.
Zip file format.
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
#include <stdio.h> | |
#include <stddef.h> | |
#include <stdlib.h> | |
#pragma warning(disable:4996) | |
/************************************************************************/ | |
/* Zip file struct */ | |
/* */ | |
/* FileEntry0,[..., FileEntryN] + DirEntry0,[..., DirEntryN] */ | |
/* + DigitalSignature + EndEntry*/ | |
/* [FileEntryHeader + Data + [DataDesc]] */ | |
/************************************************************************/ | |
#pragma pack(push) | |
#pragma pack(2) | |
struct ZipDate | |
{ | |
unsigned short Mday:5; /* day of the month - [1,31] */ | |
unsigned short Mon:4; /* months since January - [0,11] */ | |
unsigned short Year:7; /* years - [1980..2044] */ | |
}; | |
struct ZipTime | |
{ | |
unsigned short Sec:5; /* seconds after the minute - [0,59] */ | |
unsigned short Min:6; /* minutes after the hour - [0,59] */ | |
unsigned short Hour:5; /* hours since midnight - [0,23] */ | |
}; | |
#define ZIP_FILE_MAGIC_NUMBER 0x04034b50 | |
struct ZipFileEntryHeader { | |
//unsigned long m_MagicNumber; /* Magic number 4 bytes, must be 0x04034b50 */ | |
unsigned short m_VersionNeeded; /* version needed to extract 2 bytes */ | |
unsigned short m_Flag; /* general purpose bit flag 2 bytes */ | |
unsigned short m_CompressionMethod; /* compression method 2 bytes */ | |
ZipTime m_LastModTime; /* last mod file time in Dos fmt 2 bytes */ | |
ZipDate m_LastModDate; /* last mod file time in Dos date 2 bytes */ | |
unsigned long m_CRC; /* crc-32 4 bytes */ | |
unsigned long m_CompressedSize; /* compressed size 4 bytes */ | |
unsigned long m_UncompressedSize; /* uncompressed size 4 bytes */ | |
unsigned short m_FilenameSize; /* filename length 2 bytes */ | |
unsigned short m_FileExtraSize; /* extra field length 2 bytes */ | |
/* file name (variable size) */ | |
/* extra field (variable size) */ | |
}; | |
/** | |
* This part only availably when the 3rd bit is 1 of 'm_Flag' in 'ZipEntryHeader' | |
*/ | |
struct ZipDataDesc { | |
unsigned long m_CRC; /* crc-32 4 bytes */ | |
unsigned long m_CompressedSize; /* compressed size 4 bytes */ | |
unsigned long m_UncompressedSize; /* uncompressed size 4 bytes */ | |
}; | |
#define ZIP_DIR_MAGIC_NUMBER 0x02014b50 | |
struct ZipDirEntry { | |
//unsigned long m_MagicNumber; /* Magic number 4 bytes (0x02014b50) */ | |
unsigned short m_VersionMade; /* version made by 2 bytes */ | |
unsigned short m_VersionNeeded; /* version needed to extract 2 bytes */ | |
unsigned short m_Flag; /* general purpose bit flag 2 bytes */ | |
unsigned short m_CompressionMethod; /* compression method 2 bytes */ | |
ZipTime m_LastModTime; /* last mod file time in Dos fmt 2 bytes */ | |
ZipDate m_LastModData; /* last mod file time in Dos fmt 2 bytes */ | |
unsigned long m_CRC; /* crc-32 4 bytes */ | |
unsigned long m_CompressedSize; /* compressed size 4 bytes */ | |
unsigned long m_UncompressedSize; /* uncompressed size 4 bytes */ | |
unsigned short m_FilenameSize; /* filename length 2 bytes */ | |
unsigned short m_FileExtraSize; /* extra field length 2 bytes */ | |
unsigned short m_FileCommentSize; /* file comment length 2 bytes */ | |
unsigned short m_DiskNumberStart; /* disk number start 2 bytes */ | |
unsigned short m_InternalFileAttribute;/* internal file attributes 2 bytes */ | |
unsigned long m_ExternalFileAttribute; /* external file attributes 4 bytes */ | |
unsigned long m_OffsetOfLocalHeader; /* relative offset of local header 4 bytes */ | |
/* file name (variable size) */ | |
/* extra field (variable size) */ | |
/* file comment (variable size) */ | |
}; | |
#define ZIP_DIR_SIGN_MAGIC_NUMBER 0x05054b50 | |
struct ZipDirSignature { | |
//unsigned long m_MagicNumber; /*header signature 4 bytes (0x05054b50) */ | |
unsigned short m_DataSize; /* size of data 2 bytes */ | |
/* signature data (variable size) */ | |
}; | |
#define ZIP_DIR_END_MAGIC_NUMBER 0x06054b50 | |
struct ZipEndDir { | |
//unsigned long m_MagicNumber; /* end of central dir signature 4 bytes (0x06054b50) */ | |
unsigned short m_DiskNumber; /* number of this disk 2 bytes */ | |
unsigned short m_DiskNumWithStart; /* number of the disk with the start of the central directory 2 bytes */ | |
unsigned short m_DiskEntryCount; /* total number of entries in the central directory on this disk 2 bytes */ | |
unsigned short m_EntryCount; /* total number of entries in the central directory 2 bytes */ | |
unsigned long m_DirCount; /* size of the central directory 4 bytes */ | |
unsigned long m_DiskOffset; /* offset of start of central directory with respect to the starting disk number 4 bytes */ | |
unsigned short m_Comment; /* .ZIP file comment length 2 bytes */ | |
/* .ZIP file comment (variable size) */ | |
}; | |
#pragma pack(pop) | |
int main(int argc, char** argv) | |
{ | |
FILE* fp = ::fopen( "Test.zip", "rb" ); | |
unsigned long magic_number = 0; | |
char szFileName[256]; | |
::fread( &magic_number, sizeof(unsigned long), 1, fp ); | |
while( ZIP_FILE_MAGIC_NUMBER==magic_number ) { | |
printf( "A local file: " ); | |
ZipFileEntryHeader zip_local_header; | |
::fread( &zip_local_header, sizeof(ZipFileEntryHeader), 1, fp ); | |
if( zip_local_header.m_FilenameSize> 0 ) { | |
::fread(szFileName, zip_local_header.m_FilenameSize, 1, fp ); | |
szFileName[zip_local_header.m_FilenameSize] = 0; | |
printf( " name:%s.", szFileName ); | |
if( (zip_local_header.m_Flag & 0x00000001) ) { //an encrypt data | |
printf( " encrypted." ); | |
} | |
} | |
if( zip_local_header.m_FileExtraSize> 0 ) { | |
::fseek(fp, zip_local_header.m_FileExtraSize, SEEK_CUR); | |
} | |
// file data | |
::fseek(fp, zip_local_header.m_CompressedSize, SEEK_CUR); | |
printf( "\n" ); | |
::fread( &magic_number, sizeof(unsigned long), 1, fp ); | |
if( 0x08074b50==magic_number || (zip_local_header.m_Flag & (0x00000001<<3)) ) { | |
if( 0x08074b50!=magic_number ) | |
::fseek(fp, -4, SEEK_CUR); | |
//when the 3rd bit is 1 of 'm_Flag' in 'ZipEntryHeader' | |
ZipDataDesc data_desc; | |
::fread( &data_desc, sizeof(ZipDataDesc), 1, fp ); | |
zip_local_header.m_CRC = data_desc.m_CRC; | |
zip_local_header.m_CompressedSize = data_desc.m_CompressedSize; | |
zip_local_header.m_UncompressedSize = data_desc.m_UncompressedSize; | |
::fread( &magic_number, sizeof(unsigned long), 1, fp ); | |
} | |
} | |
while( ZIP_DIR_MAGIC_NUMBER==magic_number ) { | |
printf( "A dir: " ); | |
ZipDirEntry zip_dir; | |
::fread( &zip_dir, sizeof(ZipDirEntry), 1, fp ); | |
if( zip_dir.m_FilenameSize> 0 ) { | |
::fread(szFileName, zip_dir.m_FilenameSize, 1, fp ); | |
szFileName[zip_dir.m_FilenameSize] = 0; | |
printf( "name:%s.", szFileName ); | |
} | |
if( zip_dir.m_FileExtraSize> 0 ) { | |
::fseek(fp, zip_dir.m_FileExtraSize, SEEK_CUR); | |
} | |
if( zip_dir.m_FileCommentSize> 0 ) { | |
::fseek(fp, zip_dir.m_FileCommentSize, SEEK_CUR); | |
} | |
printf( "\n" ); | |
::fread( &magic_number, sizeof(unsigned long), 1, fp ); | |
} | |
while( ZIP_DIR_SIGN_MAGIC_NUMBER==magic_number ) { | |
printf( "A dir sign.\n" ); | |
ZipDirSignature zip_dir_sign; | |
::fread( &zip_dir_sign, sizeof(ZipDirSignature), 1, fp ); | |
if( zip_dir_sign.m_DataSize> 0 ) { | |
::fseek(fp, zip_dir_sign.m_DataSize, SEEK_CUR); | |
} | |
::fread( &magic_number, sizeof(unsigned long), 1, fp ); | |
} | |
if( ZIP_DIR_END_MAGIC_NUMBER==magic_number ) { | |
printf( "A dir end." ); | |
ZipEndDir zip_dir_end; | |
::fread( &zip_dir_end, sizeof(ZipEndDir), 1, fp ); | |
if( zip_dir_end.m_Comment> 0 ) { | |
::fread(szFileName, zip_dir_end.m_Comment, 1, fp ); | |
szFileName[zip_dir_end.m_Comment] = 0; | |
printf( " Comment:%s.", szFileName ); | |
} | |
printf( "\n" ); | |
} | |
::fclose( fp ); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment