📄 liteunzip.c
字号:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include "../LiteUnzip.h"
#define IDS_OK 20
#define IDS_UNKNOWN 21
// =========================== Defines ======================
// Basic data types
typedef unsigned int uInt; // 16 bits or more
typedef unsigned char UCH;
typedef unsigned long ULG;
typedef unsigned long lutime_t; // define it ourselves since we don't include time.h
#define ZIP_MEMORY 0x01
#define ZIP_FILENAME 0x02
#define ZIP_HANDLE 0x04
#define ZIP_ALREADYINIT 0x40000000
#define ZIP_UNICODE 0x80000000
// Allowed flush values; see deflate() for details
#define Z_NO_FLUSH 0
#define Z_SYNC_FLUSH 2
#define Z_FULL_FLUSH 3
#define Z_FINISH 4
// The deflate compression method (the only one supported in this version)
#define Z_DEFLATED 8
// Return codes for the DEFLATE low-level functions. Negative
// values are errors, positive values are used for special but normal events.
#define Z_OK 0
#define Z_STREAM_END 1
#define Z_NEED_DICT 2
#define Z_STREAM_ERROR (-2)
#define Z_DATA_ERROR (-3)
#define Z_MEM_ERROR (-4)
#define Z_BUF_ERROR (-5)
// preset dictionary flag in zlib header
#define PRESET_DICT 0x20
// Maximum size of dynamic tree. The maximum found in a long but non-
// exhaustive search was 1004 huft structures (850 for length/literals
// and 154 for distances, the latter actually the result of an
// exhaustive search). The actual maximum is not known, but the
// value below is more than safe.
#define MANY 1440
// =========================== Structs ======================
typedef struct
{
unsigned int tm_sec; // seconds after the minute - [0,59]
unsigned int tm_min; // minutes after the hour - [0,59]
unsigned int tm_hour; // hours since midnight - [0,23]
unsigned int tm_mday; // day of the month - [1,31]
unsigned int tm_mon; // months since January - [0,11]
unsigned int tm_year; // years - [1980..2044]
} TM_UNZ;
// ZIPENTRYINFO holds information about one entry in the zip archive.
// This header appears in the ZIP archive.
#define UNZ_BUFSIZE (16384)
#define UNZ_MAXFILENAMEINZIP (256)
#define SIZECENTRALDIRITEM (0x2e)
#define SIZEZIPLOCALHEADER (0x1e)
#define ZIP_FIELDS_REFORMAT 0x000060F0
#define NUM_FIELDS_REFORMAT 15
#pragma pack(1)
typedef struct
{
unsigned short version; // version made by 2 bytes
unsigned short version_needed; // version needed to extract 2 bytes
unsigned short flag; // general purpose bit flag 2 bytes
unsigned short compression_method; // compression method 2 bytes
unsigned long dosDate; // last mod file date in Dos fmt 4 bytes
unsigned long crc; // crc-32 4 bytes
unsigned long compressed_size; // compressed size 4 bytes
unsigned long uncompressed_size; // uncompressed size 4 bytes
unsigned short size_filename; // filename length 2 bytes
unsigned short size_file_extra; // extra field length 2 bytes
unsigned short size_file_comment; // file comment length 2 bytes
unsigned short disk_num_start; // disk number start 2 bytes
unsigned short internal_fa; // internal file attributes 2 bytes
unsigned long external_fa; // external file attributes 4 bytes
unsigned long offset; // Byte offset of local header 4 bytes
} ZIPENTRYINFO;
#pragma pack()
// Used for DEFLATE decompression
typedef struct {
union {
struct {
UCH Exop; // number of extra bits or operation
UCH Bits; // number of bits in this code or subcode
} what;
uInt pad; // pad structure to a power of 2 (4 bytes for
} word; // 16-bit, 8 bytes for 32-bit int's)
uInt base; // literal, length base, distance base, or table offset
} INFLATE_HUFT;
// INFLATE_CODES_STATE->mode
// waiting for "i:"=input, "o:"=output, "x:"=nothing
#define START 0 // x: set up for LEN
#define LEN 1 // i: get length/literal/eob next
#define LENEXT 2 // i: getting length extra (have base)
#define DIST 3 // i: get distance next
#define DISTEXT 4 // i: getting distance extra
#define COPY 5 // o: copying bytes in window, waiting for space
#define LIT 6 // o: got literal, waiting for output space
#define WASH 7 // o: got eob, possibly still output waiting
#define END 8 // x: got eob and all data flushed
#define BADCODE 9 // x: got error
// inflate codes private state
typedef struct {
uInt len;
// mode dependent information
union {
struct {
const INFLATE_HUFT *tree; // pointer into tree
uInt need; // bits needed
} code; // if LEN or DIST, where in tree
uInt lit; // if LIT, literal
struct {
uInt get; // bits to get for extra
uInt dist; // distance back to copy from
} copy; // if EXT or COPY, where and how much
} sub; // submode
// mode independent information
const INFLATE_HUFT *ltree; // literal/length/eob tree
const INFLATE_HUFT *dtree; // distance tree
UCH lbits; // ltree bits decoded per branch
UCH dbits; // dtree bits decoder per branch
unsigned char mode; // current inflate_codes mode
} INFLATE_CODES_STATE;
// INFLATE_BLOCKS_STATE->mode
#define IBM_TYPE 0 // get type bits (3, including end bit)
#define IBM_LENS 1 // get lengths for stored
#define IBM_STORED 2 // processing stored block
#define IBM_TABLE 3 // get table lengths
#define IBM_BTREE 4 // get bit lengths tree for a dynamic block
#define IBM_DTREE 5 // get length, distance trees for a dynamic block
#define IBM_CODES 6 // processing fixed or dynamic block
#define IBM_DRY 7 // output remaining window bytes
#define IBM_DONE 8 // finished last block, done
#define IBM_BAD 9 // got a data error--stuck here
// inflate blocks semi-private state
typedef struct {
// mode dependent information
union {
uInt left; // if STORED, bytes left to copy
struct {
uInt table; // table lengths (14 bits)
uInt index; // index into blens (or border)
uInt *blens; // bit lengths of codes
uInt bb; // bit length tree depth
INFLATE_HUFT *tb; // bit length decoding tree
} trees; // if DTREE, decoding info for trees
struct {
INFLATE_CODES_STATE *codes;
} decode; // if CODES, current state
} sub; // submode
// mode independent information
uInt last; // TRUE if this block is the last block
uInt bitk; // bits in bit buffer
ULG bitb; // bit buffer
INFLATE_HUFT *hufts; // single malloc for tree space
UCH *window; // sliding window
UCH *end; // one byte after sliding window
UCH *read; // window read pointer
UCH *write; // window write pointer
ULG check; // check on output
unsigned char mode; // current inflate_block mode
} INFLATE_BLOCKS_STATE;
// INTERNAL_STATE->mode
#define IM_METHOD 0 // waiting for method byte
#define IM_FLAG 1 // waiting for flag byte
#define IM_DICT4 2 // four dictionary check bytes to go
#define IM_DICT3 3 // three dictionary check bytes to go
#define IM_DICT2 4 // two dictionary check bytes to go
#define IM_DICT1 5 // one dictionary check byte to go
#define IM_DICT0 6 // waiting for inflateSetDictionary
#define IM_BLOCKS 7 // decompressing blocks
#define IM_CHECK4 8 // four check bytes to go
#define IM_CHECK3 9 // three check bytes to go
#define IM_CHECK2 10 // two check bytes to go
#define IM_CHECK1 11 // one check byte to go
#define IM_DONE 12 // finished check, done
#define IM_BAD 13 // got an error--stay here
// inflate private state
typedef struct {
// mode dependent information
union {
uInt method; // if IM_FLAGS, method byte
struct {
ULG was; // computed check value
ULG need; // stream check value
} check; // if CHECK, check values to compare
uInt marker; // if IM_BAD, inflateSync's marker bytes count
} sub; // submode
// mode independent information
uInt wbits; // log2(window size) (8..15, defaults to 15)
INFLATE_BLOCKS_STATE blocks; // current inflate_blocks state
unsigned char mode; // current inflate mode
// unsigned char nowrap; // flag for no wrapper
} INTERNAL_STATE;
// readEntry() updates next_in and avail_in when avail_in has
// dropped to zero. It updates next_out and avail_out when avail_out
// has dropped to zero. All other fields are set by low level
// DEFLATE routines and must not be updated by the higher level.
//
// The fields total_in and total_out can be used for statistics or
// progress reports. After compression, total_in holds the total size of
// the uncompressed data and may be saved for use in the decompressor
// (particularly if the decompressor wants to decompress everything in
// a single step)
typedef struct {
UCH * next_in; // next input byte
DWORD avail_in; // # of bytes available at next_in
DWORD total_in; // total # of input bytes read so far
UCH * next_out; // next output byte should be put there
DWORD avail_out; // remaining free space at next_out
DWORD total_out; // total # of bytes output so far
#ifndef NDEBUG
char * msg; // last error message, NULL if no error
#endif
INTERNAL_STATE *state;
// int data_type; // best guess about the data type: ascii or binary
// ULG adler; // adler32 value of the uncompressed data
} Z_STREAM;
// ENTRYREADVARS holds tables/variables used when reading and decompressing an entry
typedef struct
{
UCH *InputBuffer; // Buffer for reading in compressed data of the current entry
Z_STREAM stream; // structure for inflate()
// DWORD PosInArchive; // Current "file position" within the archive
ULG RunningCrc; // crc32 of all data uncompressed
DWORD RemainingCompressed; // Remaining number of bytes to be decompressed
DWORD RemainingUncompressed; // Remaining number of bytes to be obtained after decomp
unsigned long Keys[3]; // Decryption keys, initialized by initEntry()
DWORD RemainingEncrypt; // The first call(s) to readEntry will read this many encryption-header bytes first
char CrcEncTest; // If encrypted, we'll check the encryption buffer against this
} ENTRYREADVARS;
// For TUNZIP->flags
#define TZIP_ARCMEMORY 0x0000001 // Set if TZIP->archive is memory, instead of a file, handle.
#define TZIP_ARCCLOSEFH 0x0000002 // Set if we open the file handle in archiveOpen() and must close it later.
#define TZIP_GZIP 0x0000004 // Set if a GZIP archive.
// TUNZIP holds information about the ZIP archive itself.
typedef struct
{
DWORD Flags;
HANDLE ArchivePtr; // Points to a handle, or a buffer if TZIP_ARCMEMORY
DWORD LastErr; // Holds the last TUNZIP error code
DWORD InitialArchiveOffset; // Initial offset within a file where the ZIP archive begins. This allows reading a ZIP archive contained within another file
DWORD ArchiveBufLen; // Size of memory buffer
DWORD ArchiveBufPos; // Current position within "ArchivePtr" if TZIP_ARCMEMORY
DWORD TotalEntries; // Total number of entries in the current disk of this archive
DWORD CommentSize; // Size of the global comment of the archive
DWORD ByteBeforeZipArchive; // Byte before the archive, (>0 for sfx)
DWORD CurrentEntryNum; // Number of the entry (in the archive) that is currently selected for
// unzipping. -1 if none.
DWORD CurrEntryPosInCentralDir; // Position of the current entry's header within the central dir
// DWORD CentralDirPos; // Byte offset to the beginning of the central dir
DWORD CentralDirOffset; // Offset of start of central directory with respect to the starting disk number
unsigned char *Password; // Password, or 0 if none.
unsigned char *OutBuffer; // Output buffer (where we decompress the current entry when unzipping it).
ZIPENTRYINFO CurrentEntryInfo; // Info about the currently selected entry (gotten from the Central Dir)
ENTRYREADVARS EntryReadVars; // Variables/buffers for decompressing the current entry
unsigned char Rootdir[MAX_PATH]; // Root dir for unzipping entries. Includes a trailing slash. Must be the last field!!!
} TUNZIP;
// ======================== Function Declarations ======================
// Diagnostic functions
#ifndef NDEBUG
#define LuAssert(cond,msg)
#define LuTrace(x)
#define LuTracev(x)
#define LuTracevv(x)
#define LuTracec(c,x)
#define LuTracecv(c,x)
#endif
static int inflate_trees_bits (uInt *, uInt *, INFLATE_HUFT **, INFLATE_HUFT *, Z_STREAM *);
static int inflate_trees_dynamic(uInt, uInt, uInt *, uInt *, uInt *, INFLATE_HUFT **, INFLATE_HUFT **, INFLATE_HUFT *, Z_STREAM *);
static INFLATE_BLOCKS_STATE * inflate_blocks_new(Z_STREAM * z, uInt w);
static INFLATE_CODES_STATE *inflate_codes_new(uInt, uInt, const INFLATE_HUFT *, const INFLATE_HUFT *, Z_STREAM *);
static int inflate_codes(INFLATE_BLOCKS_STATE *, Z_STREAM *, int);
static int inflate_flush(INFLATE_BLOCKS_STATE *, Z_STREAM *, int);
static int inflate_fast(uInt, uInt, const INFLATE_HUFT *, const INFLATE_HUFT *, INFLATE_BLOCKS_STATE *, Z_STREAM *);
//static ULG adler32(ULG, const UCH *, DWORD);
static DWORD setCurrentEntry(TUNZIP *, ZIPENTRY *, DWORD);
// simplify the use of the INFLATE_HUFT type with some defines
// defines for inflate input/output
// update pointers and return
#define UPDBITS {s->bitb = b; s->bitk = k;}
#define UPDIN {z->avail_in = n; z->total_in += (ULG)(p-z->next_in); z->next_in = p;}
#define UPDOUT {s->write = q;}
#define UPDATE {UPDBITS UPDIN UPDOUT}
#define LEAVE {UPDATE return(inflate_flush(s,z,r));}
// get bytes and bits
#define LOADIN {p = z->next_in; n = z->avail_in; b = s->bitb; k = s->bitk;}
#define NEEDBYTE {if (n) r = Z_OK; else LEAVE}
#define NEXTBYTE (n--, *p++)
#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((ULG)NEXTBYTE)<<k;k+=8;}}
#define DUMPBITS(j) {b >>= (j); k -= (j);}
// output bytes
#define WAVAIL (uInt)(q < s->read ? s->read - q - 1: s->end - q)
#define LOADOUT {q=s->write;m=(uInt)WAVAIL;m;}
#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
#define OUTBYTE(a) {*q++=(UCH)(a);m--;}
// load local pointers
#define LOAD {LOADIN LOADOUT}
// NOTE: I specify this data section to be Shared (ie, each running rexx
// script shares these variables, rather than getting its own copies of these
// variables). This is because, since I have only globals that are read-only
// or whose value is the same for all processes, I don't need a separate copy
// of these for each process that uses this DLL. In Visual C++'s Linker
// settings, I add "/section:Shared,rws"
#pragma data_seg("shared")
static HINSTANCE ThisInstance;
// Table of CRC-32's of all single-byte values (made by make_Crc_table)
static const ULG Crc_table[256] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -