├── ReadMe.txt
├── Zip.sln
└── Zip
├── Zip.vcxproj
├── Zip.vcxproj.filters
├── Zip.vcxproj.user
├── ZipFunction.cpp
├── ZipFunction.h
├── ZipTest.cpp
└── zip
├── ZipDefine.h
├── unzip.cpp
├── unzip.h
├── zip.cpp
└── zip.h
/ReadMe.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DoreRandom/Zip/7bef5a774886ef6456209ad93064f52d125ec50f/ReadMe.txt
--------------------------------------------------------------------------------
/Zip.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.31101.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zip", "Zip\Zip.vcxproj", "{4C556546-352E-47BC-9D5C-62239A93389F}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Win32 = Debug|Win32
11 | Release|Win32 = Release|Win32
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {4C556546-352E-47BC-9D5C-62239A93389F}.Debug|Win32.ActiveCfg = Debug|Win32
15 | {4C556546-352E-47BC-9D5C-62239A93389F}.Debug|Win32.Build.0 = Debug|Win32
16 | {4C556546-352E-47BC-9D5C-62239A93389F}.Release|Win32.ActiveCfg = Release|Win32
17 | {4C556546-352E-47BC-9D5C-62239A93389F}.Release|Win32.Build.0 = Release|Win32
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/Zip/Zip.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | {4C556546-352E-47BC-9D5C-62239A93389F}
27 | Win32Proj
28 | Zip
29 |
30 |
31 |
32 | Application
33 | true
34 | v120
35 | Unicode
36 |
37 |
38 | Application
39 | false
40 | v120
41 | true
42 | Unicode
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | true
56 |
57 |
58 | false
59 |
60 |
61 |
62 |
63 |
64 | Level3
65 | Disabled
66 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
67 | false
68 |
69 |
70 | Console
71 | true
72 |
73 |
74 |
75 |
76 | Level3
77 |
78 |
79 | MaxSpeed
80 | true
81 | true
82 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
83 |
84 |
85 | Console
86 | true
87 | true
88 | true
89 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/Zip/Zip.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | 源文件
20 |
21 |
22 | 源文件
23 |
24 |
25 | 源文件
26 |
27 |
28 | 源文件
29 |
30 |
31 |
32 |
33 | 头文件
34 |
35 |
36 | 头文件
37 |
38 |
39 | 头文件
40 |
41 |
42 | 头文件
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Zip/Zip.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 |
6 |
--------------------------------------------------------------------------------
/Zip/ZipFunction.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DoreRandom/Zip/7bef5a774886ef6456209ad93064f52d125ec50f/Zip/ZipFunction.cpp
--------------------------------------------------------------------------------
/Zip/ZipFunction.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef ZIP_FUNCTION
3 | #define ZIP_FUNCTION
4 |
5 | /*******************************************************************************
6 | ** AREA1 : include header files area
7 | *******************************************************************************/
8 |
9 | #include "zip/unzip.h"
10 | #include "zip/zip.h"
11 | #include
12 | #include
13 |
14 | /*******************************************************************************
15 | ** AREA2 : code function declare area
16 | *******************************************************************************/
17 |
18 | ZRESULT ExtractZipToDir(const char* unzipSrcPath, const char* unzipDestPath = NULL);
19 | ZRESULT CompressDirToZip(const char* zipSrcPath, const char* zipDestPath = NULL);
20 | ZRESULT CompressDirToZip(std::vector vzipSrcPath, const char* czipDestPath);
21 | ZRESULT ExtractZipToDir(LPCTSTR unzipSrcPath, LPCTSTR unzipDestPath = NULL);
22 | ZRESULT CompressDirToZip(LPCTSTR zipSrcPath, LPCTSTR zipDestPath = NULL);
23 |
24 |
25 | std::string GetZipErrorMessage(ZRESULT code);
26 | void SetZipEncode(int mode);
27 | #endif
--------------------------------------------------------------------------------
/Zip/ZipTest.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DoreRandom/Zip/7bef5a774886ef6456209ad93064f52d125ec50f/Zip/ZipTest.cpp
--------------------------------------------------------------------------------
/Zip/zip/ZipDefine.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DoreRandom/Zip/7bef5a774886ef6456209ad93064f52d125ec50f/Zip/zip/ZipDefine.h
--------------------------------------------------------------------------------
/Zip/zip/unzip.h:
--------------------------------------------------------------------------------
1 | #ifndef _unzip_H
2 | #define _unzip_H
3 |
4 | // UNZIPPING functions -- for unzipping.
5 | // This file is a repackaged form of extracts from the zlib code available
6 | // at www.gzip.org/zlib, by Jean-Loup Gailly and Mark Adler. The original
7 | // copyright notice may be found in unzip.cpp. The repackaging was done
8 | // by Lucian Wischik to simplify and extend its use in Windows/C++. Also
9 | // encryption and unicode filenames have been added.
10 | #include
11 | #ifndef _zip_H
12 | typedef void* HZIP;
13 | #endif
14 | // An HZIP identifies a zip file that has been opened
15 |
16 | typedef DWORD ZRESULT;
17 | // return codes from any of the zip functions. Listed later.
18 |
19 | typedef struct
20 | {
21 | int index; // index of this file within the zip
22 | TCHAR name[MAX_PATH]; // filename within the zip
23 | DWORD attr; // attributes, as in GetFileAttributes.
24 | FILETIME atime, ctime, mtime;// access, create, modify filetimes
25 | long comp_size; // sizes of item, compressed and uncompressed. These
26 | long unc_size; // may be -1 if not yet known (e.g. being streamed in)
27 | } ZIPENTRY;
28 |
29 |
30 | HZIP OpenZip(const TCHAR *fn, const char *password);
31 | HZIP OpenZip(void *z, unsigned int len, const char *password);
32 | HZIP OpenZipHandle(HANDLE h, const char *password);
33 | // OpenZip - opens a zip file and returns a handle with which you can
34 | // subsequently examine its contents. You can open a zip file from:
35 | // from a pipe: OpenZipHandle(hpipe_read,0);
36 | // from a file (by handle): OpenZipHandle(hfile,0);
37 | // from a file (by name): OpenZip("c:\\test.zip","password");
38 | // from a memory block: OpenZip(bufstart, buflen,0);
39 | // If the file is opened through a pipe, then items may only be
40 | // accessed in increasing order, and an item may only be unzipped once,
41 | // although GetZipItem can be called immediately before and after unzipping
42 | // it. If it's opened in any other way, then full random access is possible.
43 | // Note: pipe input is not yet implemented.
44 | // Note: zip passwords are ascii, not unicode.
45 | // Note: for windows-ce, you cannot close the handle until after CloseZip.
46 | // but for real windows, the zip makes its own copy of your handle, so you
47 | // can close yours anytime.
48 |
49 | ZRESULT GetZipItem(HZIP hz, int index, ZIPENTRY *ze);
50 | // GetZipItem - call this to get information about an item in the zip.
51 | // If index is -1 and the file wasn't opened through a pipe,
52 | // then it returns information about the whole zipfile
53 | // (and in particular ze.index returns the number of index items).
54 | // Note: the item might be a directory (ze.attr & FILE_ATTRIBUTE_DIRECTORY)
55 | // See below for notes on what happens when you unzip such an item.
56 | // Note: if you are opening the zip through a pipe, then random access
57 | // is not possible and GetZipItem(-1) fails and you can't discover the number
58 | // of items except by calling GetZipItem on each one of them in turn,
59 | // starting at 0, until eventually the call fails. Also, in the event that
60 | // you are opening through a pipe and the zip was itself created into a pipe,
61 | // then then comp_size and sometimes unc_size as well may not be known until
62 | // after the item has been unzipped.
63 |
64 | ZRESULT FindZipItem(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze);
65 | // FindZipItem - finds an item by name. ic means 'insensitive to case'.
66 | // It returns the index of the item, and returns information about it.
67 | // If nothing was found, then index is set to -1 and the function returns
68 | // an error code.
69 |
70 | ZRESULT UnzipItem(HZIP hz, int index, const TCHAR *fn);
71 | ZRESULT UnzipItem(HZIP hz, int index, void *z, unsigned int len);
72 | ZRESULT UnzipItemHandle(HZIP hz, int index, HANDLE h);
73 | // UnzipItem - given an index to an item, unzips it. You can unzip to:
74 | // to a pipe: UnzipItemHandle(hz,i, hpipe_write);
75 | // to a file (by handle): UnzipItemHandle(hz,i, hfile);
76 | // to a file (by name): UnzipItem(hz,i, ze.name);
77 | // to a memory block: UnzipItem(hz,i, buf,buflen);
78 | // In the final case, if the buffer isn't large enough to hold it all,
79 | // then the return code indicates that more is yet to come. If it was
80 | // large enough, and you want to know precisely how big, GetZipItem.
81 | // Note: zip files are normally stored with relative pathnames. If you
82 | // unzip with ZIP_FILENAME a relative pathname then the item gets created
83 | // relative to the current directory - it first ensures that all necessary
84 | // subdirectories have been created. Also, the item may itself be a directory.
85 | // If you unzip a directory with ZIP_FILENAME, then the directory gets created.
86 | // If you unzip it to a handle or a memory block, then nothing gets created
87 | // and it emits 0 bytes.
88 | ZRESULT SetUnzipBaseDir(HZIP hz, const TCHAR *dir);
89 | // if unzipping to a filename, and it's a relative filename, then it will be relative to here.
90 | // (defaults to current-directory).
91 |
92 |
93 | ZRESULT CloseZip(HZIP hz);
94 | // CloseZip - the zip handle must be closed with this function.
95 |
96 | unsigned int FormatZipMessage(ZRESULT code, TCHAR *buf, unsigned int len);
97 | // FormatZipMessage - given an error code, formats it as a string.
98 | // It returns the length of the error message. If buf/len points
99 | // to a real buffer, then it also writes as much as possible into there.
100 |
101 |
102 | // These are the result codes:
103 | #define ZR_OK 0x00000000 // nb. the pseudo-code zr-recent is never returned,
104 | #define ZR_RECENT 0x00000001 // but can be passed to FormatZipMessage.
105 | // The following come from general system stuff (e.g. files not openable)
106 | #define ZR_GENMASK 0x0000FF00
107 | #define ZR_NODUPH 0x00000100 // couldn't duplicate the handle
108 | #define ZR_NOFILE 0x00000200 // couldn't create/open the file
109 | #define ZR_NOALLOC 0x00000300 // failed to allocate some resource
110 | #define ZR_WRITE 0x00000400 // a general error writing to the file
111 | #define ZR_NOTFOUND 0x00000500 // couldn't find that file in the zip
112 | #define ZR_MORE 0x00000600 // there's still more data to be unzipped
113 | #define ZR_CORRUPT 0x00000700 // the zipfile is corrupt or not a zipfile
114 | #define ZR_READ 0x00000800 // a general error reading the file
115 | #define ZR_PASSWORD 0x00001000 // we didn't get the right password to unzip the file
116 | // The following come from mistakes on the part of the caller
117 | #define ZR_CALLERMASK 0x00FF0000
118 | #define ZR_ARGS 0x00010000 // general mistake with the arguments
119 | #define ZR_NOTMMAP 0x00020000 // tried to ZipGetMemory, but that only works on mmap zipfiles, which yours wasn't
120 | #define ZR_MEMSIZE 0x00030000 // the memory size is too small
121 | #define ZR_FAILED 0x00040000 // the thing was already failed when you called this function
122 | #define ZR_ENDED 0x00050000 // the zip creation has already been closed
123 | #define ZR_MISSIZE 0x00060000 // the indicated input file size turned out mistaken
124 | #define ZR_PARTIALUNZ 0x00070000 // the file had already been partially unzipped
125 | #define ZR_ZMODE 0x00080000 // tried to mix creating/opening a zip
126 | // The following come from bugs within the zip library itself
127 | #define ZR_BUGMASK 0xFF000000
128 | #define ZR_NOTINITED 0x01000000 // initialisation didn't work
129 | #define ZR_SEEK 0x02000000 // trying to seek in an unseekable file
130 | #define ZR_NOCHANGE 0x04000000 // changed its mind on storage, but not allowed
131 | #define ZR_FLATE 0x05000000 // an internal error in the de/inflation code
132 |
133 |
134 |
135 |
136 |
137 | // e.g.
138 | //
139 | // SetCurrentDirectory("c:\\docs\\stuff");
140 | // HZIP hz = OpenZip("c:\\stuff.zip",0);
141 | // ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
142 | // for (int i=0; i
2 | #include
3 | #include
4 | #include
5 | #include "ZipDefine.h"
6 | #include "zip.h"
7 |
8 |
9 | // THIS FILE is almost entirely based upon code by info-zip.
10 | // It has been modified by Lucian Wischik. The modifications
11 | // were a complete rewrite of the bit of code that generates the
12 | // layout of the zipfile, and support for zipping to/from memory
13 | // or handles or pipes or pagefile or diskfiles, encryption, unicode.
14 | // The original code may be found at http://www.info-zip.org
15 | // The original copyright text follows.
16 | //
17 | //
18 | //
19 | // This is version 1999-Oct-05 of the Info-ZIP copyright and license.
20 | // The definitive version of this document should be available at
21 | // ftp://ftp.cdrom.com/pub/infozip/license.html indefinitely.
22 | //
23 | // Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
24 | //
25 | // For the purposes of this copyright and license, "Info-ZIP" is defined as
26 | // the following set of individuals:
27 | //
28 | // Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,
29 | // Jean-loup Gailly, Hunter Goatley, Ian Gorman, Chris Herborth, Dirk Haase,
30 | // Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, David Kirschbaum,
31 | // Johnny Lee, Onno van der Linden, Igor Mandrichenko, Steve P. Miller,
32 | // Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, Kai Uwe Rommel,
33 | // Steve Salisbury, Dave Smith, Christian Spieler, Antoine Verheijen,
34 | // Paul von Behren, Rich Wales, Mike White
35 | //
36 | // This software is provided "as is," without warranty of any kind, express
37 | // or implied. In no event shall Info-ZIP or its contributors be held liable
38 | // for any direct, indirect, incidental, special or consequential damages
39 | // arising out of the use of or inability to use this software.
40 | //
41 | // Permission is granted to anyone to use this software for any purpose,
42 | // including commercial applications, and to alter it and redistribute it
43 | // freely, subject to the following restrictions:
44 | //
45 | // 1. Redistributions of source code must retain the above copyright notice,
46 | // definition, disclaimer, and this list of conditions.
47 | //
48 | // 2. Redistributions in binary form must reproduce the above copyright
49 | // notice, definition, disclaimer, and this list of conditions in
50 | // documentation and/or other materials provided with the distribution.
51 | //
52 | // 3. Altered versions--including, but not limited to, ports to new operating
53 | // systems, existing ports with new graphical interfaces, and dynamic,
54 | // shared, or static library versions--must be plainly marked as such
55 | // and must not be misrepresented as being the original source. Such
56 | // altered versions also must not be misrepresented as being Info-ZIP
57 | // releases--including, but not limited to, labeling of the altered
58 | // versions with the names "Info-ZIP" (or any variation thereof, including,
59 | // but not limited to, different capitalizations), "Pocket UnZip," "WiZ"
60 | // or "MacZip" without the explicit permission of Info-ZIP. Such altered
61 | // versions are further prohibited from misrepresentative use of the
62 | // Zip-Bugs or Info-ZIP e-mail addresses or of the Info-ZIP URL(s).
63 | //
64 | // 4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip,"
65 | // "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its own source and
66 | // binary releases.
67 | //
68 |
69 |
70 | typedef unsigned char uch; // unsigned 8-bit value
71 | typedef unsigned short ush; // unsigned 16-bit value
72 | typedef unsigned long ulg; // unsigned 32-bit value
73 | typedef size_t extent; // file size
74 | typedef unsigned Pos; // must be at least 32 bits
75 | typedef unsigned IPos; // A Pos is an index in the character window. Pos is used only for parameter passing
76 |
77 | #ifndef EOF
78 | #define EOF (-1)
79 | #endif
80 |
81 |
82 |
83 |
84 |
85 |
86 | // Error return values. The values 0..4 and 12..18 follow the conventions
87 | // of PKZIP. The values 4..10 are all assigned to "insufficient memory"
88 | // by PKZIP, so the codes 5..10 are used here for other purposes.
89 | #define ZE_MISS -1 // used by procname(), zipbare()
90 | #define ZE_OK 0 // success
91 | #define ZE_EOF 2 // unexpected end of zip file
92 | #define ZE_FORM 3 // zip file structure error
93 | #define ZE_MEM 4 // out of memory
94 | #define ZE_LOGIC 5 // internal logic error
95 | #define ZE_BIG 6 // entry too large to split
96 | #define ZE_NOTE 7 // invalid comment format
97 | #define ZE_TEST 8 // zip test (-T) failed or out of memory
98 | #define ZE_ABORT 9 // user interrupt or termination
99 | #define ZE_TEMP 10 // error using a temp file
100 | #define ZE_READ 11 // read or seek error
101 | #define ZE_NONE 12 // nothing to do
102 | #define ZE_NAME 13 // missing or empty zip file
103 | #define ZE_WRITE 14 // error writing to a file
104 | #define ZE_CREAT 15 // couldn't open to write
105 | #define ZE_PARMS 16 // bad command line
106 | #define ZE_OPEN 18 // could not open a specified file to read
107 | #define ZE_MAXERR 18 // the highest error number
108 |
109 |
110 | // internal file attribute
111 | #define UNKNOWN (-1)
112 | #define BINARY 0
113 | #define ASCII 1
114 |
115 | #define BEST -1 // Use best method (deflation or store)
116 | #define STORE 0 // Store method
117 | #define DEFLATE 8 // Deflation method
118 |
119 | #define CRCVAL_INITIAL 0L
120 |
121 | // MSDOS file or directory attributes
122 | #define MSDOS_HIDDEN_ATTR 0x02
123 | #define MSDOS_DIR_ATTR 0x10
124 |
125 | // Lengths of headers after signatures in bytes
126 | #define LOCHEAD 26
127 | #define CENHEAD 42
128 | #define ENDHEAD 18
129 |
130 | // Definitions for extra field handling:
131 | #define EB_HEADSIZE 4 /* length of a extra field block header */
132 | #define EB_LEN 2 /* offset of data length field in header */
133 | #define EB_UT_MINLEN 1 /* minimal UT field contains Flags byte */
134 | #define EB_UT_FLAGS 0 /* byte offset of Flags field */
135 | #define EB_UT_TIME1 1 /* byte offset of 1st time value */
136 | #define EB_UT_FL_MTIME (1 << 0) /* mtime present */
137 | #define EB_UT_FL_ATIME (1 << 1) /* atime present */
138 | #define EB_UT_FL_CTIME (1 << 2) /* ctime present */
139 | #define EB_UT_LEN(n) (EB_UT_MINLEN + 4 * (n))
140 | #define EB_L_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(3))
141 | #define EB_C_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(1))
142 |
143 |
144 | // Macros for writing machine integers to little-endian format
145 | #define PUTSH(a,f) {char _putsh_c=(char)((a)&0xff); wfunc(param,&_putsh_c,1); _putsh_c=(char)((a)>>8); wfunc(param,&_putsh_c,1);}
146 | #define PUTLG(a,f) {PUTSH((a) & 0xffff,(f)) PUTSH((a) >> 16,(f))}
147 |
148 |
149 | // -- Structure of a ZIP file --
150 | // Signatures for zip file information headers
151 | #define LOCSIG 0x04034b50L
152 | #define CENSIG 0x02014b50L
153 | #define ENDSIG 0x06054b50L
154 | #define EXTLOCSIG 0x08074b50L
155 |
156 |
157 | #define MIN_MATCH 3
158 | #define MAX_MATCH 258
159 | // The minimum and maximum match lengths
160 |
161 |
162 | #define WSIZE (0x8000)
163 | // Maximum window size = 32K. If you are really short of memory, compile
164 | // with a smaller WSIZE but this reduces the compression ratio for files
165 | // of size > WSIZE. WSIZE must be a power of two in the current implementation.
166 | //
167 |
168 | #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
169 | // Minimum amount of lookahead, except at the end of the input file.
170 | // See deflate.c for comments about the MIN_MATCH+1.
171 | //
172 |
173 | #define MAX_DIST (WSIZE-MIN_LOOKAHEAD)
174 | // In order to simplify the code, particularly on 16 bit machines, match
175 | // distances are limited to MAX_DIST instead of WSIZE.
176 | //
177 |
178 |
179 | #define ZIP_HANDLE 1
180 | #define ZIP_FILENAME 2
181 | #define ZIP_MEMORY 3
182 | #define ZIP_FOLDER 4
183 |
184 |
185 |
186 | // ===========================================================================
187 | // Constants
188 | //
189 |
190 | #define MAX_BITS 15
191 | // All codes must not exceed MAX_BITS bits
192 |
193 | #define MAX_BL_BITS 7
194 | // Bit length codes must not exceed MAX_BL_BITS bits
195 |
196 | #define LENGTH_CODES 29
197 | // number of length codes, not counting the special END_BLOCK code
198 |
199 | #define LITERALS 256
200 | // number of literal bytes 0..255
201 |
202 | #define END_BLOCK 256
203 | // end of block literal code
204 |
205 | #define L_CODES (LITERALS+1+LENGTH_CODES)
206 | // number of Literal or Length codes, including the END_BLOCK code
207 |
208 | #define D_CODES 30
209 | // number of distance codes
210 |
211 | #define BL_CODES 19
212 | // number of codes used to transfer the bit lengths
213 |
214 |
215 | #define STORED_BLOCK 0
216 | #define STATIC_TREES 1
217 | #define DYN_TREES 2
218 | // The three kinds of block type
219 |
220 | #define LIT_BUFSIZE 0x8000
221 | #define DIST_BUFSIZE LIT_BUFSIZE
222 | // Sizes of match buffers for literals/lengths and distances. There are
223 | // 4 reasons for limiting LIT_BUFSIZE to 64K:
224 | // - frequencies can be kept in 16 bit counters
225 | // - if compression is not successful for the first block, all input data is
226 | // still in the window so we can still emit a stored block even when input
227 | // comes from standard input. (This can also be done for all blocks if
228 | // LIT_BUFSIZE is not greater than 32K.)
229 | // - if compression is not successful for a file smaller than 64K, we can
230 | // even emit a stored file instead of a stored block (saving 5 bytes).
231 | // - creating new Huffman trees less frequently may not provide fast
232 | // adaptation to changes in the input data statistics. (Take for
233 | // example a binary file with poorly compressible code followed by
234 | // a highly compressible string table.) Smaller buffer sizes give
235 | // fast adaptation but have of course the overhead of transmitting trees
236 | // more frequently.
237 | // - I can't count above 4
238 | // The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save
239 | // memory at the expense of compression). Some optimizations would be possible
240 | // if we rely on DIST_BUFSIZE == LIT_BUFSIZE.
241 | //
242 |
243 | #define REP_3_6 16
244 | // repeat previous bit length 3-6 times (2 bits of repeat count)
245 |
246 | #define REPZ_3_10 17
247 | // repeat a zero length 3-10 times (3 bits of repeat count)
248 |
249 | #define REPZ_11_138 18
250 | // repeat a zero length 11-138 times (7 bits of repeat count)
251 |
252 | #define HEAP_SIZE (2*L_CODES+1)
253 | // maximum heap size
254 |
255 |
256 | // ===========================================================================
257 | // Local data used by the "bit string" routines.
258 | //
259 |
260 | #define Buf_size (8 * 2*sizeof(char))
261 | // Number of bits used within bi_buf. (bi_buf may be implemented on
262 | // more than 16 bits on some systems.)
263 |
264 | // Output a 16 bit value to the bit stream, lower (oldest) byte first
265 | #define PUTSHORT(state,w) \
266 | { if (state.bs.out_offset >= state.bs.out_size-1) \
267 | state.flush_outbuf(state.param,state.bs.out_buf, &state.bs.out_offset); \
268 | state.bs.out_buf[state.bs.out_offset++] = (char) ((w) & 0xff); \
269 | state.bs.out_buf[state.bs.out_offset++] = (char) ((ush)(w) >> 8); \
270 | }
271 |
272 | #define PUTBYTE(state,b) \
273 | { if (state.bs.out_offset >= state.bs.out_size) \
274 | state.flush_outbuf(state.param,state.bs.out_buf, &state.bs.out_offset); \
275 | state.bs.out_buf[state.bs.out_offset++] = (char) (b); \
276 | }
277 |
278 | // DEFLATE.CPP HEADER
279 |
280 | #define HASH_BITS 15
281 | // For portability to 16 bit machines, do not use values above 15.
282 |
283 | #define HASH_SIZE (unsigned)(1<= HASH_BITS
312 |
313 | #define max_insert_length max_lazy_match
314 | // Insert new strings in the hash table only if the match length
315 | // is not greater than this length. This saves time but degrades compression.
316 | // max_insert_length is used only for compression levels <= 3.
317 |
318 |
319 |
320 | const int extra_lbits[LENGTH_CODES] // extra bits for each length code
321 | = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 };
322 |
323 | const int extra_dbits[D_CODES] // extra bits for each distance code
324 | = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
325 |
326 | const int extra_blbits[BL_CODES]// extra bits for each bit length code
327 | = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };
328 |
329 | const uch bl_order[BL_CODES] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
330 | // The lengths of the bit length codes are sent in order of decreasing
331 | // probability, to avoid transmitting the lengths for unused bit length codes.
332 |
333 |
334 | typedef struct config {
335 | ush good_length; // reduce lazy search above this match length
336 | ush max_lazy; // do not perform lazy search above this match length
337 | ush nice_length; // quit search above this match length
338 | ush max_chain;
339 | } config;
340 |
341 | // Values for max_lazy_match, good_match, nice_match and max_chain_length,
342 | // depending on the desired pack level (0..9). The values given below have
343 | // been tuned to exclude worst case performance for pathological files.
344 | // Better values may be found for specific files.
345 | //
346 |
347 | const config configuration_table[10] = {
348 | // good lazy nice chain
349 | { 0, 0, 0, 0 }, // 0 store only
350 | { 4, 4, 8, 4 }, // 1 maximum speed, no lazy matches
351 | { 4, 5, 16, 8 }, // 2
352 | { 4, 6, 32, 32 }, // 3
353 | { 4, 4, 16, 16 }, // 4 lazy matches */
354 | { 8, 16, 32, 32 }, // 5
355 | { 8, 16, 128, 128 }, // 6
356 | { 8, 32, 128, 256 }, // 7
357 | { 32, 128, 258, 1024 }, // 8
358 | { 32, 258, 258, 4096 } };// 9 maximum compression */
359 |
360 | // Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
361 | // For deflate_fast() (levels <= 3) good is ignored and lazy has a different meaning.
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 | // Data structure describing a single value and its code string.
370 | typedef struct ct_data {
371 | union {
372 | ush freq; // frequency count
373 | ush code; // bit string
374 | } fc;
375 | union {
376 | ush dad; // father node in Huffman tree
377 | ush len; // length of bit string
378 | } dl;
379 | } ct_data;
380 |
381 | typedef struct tree_desc {
382 | ct_data *dyn_tree; // the dynamic tree
383 | ct_data *static_tree; // corresponding static tree or NULL
384 | const int *extra_bits; // extra bits for each code or NULL
385 | int extra_base; // base index for extra_bits
386 | int elems; // max number of elements in the tree
387 | int max_length; // max bit length for the codes
388 | int max_code; // largest code with non zero frequency
389 | } tree_desc;
390 |
391 |
392 |
393 |
394 | class TTreeState
395 | {
396 | public:
397 | TTreeState();
398 |
399 | ct_data dyn_ltree[HEAP_SIZE]; // literal and length tree
400 | ct_data dyn_dtree[2 * D_CODES + 1]; // distance tree
401 | ct_data static_ltree[L_CODES + 2]; // the static literal tree...
402 | // ... Since the bit lengths are imposed, there is no need for the L_CODES
403 | // extra codes used during heap construction. However the codes 286 and 287
404 | // are needed to build a canonical tree (see ct_init below).
405 | ct_data static_dtree[D_CODES]; // the static distance tree...
406 | // ... (Actually a trivial tree since all codes use 5 bits.)
407 | ct_data bl_tree[2 * BL_CODES + 1]; // Huffman tree for the bit lengths
408 |
409 | tree_desc l_desc;
410 | tree_desc d_desc;
411 | tree_desc bl_desc;
412 |
413 | ush bl_count[MAX_BITS + 1]; // number of codes at each bit length for an optimal tree
414 |
415 | int heap[2 * L_CODES + 1]; // heap used to build the Huffman trees
416 | int heap_len; // number of elements in the heap
417 | int heap_max; // element of largest frequency
418 | // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
419 | // The same heap array is used to build all trees.
420 |
421 | uch depth[2 * L_CODES + 1];
422 | // Depth of each subtree used as tie breaker for trees of equal frequency
423 |
424 | uch length_code[MAX_MATCH - MIN_MATCH + 1];
425 | // length code for each normalized match length (0 == MIN_MATCH)
426 |
427 | uch dist_code[512];
428 | // distance codes. The first 256 values correspond to the distances
429 | // 3 .. 258, the last 256 values correspond to the top 8 bits of
430 | // the 15 bit distances.
431 |
432 | int base_length[LENGTH_CODES];
433 | // First normalized length for each code (0 = MIN_MATCH)
434 |
435 | int base_dist[D_CODES];
436 | // First normalized distance for each code (0 = distance of 1)
437 |
438 | uch l_buf[LIT_BUFSIZE]; // buffer for literals/lengths
439 | ush d_buf[DIST_BUFSIZE]; // buffer for distances
440 |
441 | uch flag_buf[(LIT_BUFSIZE / 8)];
442 | // flag_buf is a bit array distinguishing literals from lengths in
443 | // l_buf, and thus indicating the presence or absence of a distance.
444 |
445 | unsigned last_lit; // running index in l_buf
446 | unsigned last_dist; // running index in d_buf
447 | unsigned last_flags; // running index in flag_buf
448 | uch flags; // current flags not yet saved in flag_buf
449 | uch flag_bit; // current bit used in flags
450 | // bits are filled in flags starting at bit 0 (least significant).
451 | // Note: these flags are overkill in the current code since we don't
452 | // take advantage of DIST_BUFSIZE == LIT_BUFSIZE.
453 |
454 | ulg opt_len; // bit length of current block with optimal trees
455 | ulg static_len; // bit length of current block with static trees
456 |
457 | ulg cmpr_bytelen; // total byte length of compressed file
458 | ulg cmpr_len_bits; // number of bits past 'cmpr_bytelen'
459 |
460 | ulg input_len; // total byte length of input file
461 | // input_len is for debugging only since we can get it by other means.
462 |
463 | ush *file_type; // pointer to UNKNOWN, BINARY or ASCII
464 | // int *file_method; // pointer to DEFLATE or STORE
465 | };
466 |
467 | TTreeState::TTreeState()
468 | {
469 | tree_desc a = { dyn_ltree, static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS, 0 }; l_desc = a;
470 | tree_desc b = { dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0 }; d_desc = b;
471 | tree_desc c = { bl_tree, NULL, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0 }; bl_desc = c;
472 | last_lit = 0;
473 | last_dist = 0;
474 | last_flags = 0;
475 | }
476 |
477 |
478 |
479 | class TBitState
480 | {
481 | public:
482 |
483 | int flush_flg;
484 | //
485 | unsigned bi_buf;
486 | // Output buffer. bits are inserted starting at the bottom (least significant
487 | // bits). The width of bi_buf must be at least 16 bits.
488 | int bi_valid;
489 | // Number of valid bits in bi_buf. All bits above the last valid bit
490 | // are always zero.
491 | char *out_buf;
492 | // Current output buffer.
493 | unsigned out_offset;
494 | // Current offset in output buffer.
495 | // On 16 bit machines, the buffer is limited to 64K.
496 | unsigned out_size;
497 | // Size of current output buffer
498 | ulg bits_sent; // bit length of the compressed data only needed for debugging???
499 | };
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 | class TDeflateState
508 | {
509 | public:
510 | TDeflateState() { window_size = 0; }
511 |
512 | uch window[2L * WSIZE];
513 | // Sliding window. Input bytes are read into the second half of the window,
514 | // and move to the first half later to keep a dictionary of at least WSIZE
515 | // bytes. With this organization, matches are limited to a distance of
516 | // WSIZE-MAX_MATCH bytes, but this ensures that IO is always
517 | // performed with a length multiple of the block size. Also, it limits
518 | // the window size to 64K, which is quite useful on MSDOS.
519 | // To do: limit the window size to WSIZE+CBSZ if SMALL_MEM (the code would
520 | // be less efficient since the data would have to be copied WSIZE/CBSZ times)
521 | Pos prev[WSIZE];
522 | // Link to older string with same hash index. To limit the size of this
523 | // array to 64K, this link is maintained only for the last 32K strings.
524 | // An index in this array is thus a window index modulo 32K.
525 | Pos head[HASH_SIZE];
526 | // Heads of the hash chains or NIL. If your compiler thinks that
527 | // HASH_SIZE is a dynamic value, recompile with -DDYN_ALLOC.
528 |
529 | ulg window_size;
530 | // window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
531 | // input file length plus MIN_LOOKAHEAD.
532 |
533 | long block_start;
534 | // window position at the beginning of the current output block. Gets
535 | // negative when the window is moved backwards.
536 |
537 | int sliding;
538 | // Set to false when the input file is already in memory
539 |
540 | unsigned ins_h; // hash index of string to be inserted
541 |
542 | unsigned int prev_length;
543 | // Length of the best match at previous step. Matches not greater than this
544 | // are discarded. This is used in the lazy match evaluation.
545 |
546 | unsigned strstart; // start of string to insert
547 | unsigned match_start; // start of matching string
548 | int eofile; // flag set at end of input file
549 | unsigned lookahead; // number of valid bytes ahead in window
550 |
551 | unsigned max_chain_length;
552 | // To speed up deflation, hash chains are never searched beyond this length.
553 | // A higher limit improves compression ratio but degrades the speed.
554 |
555 | unsigned int max_lazy_match;
556 | // Attempt to find a better match only when the current match is strictly
557 | // smaller than this value. This mechanism is used only for compression
558 | // levels >= 4.
559 |
560 | unsigned good_match;
561 | // Use a faster search when the previous match is longer than this
562 |
563 | int nice_match; // Stop searching when current match exceeds this
564 | };
565 |
566 | typedef long lutime_t; // define it ourselves since we don't include time.h
567 |
568 | typedef struct iztimes {
569 | lutime_t atime, mtime, ctime;
570 | } iztimes; // access, modify, create times
571 |
572 | typedef struct zlist {
573 | ush vem, ver, flg, how; // See central header in zipfile.c for what vem..off are
574 | ulg tim, crc, siz, len;
575 | extent nam, ext, cext, com; // offset of ext must be >= LOCHEAD
576 | ush dsk, att, lflg; // offset of lflg must be >= LOCHEAD
577 | ulg atx, off;
578 | char name[MAX_PATH]; // File name in zip file
579 | char *extra; // Extra field (set only if ext != 0)
580 | char *cextra; // Extra in central (set only if cext != 0)
581 | char *comment; // Comment (set only if com != 0)
582 | char iname[MAX_PATH]; // Internal file name after cleanup
583 | char zname[MAX_PATH]; // External version of internal name
584 | int mark; // Marker for files to operate on
585 | int trash; // Marker for files to delete
586 | int dosflag; // Set to force MSDOS file attributes
587 | struct zlist *nxt; // Pointer to next header in list
588 | } TZipFileInfo;
589 |
590 |
591 | struct TState;
592 | typedef unsigned(*READFUNC)(TState &state, char *buf, unsigned size);
593 | typedef unsigned(*FLUSHFUNC)(void *param, const char *buf, unsigned *size);
594 | typedef unsigned(*WRITEFUNC)(void *param, const char *buf, unsigned size);
595 | struct TState
596 | {
597 | void *param;
598 | int level; bool seekable;
599 | READFUNC readfunc; FLUSHFUNC flush_outbuf;
600 | TTreeState ts; TBitState bs; TDeflateState ds;
601 | const char *err;
602 | };
603 |
604 |
605 |
606 |
607 | // ----------------------------------------------------------------------
608 | // some windows<->linux portability things
609 | void filetime2dosdatetime(const FILETIME ft, WORD *dosdate, WORD *dostime)
610 | { // date: bits 0-4 are day of month 1-31. Bits 5-8 are month 1..12. Bits 9-15 are year-1980
611 | // time: bits 0-4 are seconds/2, bits 5-10 are minute 0..59. Bits 11-15 are hour 0..23
612 | SYSTEMTIME st; FileTimeToSystemTime(&ft, &st);
613 | *dosdate = (WORD)(((st.wYear - 1980) & 0x7f) << 9);
614 | *dosdate |= (WORD)((st.wMonth & 0xf) << 5);
615 | *dosdate |= (WORD)((st.wDay & 0x1f));
616 | *dostime = (WORD)((st.wHour & 0x1f) << 11);
617 | *dostime |= (WORD)((st.wMinute & 0x3f) << 5);
618 | *dostime |= (WORD)((st.wSecond * 2) & 0x1f);
619 | }
620 |
621 | lutime_t filetime2timet(const FILETIME ft)
622 | {
623 | LONGLONG i = *(LONGLONG*)&ft;
624 | return (lutime_t)((i - 116444736000000000LL) / 10000000LL);
625 | }
626 |
627 | void GetNow(lutime_t *pft, WORD *dosdate, WORD *dostime)
628 | {
629 | SYSTEMTIME st; GetLocalTime(&st);
630 | FILETIME ft; SystemTimeToFileTime(&st, &ft);
631 | filetime2dosdatetime(ft, dosdate, dostime);
632 | *pft = filetime2timet(ft);
633 | }
634 |
635 | DWORD GetFilePosZ(HANDLE hfout)
636 | {
637 | return SetFilePointer(hfout, 0, 0, FILE_CURRENT);
638 | }
639 |
640 |
641 | ZRESULT GetFileInfo(HANDLE hf, ulg *attr, long *size, iztimes *times, ulg *timestamp)
642 | { // The handle must be a handle to a file
643 | // The date and time is returned in a long with the date most significant to allow
644 | // unsigned integer comparison of absolute times. The attributes have two
645 | // high bytes unix attr, and two low bytes a mapping of that to DOS attr.
646 | //struct stat s; int res=stat(fn,&s); if (res!=0) return false;
647 | // translate windows file attributes into zip ones.
648 | BY_HANDLE_FILE_INFORMATION bhi; BOOL res = GetFileInformationByHandle(hf, &bhi);
649 | if (!res) return ZR_NOFILE;
650 | DWORD fa = bhi.dwFileAttributes; ulg a = 0;
651 | // Zip uses the lower word for its interpretation of windows stuff
652 | if (fa&FILE_ATTRIBUTE_READONLY) a |= 0x01;
653 | if (fa&FILE_ATTRIBUTE_HIDDEN) a |= 0x02;
654 | if (fa&FILE_ATTRIBUTE_SYSTEM) a |= 0x04;
655 | if (fa&FILE_ATTRIBUTE_DIRECTORY)a |= 0x10;
656 | if (fa&FILE_ATTRIBUTE_ARCHIVE) a |= 0x20;
657 | // It uses the upper word for standard unix attr, which we manually construct
658 | if (fa&FILE_ATTRIBUTE_DIRECTORY)a |= 0x40000000; // directory
659 | else a |= 0x80000000; // normal file
660 | a |= 0x01000000; // readable
661 | if (fa&FILE_ATTRIBUTE_READONLY) {}
662 | else a |= 0x00800000; // writeable
663 | // now just a small heuristic to check if it's an executable:
664 | DWORD red, hsize = GetFileSize(hf, NULL); if (hsize>40)
665 | {
666 | SetFilePointer(hf, 0, NULL, FILE_BEGIN); unsigned short magic; ReadFile(hf, &magic, sizeof(magic), &red, NULL);
667 | SetFilePointer(hf, 36, NULL, FILE_BEGIN); unsigned long hpos; ReadFile(hf, &hpos, sizeof(hpos), &red, NULL);
668 | if (magic == 0x54AD && hsize>hpos + 4 + 20 + 28)
669 | {
670 | SetFilePointer(hf, hpos, NULL, FILE_BEGIN); unsigned long signature; ReadFile(hf, &signature, sizeof(signature), &red, NULL);
671 | if (signature == IMAGE_DOS_SIGNATURE || signature == IMAGE_OS2_SIGNATURE
672 | || signature == IMAGE_OS2_SIGNATURE_LE || signature == IMAGE_NT_SIGNATURE)
673 | {
674 | a |= 0x00400000; // executable
675 | }
676 | }
677 | }
678 | //
679 | if (attr != NULL) *attr = a;
680 | if (size != NULL) *size = hsize;
681 | if (times != NULL)
682 | { // lutime_t is 32bit number of seconds elapsed since 0:0:0GMT, Jan1, 1970.
683 | // but FILETIME is 64bit number of 100-nanosecs since Jan1, 1601
684 | times->atime = filetime2timet(bhi.ftLastAccessTime);
685 | times->mtime = filetime2timet(bhi.ftLastWriteTime);
686 | times->ctime = filetime2timet(bhi.ftCreationTime);
687 | }
688 | if (timestamp != NULL)
689 | {
690 | WORD dosdate, dostime;
691 | filetime2dosdatetime(bhi.ftLastWriteTime, &dosdate, &dostime);
692 | *timestamp = (WORD)dostime | (((DWORD)dosdate) << 16);
693 | }
694 | return ZR_OK;
695 | }
696 | // ----------------------------------------------------------------------
697 |
698 |
699 |
700 |
701 |
702 | void Assert(TState &state, bool cond, const char *msg)
703 | {
704 | if (cond) return;
705 | state.err = msg;
706 | }
707 | void Trace(const char *x, ...) { va_list paramList; va_start(paramList, x); paramList; va_end(paramList); }
708 | void Tracec(bool, const char *x, ...) { va_list paramList; va_start(paramList, x); paramList; va_end(paramList); }
709 |
710 |
711 |
712 | // ===========================================================================
713 | // Local (static) routines in this file.
714 | //
715 |
716 | void init_block(TState &);
717 | void pqdownheap(TState &, ct_data *tree, int k);
718 | void gen_bitlen(TState &, tree_desc *desc);
719 | void gen_codes(TState &state, ct_data *tree, int max_code);
720 | void build_tree(TState &, tree_desc *desc);
721 | void scan_tree(TState &, ct_data *tree, int max_code);
722 | void send_tree(TState &state, ct_data *tree, int max_code);
723 | int build_bl_tree(TState &);
724 | void send_all_trees(TState &state, int lcodes, int dcodes, int blcodes);
725 | void compress_block(TState &state, ct_data *ltree, ct_data *dtree);
726 | void set_file_type(TState &);
727 | void send_bits(TState &state, int value, int length);
728 | unsigned bi_reverse(unsigned code, int len);
729 | void bi_windup(TState &state);
730 | void copy_block(TState &state, char *buf, unsigned len, int header);
731 |
732 |
733 | #define send_code(state, c, tree) send_bits(state, tree[c].fc.code, tree[c].dl.len)
734 | // Send a code of the given tree. c and tree must not have side effects
735 |
736 | // alternatively...
737 | //#define send_code(state, c, tree)
738 | // { if (state.verbose>1) fprintf(stderr,"\ncd %3d ",(c));
739 | // send_bits(state, tree[c].fc.code, tree[c].dl.len); }
740 |
741 | #define d_code(dist) ((dist) < 256 ? state.ts.dist_code[dist] : state.ts.dist_code[256+((dist)>>7)])
742 | // Mapping from a distance to a distance code. dist is the distance - 1 and
743 | // must not have side effects. dist_code[256] and dist_code[257] are never used.
744 |
745 | #define Max(a,b) (a >= b ? a : b)
746 | /* the arguments must not have side effects */
747 |
748 | /* ===========================================================================
749 | * Allocate the match buffer, initialize the various tables and save the
750 | * location of the internal file attribute (ascii/binary) and method
751 | * (DEFLATE/STORE).
752 | */
753 | void ct_init(TState &state, ush *attr)
754 | {
755 | int n; /* iterates over tree elements */
756 | int bits; /* bit counter */
757 | int length; /* length value */
758 | int code; /* code value */
759 | int dist; /* distance index */
760 |
761 | state.ts.file_type = attr;
762 | //state.ts.file_method = method;
763 | state.ts.cmpr_bytelen = state.ts.cmpr_len_bits = 0L;
764 | state.ts.input_len = 0L;
765 |
766 | if (state.ts.static_dtree[0].dl.len != 0) return; /* ct_init already called */
767 |
768 | /* Initialize the mapping length (0..255) -> length code (0..28) */
769 | length = 0;
770 | for (code = 0; code < LENGTH_CODES - 1; code++) {
771 | state.ts.base_length[code] = length;
772 | for (n = 0; n < (1 << extra_lbits[code]); n++) {
773 | state.ts.length_code[length++] = (uch)code;
774 | }
775 | }
776 | Assert(state, length == 256, "ct_init: length != 256");
777 | /* Note that the length 255 (match length 258) can be represented
778 | * in two different ways: code 284 + 5 bits or code 285, so we
779 | * overwrite length_code[255] to use the best encoding:
780 | */
781 | state.ts.length_code[length - 1] = (uch)code;
782 |
783 | /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
784 | dist = 0;
785 | for (code = 0; code < 16; code++) {
786 | state.ts.base_dist[code] = dist;
787 | for (n = 0; n < (1 << extra_dbits[code]); n++) {
788 | state.ts.dist_code[dist++] = (uch)code;
789 | }
790 | }
791 | Assert(state, dist == 256, "ct_init: dist != 256");
792 | dist >>= 7; /* from now on, all distances are divided by 128 */
793 | for (; code < D_CODES; code++) {
794 | state.ts.base_dist[code] = dist << 7;
795 | for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
796 | state.ts.dist_code[256 + dist++] = (uch)code;
797 | }
798 | }
799 | Assert(state, dist == 256, "ct_init: 256+dist != 512");
800 |
801 | /* Construct the codes of the static literal tree */
802 | for (bits = 0; bits <= MAX_BITS; bits++) state.ts.bl_count[bits] = 0;
803 | n = 0;
804 | while (n <= 143) state.ts.static_ltree[n++].dl.len = 8, state.ts.bl_count[8]++;
805 | while (n <= 255) state.ts.static_ltree[n++].dl.len = 9, state.ts.bl_count[9]++;
806 | while (n <= 279) state.ts.static_ltree[n++].dl.len = 7, state.ts.bl_count[7]++;
807 | while (n <= 287) state.ts.static_ltree[n++].dl.len = 8, state.ts.bl_count[8]++;
808 | /* fc.codes 286 and 287 do not exist, but we must include them in the
809 | * tree construction to get a canonical Huffman tree (longest code
810 | * all ones)
811 | */
812 | gen_codes(state, (ct_data *)state.ts.static_ltree, L_CODES + 1);
813 |
814 | /* The static distance tree is trivial: */
815 | for (n = 0; n < D_CODES; n++) {
816 | state.ts.static_dtree[n].dl.len = 5;
817 | state.ts.static_dtree[n].fc.code = (ush)bi_reverse(n, 5);
818 | }
819 |
820 | /* Initialize the first block of the first file: */
821 | init_block(state);
822 | }
823 |
824 | /* ===========================================================================
825 | * Initialize a new block.
826 | */
827 | void init_block(TState &state)
828 | {
829 | int n; /* iterates over tree elements */
830 |
831 | /* Initialize the trees. */
832 | for (n = 0; n < L_CODES; n++) state.ts.dyn_ltree[n].fc.freq = 0;
833 | for (n = 0; n < D_CODES; n++) state.ts.dyn_dtree[n].fc.freq = 0;
834 | for (n = 0; n < BL_CODES; n++) state.ts.bl_tree[n].fc.freq = 0;
835 |
836 | state.ts.dyn_ltree[END_BLOCK].fc.freq = 1;
837 | state.ts.opt_len = state.ts.static_len = 0L;
838 | state.ts.last_lit = state.ts.last_dist = state.ts.last_flags = 0;
839 | state.ts.flags = 0; state.ts.flag_bit = 1;
840 | }
841 |
842 | #define SMALLEST 1
843 | /* Index within the heap array of least frequent node in the Huffman tree */
844 |
845 |
846 | /* ===========================================================================
847 | * Remove the smallest element from the heap and recreate the heap with
848 | * one less element. Updates heap and heap_len.
849 | */
850 | #define pqremove(tree, top) \
851 | {\
852 | top = state.ts.heap[SMALLEST]; \
853 | state.ts.heap[SMALLEST] = state.ts.heap[state.ts.heap_len--]; \
854 | pqdownheap(state,tree, SMALLEST); \
855 | }
856 |
857 | /* ===========================================================================
858 | * Compares to subtrees, using the tree depth as tie breaker when
859 | * the subtrees have equal frequency. This minimizes the worst case length.
860 | */
861 | #define smaller(tree, n, m) \
862 | (tree[n].fc.freq < tree[m].fc.freq || \
863 | (tree[n].fc.freq == tree[m].fc.freq && state.ts.depth[n] <= state.ts.depth[m]))
864 |
865 | /* ===========================================================================
866 | * Restore the heap property by moving down the tree starting at node k,
867 | * exchanging a node with the smallest of its two sons if necessary, stopping
868 | * when the heap property is re-established (each father smaller than its
869 | * two sons).
870 | */
871 | void pqdownheap(TState &state, ct_data *tree, int k)
872 | {
873 | int v = state.ts.heap[k];
874 | int j = k << 1; /* left son of k */
875 | int htemp; /* required because of bug in SASC compiler */
876 |
877 | while (j <= state.ts.heap_len) {
878 | /* Set j to the smallest of the two sons: */
879 | if (j < state.ts.heap_len && smaller(tree, state.ts.heap[j + 1], state.ts.heap[j])) j++;
880 |
881 | /* Exit if v is smaller than both sons */
882 | htemp = state.ts.heap[j];
883 | if (smaller(tree, v, htemp)) break;
884 |
885 | /* Exchange v with the smallest son */
886 | state.ts.heap[k] = htemp;
887 | k = j;
888 |
889 | /* And continue down the tree, setting j to the left son of k */
890 | j <<= 1;
891 | }
892 | state.ts.heap[k] = v;
893 | }
894 |
895 | /* ===========================================================================
896 | * Compute the optimal bit lengths for a tree and update the total bit length
897 | * for the current block.
898 | * IN assertion: the fields freq and dad are set, heap[heap_max] and
899 | * above are the tree nodes sorted by increasing frequency.
900 | * OUT assertions: the field len is set to the optimal bit length, the
901 | * array bl_count contains the frequencies for each bit length.
902 | * The length opt_len is updated; static_len is also updated if stree is
903 | * not null.
904 | */
905 | void gen_bitlen(TState &state, tree_desc *desc)
906 | {
907 | ct_data *tree = desc->dyn_tree;
908 | const int *extra = desc->extra_bits;
909 | int base = desc->extra_base;
910 | int max_code = desc->max_code;
911 | int max_length = desc->max_length;
912 | ct_data *stree = desc->static_tree;
913 | int h; /* heap index */
914 | int n, m; /* iterate over the tree elements */
915 | int bits; /* bit length */
916 | int xbits; /* extra bits */
917 | ush f; /* frequency */
918 | int overflow = 0; /* number of elements with bit length too large */
919 |
920 | for (bits = 0; bits <= MAX_BITS; bits++) state.ts.bl_count[bits] = 0;
921 |
922 | /* In a first pass, compute the optimal bit lengths (which may
923 | * overflow in the case of the bit length tree).
924 | */
925 | tree[state.ts.heap[state.ts.heap_max]].dl.len = 0; /* root of the heap */
926 |
927 | for (h = state.ts.heap_max + 1; h < HEAP_SIZE; h++) {
928 | n = state.ts.heap[h];
929 | bits = tree[tree[n].dl.dad].dl.len + 1;
930 | if (bits > max_length) bits = max_length, overflow++;
931 | tree[n].dl.len = (ush)bits;
932 | /* We overwrite tree[n].dl.dad which is no longer needed */
933 |
934 | if (n > max_code) continue; /* not a leaf node */
935 |
936 | state.ts.bl_count[bits]++;
937 | xbits = 0;
938 | if (n >= base) xbits = extra[n - base];
939 | f = tree[n].fc.freq;
940 | state.ts.opt_len += (ulg)f * (bits + xbits);
941 | if (stree) state.ts.static_len += (ulg)f * (stree[n].dl.len + xbits);
942 | }
943 | if (overflow == 0) return;
944 |
945 | Trace("\nbit length overflow\n");
946 | /* This happens for example on obj2 and pic of the Calgary corpus */
947 |
948 | /* Find the first bit length which could increase: */
949 | do {
950 | bits = max_length - 1;
951 | while (state.ts.bl_count[bits] == 0) bits--;
952 | state.ts.bl_count[bits]--; /* move one leaf down the tree */
953 | state.ts.bl_count[bits + 1] += (ush)2; /* move one overflow item as its brother */
954 | state.ts.bl_count[max_length]--;
955 | /* The brother of the overflow item also moves one step up,
956 | * but this does not affect bl_count[max_length]
957 | */
958 | overflow -= 2;
959 | } while (overflow > 0);
960 |
961 | /* Now recompute all bit lengths, scanning in increasing frequency.
962 | * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
963 | * lengths instead of fixing only the wrong ones. This idea is taken
964 | * from 'ar' written by Haruhiko Okumura.)
965 | */
966 | for (bits = max_length; bits != 0; bits--) {
967 | n = state.ts.bl_count[bits];
968 | while (n != 0) {
969 | m = state.ts.heap[--h];
970 | if (m > max_code) continue;
971 | if (tree[m].dl.len != (ush)bits) {
972 | Trace("code %d bits %d->%d\n", m, tree[m].dl.len, bits);
973 | state.ts.opt_len += ((long)bits - (long)tree[m].dl.len)*(long)tree[m].fc.freq;
974 | tree[m].dl.len = (ush)bits;
975 | }
976 | n--;
977 | }
978 | }
979 | }
980 |
981 | /* ===========================================================================
982 | * Generate the codes for a given tree and bit counts (which need not be
983 | * optimal).
984 | * IN assertion: the array bl_count contains the bit length statistics for
985 | * the given tree and the field len is set for all tree elements.
986 | * OUT assertion: the field code is set for all tree elements of non
987 | * zero code length.
988 | */
989 | void gen_codes(TState &state, ct_data *tree, int max_code)
990 | {
991 | ush next_code[MAX_BITS + 1]; /* next code value for each bit length */
992 | ush code = 0; /* running code value */
993 | int bits; /* bit index */
994 | int n; /* code index */
995 |
996 | /* The distribution counts are first used to generate the code values
997 | * without bit reversal.
998 | */
999 | for (bits = 1; bits <= MAX_BITS; bits++) {
1000 | next_code[bits] = code = (ush)((code + state.ts.bl_count[bits - 1]) << 1);
1001 | }
1002 | /* Check that the bit counts in bl_count are consistent. The last code
1003 | * must be all ones.
1004 | */
1005 | Assert(state, code + state.ts.bl_count[MAX_BITS] - 1 == (1 << ((ush)MAX_BITS)) - 1,
1006 | "inconsistent bit counts");
1007 | Trace("\ngen_codes: max_code %d ", max_code);
1008 |
1009 | for (n = 0; n <= max_code; n++) {
1010 | int len = tree[n].dl.len;
1011 | if (len == 0) continue;
1012 | /* Now reverse the bits */
1013 | tree[n].fc.code = (ush)bi_reverse(next_code[len]++, len);
1014 |
1015 | //Tracec(tree != state.ts.static_ltree, "\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n) ? n : ' '), len, tree[n].fc.code, next_code[len]-1);
1016 | }
1017 | }
1018 |
1019 | /* ===========================================================================
1020 | * Construct one Huffman tree and assigns the code bit strings and lengths.
1021 | * Update the total bit length for the current block.
1022 | * IN assertion: the field freq is set for all tree elements.
1023 | * OUT assertions: the fields len and code are set to the optimal bit length
1024 | * and corresponding code. The length opt_len is updated; static_len is
1025 | * also updated if stree is not null. The field max_code is set.
1026 | */
1027 | void build_tree(TState &state, tree_desc *desc)
1028 | {
1029 | ct_data *tree = desc->dyn_tree;
1030 | ct_data *stree = desc->static_tree;
1031 | int elems = desc->elems;
1032 | int n, m; /* iterate over heap elements */
1033 | int max_code = -1; /* largest code with non zero frequency */
1034 | int node = elems; /* next internal node of the tree */
1035 |
1036 | /* Construct the initial heap, with least frequent element in
1037 | * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
1038 | * heap[0] is not used.
1039 | */
1040 | state.ts.heap_len = 0, state.ts.heap_max = HEAP_SIZE;
1041 |
1042 | for (n = 0; n < elems; n++) {
1043 | if (tree[n].fc.freq != 0) {
1044 | state.ts.heap[++state.ts.heap_len] = max_code = n;
1045 | state.ts.depth[n] = 0;
1046 | }
1047 | else {
1048 | tree[n].dl.len = 0;
1049 | }
1050 | }
1051 |
1052 | /* The pkzip format requires that at least one distance code exists,
1053 | * and that at least one bit should be sent even if there is only one
1054 | * possible code. So to avoid special checks later on we force at least
1055 | * two codes of non zero frequency.
1056 | */
1057 | while (state.ts.heap_len < 2) {
1058 | int newcp = state.ts.heap[++state.ts.heap_len] = (max_code < 2 ? ++max_code : 0);
1059 | tree[newcp].fc.freq = 1;
1060 | state.ts.depth[newcp] = 0;
1061 | state.ts.opt_len--; if (stree) state.ts.static_len -= stree[newcp].dl.len;
1062 | /* new is 0 or 1 so it does not have extra bits */
1063 | }
1064 | desc->max_code = max_code;
1065 |
1066 | /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
1067 | * establish sub-heaps of increasing lengths:
1068 | */
1069 | for (n = state.ts.heap_len / 2; n >= 1; n--) pqdownheap(state, tree, n);
1070 |
1071 | /* Construct the Huffman tree by repeatedly combining the least two
1072 | * frequent nodes.
1073 | */
1074 | do {
1075 | pqremove(tree, n); /* n = node of least frequency */
1076 | m = state.ts.heap[SMALLEST]; /* m = node of next least frequency */
1077 |
1078 | state.ts.heap[--state.ts.heap_max] = n; /* keep the nodes sorted by frequency */
1079 | state.ts.heap[--state.ts.heap_max] = m;
1080 |
1081 | /* Create a new node father of n and m */
1082 | tree[node].fc.freq = (ush)(tree[n].fc.freq + tree[m].fc.freq);
1083 | state.ts.depth[node] = (uch)(Max(state.ts.depth[n], state.ts.depth[m]) + 1);
1084 | tree[n].dl.dad = tree[m].dl.dad = (ush)node;
1085 | /* and insert the new node in the heap */
1086 | state.ts.heap[SMALLEST] = node++;
1087 | pqdownheap(state, tree, SMALLEST);
1088 |
1089 | } while (state.ts.heap_len >= 2);
1090 |
1091 | state.ts.heap[--state.ts.heap_max] = state.ts.heap[SMALLEST];
1092 |
1093 | /* At this point, the fields freq and dad are set. We can now
1094 | * generate the bit lengths.
1095 | */
1096 | gen_bitlen(state, (tree_desc *)desc);
1097 |
1098 | /* The field len is now set, we can generate the bit codes */
1099 | gen_codes(state, (ct_data *)tree, max_code);
1100 | }
1101 |
1102 | /* ===========================================================================
1103 | * Scan a literal or distance tree to determine the frequencies of the codes
1104 | * in the bit length tree. Updates opt_len to take into account the repeat
1105 | * counts. (The contribution of the bit length codes will be added later
1106 | * during the construction of bl_tree.)
1107 | */
1108 | void scan_tree(TState &state, ct_data *tree, int max_code)
1109 | {
1110 | int n; /* iterates over all tree elements */
1111 | int prevlen = -1; /* last emitted length */
1112 | int curlen; /* length of current code */
1113 | int nextlen = tree[0].dl.len; /* length of next code */
1114 | int count = 0; /* repeat count of the current code */
1115 | int max_count = 7; /* max repeat count */
1116 | int min_count = 4; /* min repeat count */
1117 |
1118 | if (nextlen == 0) max_count = 138, min_count = 3;
1119 | tree[max_code + 1].dl.len = (ush)-1; /* guard */
1120 |
1121 | for (n = 0; n <= max_code; n++) {
1122 | curlen = nextlen; nextlen = tree[n + 1].dl.len;
1123 | if (++count < max_count && curlen == nextlen) {
1124 | continue;
1125 | }
1126 | else if (count < min_count) {
1127 | state.ts.bl_tree[curlen].fc.freq = (ush)(state.ts.bl_tree[curlen].fc.freq + count);
1128 | }
1129 | else if (curlen != 0) {
1130 | if (curlen != prevlen) state.ts.bl_tree[curlen].fc.freq++;
1131 | state.ts.bl_tree[REP_3_6].fc.freq++;
1132 | }
1133 | else if (count <= 10) {
1134 | state.ts.bl_tree[REPZ_3_10].fc.freq++;
1135 | }
1136 | else {
1137 | state.ts.bl_tree[REPZ_11_138].fc.freq++;
1138 | }
1139 | count = 0; prevlen = curlen;
1140 | if (nextlen == 0) {
1141 | max_count = 138, min_count = 3;
1142 | }
1143 | else if (curlen == nextlen) {
1144 | max_count = 6, min_count = 3;
1145 | }
1146 | else {
1147 | max_count = 7, min_count = 4;
1148 | }
1149 | }
1150 | }
1151 |
1152 | /* ===========================================================================
1153 | * Send a literal or distance tree in compressed form, using the codes in
1154 | * bl_tree.
1155 | */
1156 | void send_tree(TState &state, ct_data *tree, int max_code)
1157 | {
1158 | int n; /* iterates over all tree elements */
1159 | int prevlen = -1; /* last emitted length */
1160 | int curlen; /* length of current code */
1161 | int nextlen = tree[0].dl.len; /* length of next code */
1162 | int count = 0; /* repeat count of the current code */
1163 | int max_count = 7; /* max repeat count */
1164 | int min_count = 4; /* min repeat count */
1165 |
1166 | /* tree[max_code+1].dl.len = -1; */ /* guard already set */
1167 | if (nextlen == 0) max_count = 138, min_count = 3;
1168 |
1169 | for (n = 0; n <= max_code; n++) {
1170 | curlen = nextlen; nextlen = tree[n + 1].dl.len;
1171 | if (++count < max_count && curlen == nextlen) {
1172 | continue;
1173 | }
1174 | else if (count < min_count) {
1175 | do { send_code(state, curlen, state.ts.bl_tree); } while (--count != 0);
1176 |
1177 | }
1178 | else if (curlen != 0) {
1179 | if (curlen != prevlen) {
1180 | send_code(state, curlen, state.ts.bl_tree); count--;
1181 | }
1182 | Assert(state, count >= 3 && count <= 6, " 3_6?");
1183 | send_code(state, REP_3_6, state.ts.bl_tree); send_bits(state, count - 3, 2);
1184 |
1185 | }
1186 | else if (count <= 10) {
1187 | send_code(state, REPZ_3_10, state.ts.bl_tree); send_bits(state, count - 3, 3);
1188 |
1189 | }
1190 | else {
1191 | send_code(state, REPZ_11_138, state.ts.bl_tree); send_bits(state, count - 11, 7);
1192 | }
1193 | count = 0; prevlen = curlen;
1194 | if (nextlen == 0) {
1195 | max_count = 138, min_count = 3;
1196 | }
1197 | else if (curlen == nextlen) {
1198 | max_count = 6, min_count = 3;
1199 | }
1200 | else {
1201 | max_count = 7, min_count = 4;
1202 | }
1203 | }
1204 | }
1205 |
1206 | /* ===========================================================================
1207 | * Construct the Huffman tree for the bit lengths and return the index in
1208 | * bl_order of the last bit length code to send.
1209 | */
1210 | int build_bl_tree(TState &state)
1211 | {
1212 | int max_blindex; /* index of last bit length code of non zero freq */
1213 |
1214 | /* Determine the bit length frequencies for literal and distance trees */
1215 | scan_tree(state, (ct_data *)state.ts.dyn_ltree, state.ts.l_desc.max_code);
1216 | scan_tree(state, (ct_data *)state.ts.dyn_dtree, state.ts.d_desc.max_code);
1217 |
1218 | /* Build the bit length tree: */
1219 | build_tree(state, (tree_desc *)(&state.ts.bl_desc));
1220 | /* opt_len now includes the length of the tree representations, except
1221 | * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
1222 | */
1223 |
1224 | /* Determine the number of bit length codes to send. The pkzip format
1225 | * requires that at least 4 bit length codes be sent. (appnote.txt says
1226 | * 3 but the actual value used is 4.)
1227 | */
1228 | for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
1229 | if (state.ts.bl_tree[bl_order[max_blindex]].dl.len != 0) break;
1230 | }
1231 | /* Update opt_len to include the bit length tree and counts */
1232 | state.ts.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
1233 | Trace("\ndyn trees: dyn %ld, stat %ld", state.ts.opt_len, state.ts.static_len);
1234 |
1235 | return max_blindex;
1236 | }
1237 |
1238 | /* ===========================================================================
1239 | * Send the header for a block using dynamic Huffman trees: the counts, the
1240 | * lengths of the bit length codes, the literal tree and the distance tree.
1241 | * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
1242 | */
1243 | void send_all_trees(TState &state, int lcodes, int dcodes, int blcodes)
1244 | {
1245 | int rank; /* index in bl_order */
1246 |
1247 | Assert(state, lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
1248 | Assert(state, lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
1249 | "too many codes");
1250 | Trace("\nbl counts: ");
1251 | send_bits(state, lcodes - 257, 5);
1252 | /* not +255 as stated in appnote.txt 1.93a or -256 in 2.04c */
1253 | send_bits(state, dcodes - 1, 5);
1254 | send_bits(state, blcodes - 4, 4); /* not -3 as stated in appnote.txt */
1255 | for (rank = 0; rank < blcodes; rank++) {
1256 | Trace("\nbl code %2d ", bl_order[rank]);
1257 | send_bits(state, state.ts.bl_tree[bl_order[rank]].dl.len, 3);
1258 | }
1259 | Trace("\nbl tree: sent %ld", state.bs.bits_sent);
1260 |
1261 | send_tree(state, (ct_data *)state.ts.dyn_ltree, lcodes - 1); /* send the literal tree */
1262 | Trace("\nlit tree: sent %ld", state.bs.bits_sent);
1263 |
1264 | send_tree(state, (ct_data *)state.ts.dyn_dtree, dcodes - 1); /* send the distance tree */
1265 | Trace("\ndist tree: sent %ld", state.bs.bits_sent);
1266 | }
1267 |
1268 | /* ===========================================================================
1269 | * Determine the best encoding for the current block: dynamic trees, static
1270 | * trees or store, and output the encoded block to the zip file. This function
1271 | * returns the total compressed length (in bytes) for the file so far.
1272 | */
1273 | ulg flush_block(TState &state, char *buf, ulg stored_len, int eof)
1274 | {
1275 | ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
1276 | int max_blindex; /* index of last bit length code of non zero freq */
1277 |
1278 | state.ts.flag_buf[state.ts.last_flags] = state.ts.flags; /* Save the flags for the last 8 items */
1279 |
1280 | /* Check if the file is ascii or binary */
1281 | if (*state.ts.file_type == (ush)UNKNOWN) set_file_type(state);
1282 |
1283 | /* Construct the literal and distance trees */
1284 | build_tree(state, (tree_desc *)(&state.ts.l_desc));
1285 | Trace("\nlit data: dyn %ld, stat %ld", state.ts.opt_len, state.ts.static_len);
1286 |
1287 | build_tree(state, (tree_desc *)(&state.ts.d_desc));
1288 | Trace("\ndist data: dyn %ld, stat %ld", state.ts.opt_len, state.ts.static_len);
1289 | /* At this point, opt_len and static_len are the total bit lengths of
1290 | * the compressed block data, excluding the tree representations.
1291 | */
1292 |
1293 | /* Build the bit length tree for the above two trees, and get the index
1294 | * in bl_order of the last bit length code to send.
1295 | */
1296 | max_blindex = build_bl_tree(state);
1297 |
1298 | /* Determine the best encoding. Compute first the block length in bytes */
1299 | opt_lenb = (state.ts.opt_len + 3 + 7) >> 3;
1300 | static_lenb = (state.ts.static_len + 3 + 7) >> 3;
1301 | state.ts.input_len += stored_len; /* for debugging only */
1302 |
1303 | Trace("\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
1304 | opt_lenb, state.ts.opt_len, static_lenb, state.ts.static_len, stored_len,
1305 | state.ts.last_lit, state.ts.last_dist);
1306 |
1307 | if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
1308 |
1309 | // Originally, zip allowed the file to be transformed from a compressed
1310 | // into a stored file in the case where compression failed, there
1311 | // was only one block, and it was allowed to change. I've removed this
1312 | // possibility since the code's cleaner if no changes are allowed.
1313 | //if (stored_len <= opt_lenb && eof && state.ts.cmpr_bytelen == 0L
1314 | // && state.ts.cmpr_len_bits == 0L && state.seekable)
1315 | //{ // && state.ts.file_method != NULL
1316 | // // Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there:
1317 | // Assert(state,buf!=NULL,"block vanished");
1318 | // copy_block(state,buf, (unsigned)stored_len, 0); // without header
1319 | // state.ts.cmpr_bytelen = stored_len;
1320 | // Assert(state,false,"unimplemented *state.ts.file_method = STORE;");
1321 | // //*state.ts.file_method = STORE;
1322 | //}
1323 | //else
1324 | if (stored_len + 4 <= opt_lenb && buf != (char*)NULL) {
1325 | /* 4: two words for the lengths */
1326 | /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
1327 | * Otherwise we can't have processed more than WSIZE input bytes since
1328 | * the last block flush, because compression would have been
1329 | * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
1330 | * transform a block into a stored block.
1331 | */
1332 | send_bits(state, (STORED_BLOCK << 1) + eof, 3); /* send block type */
1333 | state.ts.cmpr_bytelen += ((state.ts.cmpr_len_bits + 3 + 7) >> 3) + stored_len + 4;
1334 | state.ts.cmpr_len_bits = 0L;
1335 |
1336 | copy_block(state, buf, (unsigned)stored_len, 1); /* with header */
1337 | }
1338 | else if (static_lenb == opt_lenb) {
1339 | send_bits(state, (STATIC_TREES << 1) + eof, 3);
1340 | compress_block(state, (ct_data *)state.ts.static_ltree, (ct_data *)state.ts.static_dtree);
1341 | state.ts.cmpr_len_bits += 3 + state.ts.static_len;
1342 | state.ts.cmpr_bytelen += state.ts.cmpr_len_bits >> 3;
1343 | state.ts.cmpr_len_bits &= 7L;
1344 | }
1345 | else {
1346 | send_bits(state, (DYN_TREES << 1) + eof, 3);
1347 | send_all_trees(state, state.ts.l_desc.max_code + 1, state.ts.d_desc.max_code + 1, max_blindex + 1);
1348 | compress_block(state, (ct_data *)state.ts.dyn_ltree, (ct_data *)state.ts.dyn_dtree);
1349 | state.ts.cmpr_len_bits += 3 + state.ts.opt_len;
1350 | state.ts.cmpr_bytelen += state.ts.cmpr_len_bits >> 3;
1351 | state.ts.cmpr_len_bits &= 7L;
1352 | }
1353 | Assert(state, ((state.ts.cmpr_bytelen << 3) + state.ts.cmpr_len_bits) == state.bs.bits_sent, "bad compressed size");
1354 | init_block(state);
1355 |
1356 | if (eof) {
1357 | // Assert(state,input_len == isize, "bad input size");
1358 | bi_windup(state);
1359 | state.ts.cmpr_len_bits += 7; /* align on byte boundary */
1360 | }
1361 | Trace("\n");
1362 |
1363 | return state.ts.cmpr_bytelen + (state.ts.cmpr_len_bits >> 3);
1364 | }
1365 |
1366 | /* ===========================================================================
1367 | * Save the match info and tally the frequency counts. Return true if
1368 | * the current block must be flushed.
1369 | */
1370 | int ct_tally(TState &state, int dist, int lc)
1371 | {
1372 | state.ts.l_buf[state.ts.last_lit++] = (uch)lc;
1373 | if (dist == 0) {
1374 | /* lc is the unmatched char */
1375 | state.ts.dyn_ltree[lc].fc.freq++;
1376 | }
1377 | else {
1378 | /* Here, lc is the match length - MIN_MATCH */
1379 | dist--; /* dist = match distance - 1 */
1380 | Assert(state, (ush)dist < (ush)MAX_DIST &&
1381 | (ush)lc <= (ush)(MAX_MATCH - MIN_MATCH) &&
1382 | (ush)d_code(dist) < (ush)D_CODES, "ct_tally: bad match");
1383 |
1384 | state.ts.dyn_ltree[state.ts.length_code[lc] + LITERALS + 1].fc.freq++;
1385 | state.ts.dyn_dtree[d_code(dist)].fc.freq++;
1386 |
1387 | state.ts.d_buf[state.ts.last_dist++] = (ush)dist;
1388 | state.ts.flags |= state.ts.flag_bit;
1389 | }
1390 | state.ts.flag_bit <<= 1;
1391 |
1392 | /* Output the flags if they fill a byte: */
1393 | if ((state.ts.last_lit & 7) == 0) {
1394 | state.ts.flag_buf[state.ts.last_flags++] = state.ts.flags;
1395 | state.ts.flags = 0, state.ts.flag_bit = 1;
1396 | }
1397 | /* Try to guess if it is profitable to stop the current block here */
1398 | if (state.level > 2 && (state.ts.last_lit & 0xfff) == 0) {
1399 | /* Compute an upper bound for the compressed length */
1400 | ulg out_length = (ulg)state.ts.last_lit * 8L;
1401 | ulg in_length = (ulg)state.ds.strstart - state.ds.block_start;
1402 | int dcode;
1403 | for (dcode = 0; dcode < D_CODES; dcode++) {
1404 | out_length += (ulg)state.ts.dyn_dtree[dcode].fc.freq*(5L + extra_dbits[dcode]);
1405 | }
1406 | out_length >>= 3;
1407 | Trace("\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
1408 | state.ts.last_lit, state.ts.last_dist, in_length, out_length,
1409 | 100L - out_length * 100L / in_length);
1410 | if (state.ts.last_dist < state.ts.last_lit / 2 && out_length < in_length / 2) return 1;
1411 | }
1412 | return (state.ts.last_lit == LIT_BUFSIZE - 1 || state.ts.last_dist == DIST_BUFSIZE);
1413 | /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K
1414 | * on 16 bit machines and because stored blocks are restricted to
1415 | * 64K-1 bytes.
1416 | */
1417 | }
1418 |
1419 | /* ===========================================================================
1420 | * Send the block data compressed using the given Huffman trees
1421 | */
1422 | void compress_block(TState &state, ct_data *ltree, ct_data *dtree)
1423 | {
1424 | unsigned dist; /* distance of matched string */
1425 | int lc; /* match length or unmatched char (if dist == 0) */
1426 | unsigned lx = 0; /* running index in l_buf */
1427 | unsigned dx = 0; /* running index in d_buf */
1428 | unsigned fx = 0; /* running index in flag_buf */
1429 | uch flag = 0; /* current flags */
1430 | unsigned code; /* the code to send */
1431 | int extra; /* number of extra bits to send */
1432 |
1433 | if (state.ts.last_lit != 0) do {
1434 | if ((lx & 7) == 0) flag = state.ts.flag_buf[fx++];
1435 | lc = state.ts.l_buf[lx++];
1436 | if ((flag & 1) == 0) {
1437 | send_code(state, lc, ltree); /* send a literal byte */
1438 | }
1439 | else {
1440 | /* Here, lc is the match length - MIN_MATCH */
1441 | code = state.ts.length_code[lc];
1442 | send_code(state, code + LITERALS + 1, ltree); /* send the length code */
1443 | extra = extra_lbits[code];
1444 | if (extra != 0) {
1445 | lc -= state.ts.base_length[code];
1446 | send_bits(state, lc, extra); /* send the extra length bits */
1447 | }
1448 | dist = state.ts.d_buf[dx++];
1449 | /* Here, dist is the match distance - 1 */
1450 | code = d_code(dist);
1451 | Assert(state, code < D_CODES, "bad d_code");
1452 |
1453 | send_code(state, code, dtree); /* send the distance code */
1454 | extra = extra_dbits[code];
1455 | if (extra != 0) {
1456 | dist -= state.ts.base_dist[code];
1457 | send_bits(state, dist, extra); /* send the extra distance bits */
1458 | }
1459 | } /* literal or match pair ? */
1460 | flag >>= 1;
1461 | } while (lx < state.ts.last_lit);
1462 |
1463 | send_code(state, END_BLOCK, ltree);
1464 | }
1465 |
1466 | /* ===========================================================================
1467 | * Set the file type to ASCII or BINARY, using a crude approximation:
1468 | * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
1469 | * IN assertion: the fields freq of dyn_ltree are set and the total of all
1470 | * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
1471 | */
1472 | void set_file_type(TState &state)
1473 | {
1474 | int n = 0;
1475 | unsigned ascii_freq = 0;
1476 | unsigned bin_freq = 0;
1477 | while (n < 7) bin_freq += state.ts.dyn_ltree[n++].fc.freq;
1478 | while (n < 128) ascii_freq += state.ts.dyn_ltree[n++].fc.freq;
1479 | while (n < LITERALS) bin_freq += state.ts.dyn_ltree[n++].fc.freq;
1480 | *state.ts.file_type = (ush)(bin_freq >(ascii_freq >> 2) ? BINARY : ASCII);
1481 | }
1482 |
1483 |
1484 | /* ===========================================================================
1485 | * Initialize the bit string routines.
1486 | */
1487 | void bi_init(TState &state, char *tgt_buf, unsigned tgt_size, int flsh_allowed)
1488 | {
1489 | state.bs.out_buf = tgt_buf;
1490 | state.bs.out_size = tgt_size;
1491 | state.bs.out_offset = 0;
1492 | state.bs.flush_flg = flsh_allowed;
1493 |
1494 | state.bs.bi_buf = 0;
1495 | state.bs.bi_valid = 0;
1496 | state.bs.bits_sent = 0L;
1497 | }
1498 |
1499 | /* ===========================================================================
1500 | * Send a value on a given number of bits.
1501 | * IN assertion: length <= 16 and value fits in length bits.
1502 | */
1503 | void send_bits(TState &state, int value, int length)
1504 | {
1505 | Assert(state, length > 0 && length <= 15, "invalid length");
1506 | state.bs.bits_sent += (ulg)length;
1507 | /* If not enough room in bi_buf, use (bi_valid) bits from bi_buf and
1508 | * (Buf_size - bi_valid) bits from value to flush the filled bi_buf,
1509 | * then fill in the rest of (value), leaving (length - (Buf_size-bi_valid))
1510 | * unused bits in bi_buf.
1511 | */
1512 | state.bs.bi_buf |= (value << state.bs.bi_valid);
1513 | state.bs.bi_valid += length;
1514 | if (state.bs.bi_valid > (int)Buf_size) {
1515 | PUTSHORT(state, state.bs.bi_buf);
1516 | state.bs.bi_valid -= Buf_size;
1517 | state.bs.bi_buf = (unsigned)value >> (length - state.bs.bi_valid);
1518 | }
1519 | }
1520 |
1521 | /* ===========================================================================
1522 | * Reverse the first len bits of a code, using straightforward code (a faster
1523 | * method would use a table)
1524 | * IN assertion: 1 <= len <= 15
1525 | */
1526 | unsigned bi_reverse(unsigned code, int len)
1527 | {
1528 | register unsigned res = 0;
1529 | do {
1530 | res |= code & 1;
1531 | code >>= 1, res <<= 1;
1532 | } while (--len > 0);
1533 | return res >> 1;
1534 | }
1535 |
1536 | /* ===========================================================================
1537 | * Write out any remaining bits in an incomplete byte.
1538 | */
1539 | void bi_windup(TState &state)
1540 | {
1541 | if (state.bs.bi_valid > 8) {
1542 | PUTSHORT(state, state.bs.bi_buf);
1543 | }
1544 | else if (state.bs.bi_valid > 0) {
1545 | PUTBYTE(state, state.bs.bi_buf);
1546 | }
1547 | if (state.bs.flush_flg) {
1548 | state.flush_outbuf(state.param, state.bs.out_buf, &state.bs.out_offset);
1549 | }
1550 | state.bs.bi_buf = 0;
1551 | state.bs.bi_valid = 0;
1552 | state.bs.bits_sent = (state.bs.bits_sent + 7) & ~7;
1553 | }
1554 |
1555 | /* ===========================================================================
1556 | * Copy a stored block to the zip file, storing first the length and its
1557 | * one's complement if requested.
1558 | */
1559 | void copy_block(TState &state, char *block, unsigned len, int header)
1560 | {
1561 | bi_windup(state); /* align on byte boundary */
1562 |
1563 | if (header) {
1564 | PUTSHORT(state, (ush)len);
1565 | PUTSHORT(state, (ush)~len);
1566 | state.bs.bits_sent += 2 * 16;
1567 | }
1568 | if (state.bs.flush_flg) {
1569 | state.flush_outbuf(state.param, state.bs.out_buf, &state.bs.out_offset);
1570 | state.bs.out_offset = len;
1571 | state.flush_outbuf(state.param, block, &state.bs.out_offset);
1572 | }
1573 | else if (state.bs.out_offset + len > state.bs.out_size) {
1574 | Assert(state, false, "output buffer too small for in-memory compression");
1575 | }
1576 | else {
1577 | memcpy(state.bs.out_buf + state.bs.out_offset, block, len);
1578 | state.bs.out_offset += len;
1579 | }
1580 | state.bs.bits_sent += (ulg)len << 3;
1581 | }
1582 |
1583 |
1584 |
1585 |
1586 |
1587 |
1588 |
1589 |
1590 | /* ===========================================================================
1591 | * Prototypes for functions.
1592 | */
1593 |
1594 | void fill_window(TState &state);
1595 | ulg deflate_fast(TState &state);
1596 |
1597 | int longest_match(TState &state, IPos cur_match);
1598 |
1599 |
1600 | /* ===========================================================================
1601 | * Update a hash value with the given input byte
1602 | * IN assertion: all calls to to UPDATE_HASH are made with consecutive
1603 | * input characters, so that a running hash key can be computed from the
1604 | * previous key instead of complete recalculation each time.
1605 | */
1606 | #define UPDATE_HASH(h,c) (h = (((h)< 0 if the input file is already read or
1625 | * mmap'ed in the window[] array, 0 otherwise. In the first case,
1626 | * window_size is sufficient to contain the whole input file plus
1627 | * MIN_LOOKAHEAD bytes (to avoid referencing memory beyond the end
1628 | * of window[] when looking for matches towards the end).
1629 | */
1630 | void lm_init(TState &state, int pack_level, ush *flags)
1631 | {
1632 | register unsigned j;
1633 |
1634 | Assert(state, pack_level >= 1 && pack_level <= 8, "bad pack level");
1635 |
1636 | /* Do not slide the window if the whole input is already in memory
1637 | * (window_size > 0)
1638 | */
1639 | state.ds.sliding = 0;
1640 | if (state.ds.window_size == 0L) {
1641 | state.ds.sliding = 1;
1642 | state.ds.window_size = (ulg)2L * WSIZE;
1643 | }
1644 |
1645 | /* Initialize the hash table (avoiding 64K overflow for 16 bit systems).
1646 | * prev[] will be initialized on the fly.
1647 | */
1648 | state.ds.head[HASH_SIZE - 1] = NIL;
1649 | memset((char*)state.ds.head, NIL, (unsigned)(HASH_SIZE - 1)*sizeof(*state.ds.head));
1650 |
1651 | /* Set the default configuration parameters:
1652 | */
1653 | state.ds.max_lazy_match = configuration_table[pack_level].max_lazy;
1654 | state.ds.good_match = configuration_table[pack_level].good_length;
1655 | state.ds.nice_match = configuration_table[pack_level].nice_length;
1656 | state.ds.max_chain_length = configuration_table[pack_level].max_chain;
1657 | if (pack_level <= 2) {
1658 | *flags |= FAST;
1659 | }
1660 | else if (pack_level >= 8) {
1661 | *flags |= SLOW;
1662 | }
1663 | /* ??? reduce max_chain_length for binary files */
1664 |
1665 | state.ds.strstart = 0;
1666 | state.ds.block_start = 0L;
1667 |
1668 | j = WSIZE;
1669 | j <<= 1; // Can read 64K in one step
1670 | state.ds.lookahead = state.readfunc(state, (char*)state.ds.window, j);
1671 |
1672 | if (state.ds.lookahead == 0 || state.ds.lookahead == (unsigned)EOF) {
1673 | state.ds.eofile = 1, state.ds.lookahead = 0;
1674 | return;
1675 | }
1676 | state.ds.eofile = 0;
1677 | /* Make sure that we always have enough lookahead. This is important
1678 | * if input comes from a device such as a tty.
1679 | */
1680 | if (state.ds.lookahead < MIN_LOOKAHEAD) fill_window(state);
1681 |
1682 | state.ds.ins_h = 0;
1683 | for (j = 0; j= 1
1697 | */
1698 | // For 80x86 and 680x0 and ARM, an optimized version is in match.asm or
1699 | // match.S. The code is functionally equivalent, so you can use the C version
1700 | // if desired. Which I do so desire!
1701 | int longest_match(TState &state, IPos cur_match)
1702 | {
1703 | unsigned chain_length = state.ds.max_chain_length; /* max hash chain length */
1704 | register uch *scan = state.ds.window + state.ds.strstart; /* current string */
1705 | register uch *match; /* matched string */
1706 | register int len; /* length of current match */
1707 | int best_len = state.ds.prev_length; /* best match length so far */
1708 | IPos limit = state.ds.strstart > (IPos)MAX_DIST ? state.ds.strstart - (IPos)MAX_DIST : NIL;
1709 | /* Stop when cur_match becomes <= limit. To simplify the code,
1710 | * we prevent matches with the string of window index 0.
1711 | */
1712 |
1713 | // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
1714 | // It is easy to get rid of this optimization if necessary.
1715 | Assert(state, HASH_BITS >= 8 && MAX_MATCH == 258, "Code too clever");
1716 |
1717 |
1718 |
1719 | register uch *strend = state.ds.window + state.ds.strstart + MAX_MATCH;
1720 | register uch scan_end1 = scan[best_len - 1];
1721 | register uch scan_end = scan[best_len];
1722 |
1723 | /* Do not waste too much time if we already have a good match: */
1724 | if (state.ds.prev_length >= state.ds.good_match) {
1725 | chain_length >>= 2;
1726 | }
1727 |
1728 | Assert(state, state.ds.strstart <= state.ds.window_size - MIN_LOOKAHEAD, "insufficient lookahead");
1729 |
1730 | do {
1731 | Assert(state, cur_match < state.ds.strstart, "no future");
1732 | match = state.ds.window + cur_match;
1733 |
1734 | /* Skip to next match if the match length cannot increase
1735 | * or if the match length is less than 2:
1736 | */
1737 | if (match[best_len] != scan_end ||
1738 | match[best_len - 1] != scan_end1 ||
1739 | *match != *scan ||
1740 | *++match != scan[1]) continue;
1741 |
1742 | /* The check at best_len-1 can be removed because it will be made
1743 | * again later. (This heuristic is not always a win.)
1744 | * It is not necessary to compare scan[2] and match[2] since they
1745 | * are always equal when the other bytes match, given that
1746 | * the hash keys are equal and that HASH_BITS >= 8.
1747 | */
1748 | scan += 2, match++;
1749 |
1750 | /* We check for insufficient lookahead only every 8th comparison;
1751 | * the 256th check will be made at strstart+258.
1752 | */
1753 | do {
1754 | } while (*++scan == *++match && *++scan == *++match &&
1755 | *++scan == *++match && *++scan == *++match &&
1756 | *++scan == *++match && *++scan == *++match &&
1757 | *++scan == *++match && *++scan == *++match &&
1758 | scan < strend);
1759 |
1760 | Assert(state, scan <= state.ds.window + (unsigned)(state.ds.window_size - 1), "wild scan");
1761 |
1762 | len = MAX_MATCH - (int)(strend - scan);
1763 | scan = strend - MAX_MATCH;
1764 |
1765 |
1766 | if (len > best_len) {
1767 | state.ds.match_start = cur_match;
1768 | best_len = len;
1769 | if (len >= state.ds.nice_match) break;
1770 | scan_end1 = scan[best_len - 1];
1771 | scan_end = scan[best_len];
1772 | }
1773 | } while ((cur_match = state.ds.prev[cur_match & WMASK]) > limit
1774 | && --chain_length != 0);
1775 |
1776 | return best_len;
1777 | }
1778 |
1779 |
1780 |
1781 | #define check_match(state,start, match, length)
1782 | // or alternatively...
1783 | //void check_match(TState &state,IPos start, IPos match, int length)
1784 | //{ // check that the match is indeed a match
1785 | // if (memcmp((char*)state.ds.window + match,
1786 | // (char*)state.ds.window + start, length) != EQUAL) {
1787 | // fprintf(stderr,
1788 | // " start %d, match %d, length %d\n",
1789 | // start, match, length);
1790 | // error("invalid match");
1791 | // }
1792 | // if (state.verbose > 1) {
1793 | // fprintf(stderr,"\\[%d,%d]", start-match, length);
1794 | // do { fprintf(stdout,"%c",state.ds.window[start++]); } while (--length != 0);
1795 | // }
1796 | //}
1797 |
1798 | /* ===========================================================================
1799 | * Fill the window when the lookahead becomes insufficient.
1800 | * Updates strstart and lookahead, and sets eofile if end of input file.
1801 | *
1802 | * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0
1803 | * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
1804 | * At least one byte has been read, or eofile is set; file reads are
1805 | * performed for at least two bytes (required for the translate_eol option).
1806 | */
1807 | void fill_window(TState &state)
1808 | {
1809 | register unsigned n, m;
1810 | unsigned more; /* Amount of free space at the end of the window. */
1811 |
1812 | do {
1813 | more = (unsigned)(state.ds.window_size - (ulg)state.ds.lookahead - (ulg)state.ds.strstart);
1814 |
1815 | /* If the window is almost full and there is insufficient lookahead,
1816 | * move the upper half to the lower one to make room in the upper half.
1817 | */
1818 | if (more == (unsigned)EOF) {
1819 | /* Very unlikely, but possible on 16 bit machine if strstart == 0
1820 | * and lookahead == 1 (input done one byte at time)
1821 | */
1822 | more--;
1823 |
1824 | /* For MMAP or BIG_MEM, the whole input file is already in memory so
1825 | * we must not perform sliding. We must however call (*read_buf)() in
1826 | * order to compute the crc, update lookahead and possibly set eofile.
1827 | */
1828 | }
1829 | else if (state.ds.strstart >= WSIZE + MAX_DIST && state.ds.sliding) {
1830 |
1831 | /* By the IN assertion, the window is not empty so we can't confuse
1832 | * more == 0 with more == 64K on a 16 bit machine.
1833 | */
1834 | memcpy((char*)state.ds.window, (char*)state.ds.window + WSIZE, (unsigned)WSIZE);
1835 | state.ds.match_start -= WSIZE;
1836 | state.ds.strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */
1837 |
1838 | state.ds.block_start -= (long)WSIZE;
1839 |
1840 | for (n = 0; n < HASH_SIZE; n++) {
1841 | m = state.ds.head[n];
1842 | state.ds.head[n] = (Pos)(m >= WSIZE ? m - WSIZE : NIL);
1843 | }
1844 | for (n = 0; n < WSIZE; n++) {
1845 | m = state.ds.prev[n];
1846 | state.ds.prev[n] = (Pos)(m >= WSIZE ? m - WSIZE : NIL);
1847 | /* If n is not on any hash chain, prev[n] is garbage but
1848 | * its value will never be used.
1849 | */
1850 | }
1851 | more += WSIZE;
1852 | }
1853 | if (state.ds.eofile) return;
1854 |
1855 | /* If there was no sliding:
1856 | * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
1857 | * more == window_size - lookahead - strstart
1858 | * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
1859 | * => more >= window_size - 2*WSIZE + 2
1860 | * In the MMAP or BIG_MEM case (not yet supported in gzip),
1861 | * window_size == input_size + MIN_LOOKAHEAD &&
1862 | * strstart + lookahead <= input_size => more >= MIN_LOOKAHEAD.
1863 | * Otherwise, window_size == 2*WSIZE so more >= 2.
1864 | * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
1865 | */
1866 | Assert(state, more >= 2, "more < 2");
1867 |
1868 | n = state.readfunc(state, (char*)state.ds.window + state.ds.strstart + state.ds.lookahead, more);
1869 |
1870 | if (n == 0 || n == (unsigned)EOF) {
1871 | state.ds.eofile = 1;
1872 | }
1873 | else {
1874 | state.ds.lookahead += n;
1875 | }
1876 | } while (state.ds.lookahead < MIN_LOOKAHEAD && !state.ds.eofile);
1877 | }
1878 |
1879 | /* ===========================================================================
1880 | * Flush the current block, with given end-of-file flag.
1881 | * IN assertion: strstart is set to the end of the current match.
1882 | */
1883 | #define FLUSH_BLOCK(state,eof) \
1884 | flush_block(state,state.ds.block_start >= 0L ? (char*)&state.ds.window[(unsigned)state.ds.block_start] : \
1885 | (char*)NULL, (long)state.ds.strstart - state.ds.block_start, (eof))
1886 |
1887 | /* ===========================================================================
1888 | * Processes a new input file and return its compressed length. This
1889 | * function does not perform lazy evaluation of matches and inserts
1890 | * new strings in the dictionary only for unmatched strings or for short
1891 | * matches. It is used only for the fast compression options.
1892 | */
1893 | ulg deflate_fast(TState &state)
1894 | {
1895 | IPos hash_head = NIL; /* head of the hash chain */
1896 | int flush; /* set if current block must be flushed */
1897 | unsigned match_length = 0; /* length of best match */
1898 |
1899 | state.ds.prev_length = MIN_MATCH - 1;
1900 | while (state.ds.lookahead != 0) {
1901 | /* Insert the string window[strstart .. strstart+2] in the
1902 | * dictionary, and set hash_head to the head of the hash chain:
1903 | */
1904 | if (state.ds.lookahead >= MIN_MATCH)
1905 | INSERT_STRING(state.ds.strstart, hash_head);
1906 |
1907 | /* Find the longest match, discarding those <= prev_length.
1908 | * At this point we have always match_length < MIN_MATCH
1909 | */
1910 | if (hash_head != NIL && state.ds.strstart - hash_head <= MAX_DIST) {
1911 | /* To simplify the code, we prevent matches with the string
1912 | * of window index 0 (in particular we have to avoid a match
1913 | * of the string with itself at the start of the input file).
1914 | */
1915 | /* Do not look for matches beyond the end of the input.
1916 | * This is necessary to make deflate deterministic.
1917 | */
1918 | if ((unsigned)state.ds.nice_match > state.ds.lookahead) state.ds.nice_match = (int)state.ds.lookahead;
1919 | match_length = longest_match(state, hash_head);
1920 | /* longest_match() sets match_start */
1921 | if (match_length > state.ds.lookahead) match_length = state.ds.lookahead;
1922 | }
1923 | if (match_length >= MIN_MATCH) {
1924 | check_match(state, state.ds.strstart, state.ds.match_start, match_length);
1925 |
1926 | flush = ct_tally(state, state.ds.strstart - state.ds.match_start, match_length - MIN_MATCH);
1927 |
1928 | state.ds.lookahead -= match_length;
1929 |
1930 | /* Insert new strings in the hash table only if the match length
1931 | * is not too large. This saves time but degrades compression.
1932 | */
1933 | if (match_length <= state.ds.max_insert_length
1934 | && state.ds.lookahead >= MIN_MATCH) {
1935 | match_length--; /* string at strstart already in hash table */
1936 | do {
1937 | state.ds.strstart++;
1938 | INSERT_STRING(state.ds.strstart, hash_head);
1939 | /* strstart never exceeds WSIZE-MAX_MATCH, so there are
1940 | * always MIN_MATCH bytes ahead.
1941 | */
1942 | } while (--match_length != 0);
1943 | state.ds.strstart++;
1944 | }
1945 | else {
1946 | state.ds.strstart += match_length;
1947 | match_length = 0;
1948 | state.ds.ins_h = state.ds.window[state.ds.strstart];
1949 | UPDATE_HASH(state.ds.ins_h, state.ds.window[state.ds.strstart + 1]);
1950 | Assert(state, MIN_MATCH == 3, "Call UPDATE_HASH() MIN_MATCH-3 more times");
1951 | }
1952 | }
1953 | else {
1954 | /* No match, output a literal byte */
1955 | flush = ct_tally(state, 0, state.ds.window[state.ds.strstart]);
1956 | state.ds.lookahead--;
1957 | state.ds.strstart++;
1958 | }
1959 | if (flush) FLUSH_BLOCK(state, 0), state.ds.block_start = state.ds.strstart;
1960 |
1961 | /* Make sure that we always have enough lookahead, except
1962 | * at the end of the input file. We need MAX_MATCH bytes
1963 | * for the next match, plus MIN_MATCH bytes to insert the
1964 | * string following the next match.
1965 | */
1966 | if (state.ds.lookahead < MIN_LOOKAHEAD) fill_window(state);
1967 | }
1968 | return FLUSH_BLOCK(state, 1); /* eof */
1969 | }
1970 |
1971 | /* ===========================================================================
1972 | * Same as above, but achieves better compression. We use a lazy
1973 | * evaluation for matches: a match is finally adopted only if there is
1974 | * no better match at the next window position.
1975 | */
1976 | ulg deflate(TState &state)
1977 | {
1978 | IPos hash_head = NIL; /* head of hash chain */
1979 | IPos prev_match; /* previous match */
1980 | int flush; /* set if current block must be flushed */
1981 | int match_available = 0; /* set if previous match exists */
1982 | register unsigned match_length = MIN_MATCH - 1; /* length of best match */
1983 |
1984 | if (state.level <= 3) return deflate_fast(state); /* optimized for speed */
1985 |
1986 | /* Process the input block. */
1987 | while (state.ds.lookahead != 0) {
1988 | /* Insert the string window[strstart .. strstart+2] in the
1989 | * dictionary, and set hash_head to the head of the hash chain:
1990 | */
1991 | if (state.ds.lookahead >= MIN_MATCH)
1992 | INSERT_STRING(state.ds.strstart, hash_head);
1993 |
1994 | /* Find the longest match, discarding those <= prev_length.
1995 | */
1996 | state.ds.prev_length = match_length, prev_match = state.ds.match_start;
1997 | match_length = MIN_MATCH - 1;
1998 |
1999 | if (hash_head != NIL && state.ds.prev_length < state.ds.max_lazy_match &&
2000 | state.ds.strstart - hash_head <= MAX_DIST) {
2001 | /* To simplify the code, we prevent matches with the string
2002 | * of window index 0 (in particular we have to avoid a match
2003 | * of the string with itself at the start of the input file).
2004 | */
2005 | /* Do not look for matches beyond the end of the input.
2006 | * This is necessary to make deflate deterministic.
2007 | */
2008 | if ((unsigned)state.ds.nice_match > state.ds.lookahead) state.ds.nice_match = (int)state.ds.lookahead;
2009 | match_length = longest_match(state, hash_head);
2010 | /* longest_match() sets match_start */
2011 | if (match_length > state.ds.lookahead) match_length = state.ds.lookahead;
2012 |
2013 | /* Ignore a length 3 match if it is too distant: */
2014 | if (match_length == MIN_MATCH && state.ds.strstart - state.ds.match_start > TOO_FAR){
2015 | /* If prev_match is also MIN_MATCH, match_start is garbage
2016 | * but we will ignore the current match anyway.
2017 | */
2018 | match_length = MIN_MATCH - 1;
2019 | }
2020 | }
2021 | /* If there was a match at the previous step and the current
2022 | * match is not better, output the previous match:
2023 | */
2024 | if (state.ds.prev_length >= MIN_MATCH && match_length <= state.ds.prev_length) {
2025 | unsigned max_insert = state.ds.strstart + state.ds.lookahead - MIN_MATCH;
2026 | check_match(state, state.ds.strstart - 1, prev_match, state.ds.prev_length);
2027 | flush = ct_tally(state, state.ds.strstart - 1 - prev_match, state.ds.prev_length - MIN_MATCH);
2028 |
2029 | /* Insert in hash table all strings up to the end of the match.
2030 | * strstart-1 and strstart are already inserted.
2031 | */
2032 | state.ds.lookahead -= state.ds.prev_length - 1;
2033 | state.ds.prev_length -= 2;
2034 | do {
2035 | if (++state.ds.strstart <= max_insert) {
2036 | INSERT_STRING(state.ds.strstart, hash_head);
2037 | /* strstart never exceeds WSIZE-MAX_MATCH, so there are
2038 | * always MIN_MATCH bytes ahead.
2039 | */
2040 | }
2041 | } while (--state.ds.prev_length != 0);
2042 | state.ds.strstart++;
2043 | match_available = 0;
2044 | match_length = MIN_MATCH - 1;
2045 |
2046 | if (flush) FLUSH_BLOCK(state, 0), state.ds.block_start = state.ds.strstart;
2047 |
2048 | }
2049 | else if (match_available) {
2050 | /* If there was no match at the previous position, output a
2051 | * single literal. If there was a match but the current match
2052 | * is longer, truncate the previous match to a single literal.
2053 | */
2054 | if (ct_tally(state, 0, state.ds.window[state.ds.strstart - 1])) {
2055 | FLUSH_BLOCK(state, 0), state.ds.block_start = state.ds.strstart;
2056 | }
2057 | state.ds.strstart++;
2058 | state.ds.lookahead--;
2059 | }
2060 | else {
2061 | /* There is no previous match to compare with, wait for
2062 | * the next step to decide.
2063 | */
2064 | match_available = 1;
2065 | state.ds.strstart++;
2066 | state.ds.lookahead--;
2067 | }
2068 | // Assert(state,strstart <= isize && lookahead <= isize, "a bit too far");
2069 |
2070 | /* Make sure that we always have enough lookahead, except
2071 | * at the end of the input file. We need MAX_MATCH bytes
2072 | * for the next match, plus MIN_MATCH bytes to insert the
2073 | * string following the next match.
2074 | */
2075 | if (state.ds.lookahead < MIN_LOOKAHEAD) fill_window(state);
2076 | }
2077 | if (match_available) ct_tally(state, 0, state.ds.window[state.ds.strstart - 1]);
2078 |
2079 | return FLUSH_BLOCK(state, 1); /* eof */
2080 | }
2081 |
2082 |
2083 |
2084 |
2085 |
2086 |
2087 |
2088 |
2089 |
2090 |
2091 |
2092 |
2093 | int putlocal(struct zlist *z, WRITEFUNC wfunc, void *param)
2094 | { // Write a local header described by *z to file *f. Return a ZE_ error code.
2095 | PUTLG(LOCSIG, f);
2096 | PUTSH(z->ver, f);
2097 | PUTSH(z->lflg, f);
2098 | PUTSH(z->how, f);
2099 | PUTLG(z->tim, f);
2100 | PUTLG(z->crc, f);
2101 | PUTLG(z->siz, f);
2102 | PUTLG(z->len, f);
2103 | PUTSH(z->nam, f);
2104 | PUTSH(z->ext, f);
2105 | size_t res = (size_t)wfunc(param, z->iname, (unsigned int)z->nam);
2106 | if (res != z->nam) return ZE_TEMP;
2107 | if (z->ext)
2108 | {
2109 | res = (size_t)wfunc(param, z->extra, (unsigned int)z->ext);
2110 | if (res != z->ext) return ZE_TEMP;
2111 | }
2112 | return ZE_OK;
2113 | }
2114 |
2115 | int putextended(struct zlist *z, WRITEFUNC wfunc, void *param)
2116 | { // Write an extended local header described by *z to file *f. Returns a ZE_ code
2117 | PUTLG(EXTLOCSIG, f);
2118 | PUTLG(z->crc, f);
2119 | PUTLG(z->siz, f);
2120 | PUTLG(z->len, f);
2121 | return ZE_OK;
2122 | }
2123 |
2124 | int putcentral(struct zlist *z, WRITEFUNC wfunc, void *param)
2125 | { // Write a central header entry of *z to file *f. Returns a ZE_ code.
2126 | PUTLG(CENSIG, f);
2127 | PUTSH(z->vem, f);
2128 | PUTSH(z->ver, f);
2129 | PUTSH(z->flg, f);
2130 | PUTSH(z->how, f);
2131 | PUTLG(z->tim, f);
2132 | PUTLG(z->crc, f);
2133 | PUTLG(z->siz, f);
2134 | PUTLG(z->len, f);
2135 | PUTSH(z->nam, f);
2136 | PUTSH(z->cext, f);
2137 | PUTSH(z->com, f);
2138 | PUTSH(z->dsk, f);
2139 | PUTSH(z->att, f);
2140 | PUTLG(z->atx, f);
2141 | PUTLG(z->off, f);
2142 | if ((size_t)wfunc(param, z->iname, (unsigned int)z->nam) != z->nam ||
2143 | (z->cext && (size_t)wfunc(param, z->cextra, (unsigned int)z->cext) != z->cext) ||
2144 | (z->com && (size_t)wfunc(param, z->comment, (unsigned int)z->com) != z->com))
2145 | return ZE_TEMP;
2146 | return ZE_OK;
2147 | }
2148 |
2149 |
2150 | int putend(int n, ulg s, ulg c, extent m, char *z, WRITEFUNC wfunc, void *param)
2151 | { // write the end of the central-directory-data to file *f.
2152 | PUTLG(ENDSIG, f);
2153 | PUTSH(0, f);
2154 | PUTSH(0, f);
2155 | PUTSH(n, f);
2156 | PUTSH(n, f);
2157 | PUTLG(s, f);
2158 | PUTLG(c, f);
2159 | PUTSH(m, f);
2160 | // Write the comment, if any
2161 | if (m && wfunc(param, z, (unsigned int)m) != m) return ZE_TEMP;
2162 | return ZE_OK;
2163 | }
2164 |
2165 |
2166 |
2167 |
2168 |
2169 |
2170 | const ulg crc_table[256] = {
2171 | 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
2172 | 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
2173 | 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
2174 | 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
2175 | 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
2176 | 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
2177 | 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
2178 | 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
2179 | 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
2180 | 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
2181 | 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
2182 | 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
2183 | 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
2184 | 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
2185 | 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
2186 | 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
2187 | 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
2188 | 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
2189 | 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
2190 | 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
2191 | 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
2192 | 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
2193 | 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
2194 | 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
2195 | 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
2196 | 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
2197 | 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
2198 | 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
2199 | 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
2200 | 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
2201 | 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
2202 | 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
2203 | 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
2204 | 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
2205 | 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
2206 | 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
2207 | 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
2208 | 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
2209 | 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
2210 | 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
2211 | 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
2212 | 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
2213 | 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
2214 | 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
2215 | 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
2216 | 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
2217 | 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
2218 | 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
2219 | 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
2220 | 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
2221 | 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
2222 | 0x2d02ef8dL
2223 | };
2224 |
2225 | #define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
2226 | #define DO1(buf) crc = CRC32(crc, *buf++)
2227 | #define DO2(buf) DO1(buf); DO1(buf)
2228 | #define DO4(buf) DO2(buf); DO2(buf)
2229 | #define DO8(buf) DO4(buf); DO4(buf)
2230 |
2231 | ulg crc32(ulg crc, const uch *buf, extent len)
2232 | {
2233 | if (buf == NULL) return 0L;
2234 | crc = crc ^ 0xffffffffL;
2235 | while (len >= 8) { DO8(buf); len -= 8; }
2236 | if (len) do { DO1(buf); } while (--len);
2237 | return crc ^ 0xffffffffL; // (instead of ~c for 64-bit machines)
2238 | }
2239 |
2240 |
2241 | void update_keys(unsigned long *keys, char c)
2242 | {
2243 | keys[0] = CRC32(keys[0], c);
2244 | keys[1] += keys[0] & 0xFF;
2245 | keys[1] = keys[1] * 134775813L + 1;
2246 | keys[2] = CRC32(keys[2], keys[1] >> 24);
2247 | }
2248 | char decrypt_byte(unsigned long *keys)
2249 | {
2250 | unsigned temp = ((unsigned)keys[2] & 0xffff) | 2;
2251 | return (char)(((temp * (temp ^ 1)) >> 8) & 0xff);
2252 | }
2253 | char zencode(unsigned long *keys, char c)
2254 | {
2255 | int t = decrypt_byte(keys);
2256 | update_keys(keys, c);
2257 | return (char)(t^c);
2258 | }
2259 |
2260 |
2261 |
2262 |
2263 |
2264 |
2265 |
2266 | int lustricmp(const TCHAR *sa, const TCHAR *sb)
2267 | {
2268 | for (const TCHAR *ca = sa, *cb = sb;; ca++, cb++)
2269 | {
2270 | int ia = tolower(*ca), ib = tolower(*cb);
2271 | if (ia == ib && ia == 0) return 0;
2272 | if (ia == ib) continue;
2273 | if (iaib) return 1;
2275 | }
2276 | }
2277 |
2278 |
2279 | bool HasZipSuffix(const TCHAR *fn)
2280 | {
2281 | const TCHAR *ext = fn + _tcslen(fn);
2282 | while (ext>fn && *ext != '.') ext--;
2283 | if (ext == fn && *ext != '.') return false;
2284 | if (lustricmp(ext, _T(".Z")) == 0) return true;
2285 | if (lustricmp(ext, _T(".zip")) == 0) return true;
2286 | if (lustricmp(ext, _T(".zoo")) == 0) return true;
2287 | if (lustricmp(ext, _T(".arc")) == 0) return true;
2288 | if (lustricmp(ext, _T(".lzh")) == 0) return true;
2289 | if (lustricmp(ext, _T(".arj")) == 0) return true;
2290 | if (lustricmp(ext, _T(".gz")) == 0) return true;
2291 | if (lustricmp(ext, _T(".tgz")) == 0) return true;
2292 | return false;
2293 | }
2294 |
2295 |
2296 |
2297 |
2298 |
2299 |
2300 |
2301 |
2302 | class TZip
2303 | {
2304 | public:
2305 | TZip(const char *pwd) : hfout(0), mustclosehfout(false), hmapout(0), zfis(0), obuf(0), hfin(0), writ(0), oerr(false), hasputcen(false), ooffset(0), encwriting(false), encbuf(0), password(0), state(0) { if (pwd != 0 && *pwd != 0) { password = new char[strlen(pwd) + 1]; strcpy(password, pwd); } }
2306 | ~TZip() { if (state != 0) delete state; state = 0; if (encbuf != 0) delete[] encbuf; encbuf = 0; if (password != 0) delete[] password; password = 0; }
2307 |
2308 | // These variables say about the file we're writing into
2309 | // We can write to pipe, file-by-handle, file-by-name, memory-to-memmapfile
2310 | char *password; // keep a copy of the password
2311 | HANDLE hfout; // if valid, we'll write here (for files or pipes)
2312 | bool mustclosehfout; // if true, we are responsible for closing hfout
2313 | HANDLE hmapout; // otherwise, we'll write here (for memmap)
2314 | unsigned ooffset; // for hfout, this is where the pointer was initially
2315 | ZRESULT oerr; // did a write operation give rise to an error?
2316 | unsigned writ; // how far have we written. This is maintained by Add, not write(), to avoid confusion over seeks
2317 | bool ocanseek; // can we seek?
2318 | char *obuf; // this is where we've locked mmap to view.
2319 | unsigned int opos; // current pos in the mmap
2320 | unsigned int mapsize; // the size of the map we created
2321 | bool hasputcen; // have we yet placed the central directory?
2322 | bool encwriting; // if true, then we'll encrypt stuff using 'keys' before we write it to disk
2323 | unsigned long keys[3]; // keys are initialised inside Add()
2324 | char *encbuf; // if encrypting, then this is a temporary workspace for encrypting the data
2325 | unsigned int encbufsize; // (to be used and resized inside write(), and deleted in the destructor)
2326 | //
2327 | TZipFileInfo *zfis; // each file gets added onto this list, for writing the table at the end
2328 | TState *state; // we use just one state object per zip, because it's big (500k)
2329 |
2330 | ZRESULT Create(void *z, unsigned int len, DWORD flags);
2331 | static unsigned sflush(void *param, const char *buf, unsigned *size);
2332 | static unsigned swrite(void *param, const char *buf, unsigned size);
2333 | unsigned int write(const char *buf, unsigned int size);
2334 | bool oseek(unsigned int pos);
2335 | ZRESULT GetMemory(void **pbuf, unsigned long *plen);
2336 | ZRESULT Close();
2337 |
2338 | // some variables to do with the file currently being read:
2339 | // I haven't done it object-orientedly here, just put them all
2340 | // together, since OO didn't seem to make the design any clearer.
2341 | ulg attr; iztimes times; ulg timestamp; // all open_* methods set these
2342 | bool iseekable; long isize, ired; // size is not set until close() on pips
2343 | ulg crc; // crc is not set until close(). iwrit is cumulative
2344 | HANDLE hfin; bool selfclosehf; // for input files and pipes
2345 | const char *bufin; unsigned int lenin, posin; // for memory
2346 | // and a variable for what we've done with the input: (i.e. compressed it!)
2347 | ulg csize; // compressed size, set by the compression routines
2348 | // and this is used by some of the compression routines
2349 | char buf[16384];
2350 |
2351 |
2352 | ZRESULT open_file(const TCHAR *fn);
2353 | ZRESULT open_handle(HANDLE hf, unsigned int len);
2354 | ZRESULT open_mem(void *src, unsigned int len);
2355 | ZRESULT open_dir();
2356 | static unsigned sread(TState &s, char *buf, unsigned size);
2357 | unsigned read(char *buf, unsigned size);
2358 | ZRESULT iclose();
2359 |
2360 | ZRESULT ideflate(TZipFileInfo *zfi);
2361 | ZRESULT istore();
2362 |
2363 | ZRESULT Add(const TCHAR *odstzn, void *src, unsigned int len, DWORD flags);
2364 | ZRESULT AddCentral();
2365 |
2366 | };
2367 |
2368 |
2369 |
2370 | ZRESULT TZip::Create(void *z, unsigned int len, DWORD flags)
2371 | {
2372 | if (hfout != 0 || hmapout != 0 || obuf != 0 || writ != 0 || oerr != ZR_OK || hasputcen) return ZR_NOTINITED;
2373 | //
2374 | if (flags == ZIP_HANDLE)
2375 | {
2376 | HANDLE hf = (HANDLE)z;
2377 | hfout = hf; mustclosehfout = false;
2378 | #ifdef DuplicateHandle
2379 | BOOL res = DuplicateHandle(GetCurrentProcess(), hf, GetCurrentProcess(), &hfout, 0, FALSE, DUPLICATE_SAME_ACCESS);
2380 | if (res) mustclosehandle = true;
2381 | #endif
2382 | // now we have hfout. Either we duplicated the handle and we close it ourselves
2383 | // (while the caller closes h themselves), or we couldn't duplicate it.
2384 | DWORD res = GetFilePosZ(hfout);
2385 | ocanseek = (res != 0xFFFFFFFF);
2386 | ooffset = ocanseek ? res : 0;
2387 | return ZR_OK;
2388 | }
2389 | else if (flags == ZIP_FILENAME)
2390 | {
2391 | const TCHAR *fn = (const TCHAR*)z;
2392 |
2393 | hfout = CreateFile(fn, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2394 | if (hfout == INVALID_HANDLE_VALUE) { hfout = 0; return ZR_NOFILE; }
2395 | ocanseek = true;
2396 | ooffset = 0;
2397 | mustclosehfout = true;
2398 | return ZR_OK;
2399 | }
2400 | else if (flags == ZIP_MEMORY)
2401 | {
2402 | unsigned int size = len;
2403 | if (size == 0) return ZR_MEMSIZE;
2404 |
2405 | if (z != 0) obuf = (char*)z;
2406 | else
2407 | {
2408 | hmapout = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, NULL);
2409 | if (hmapout == NULL) return ZR_NOALLOC;
2410 | obuf = (char*)MapViewOfFile(hmapout, FILE_MAP_ALL_ACCESS, 0, 0, size);
2411 | if (obuf == 0) { CloseHandle(hmapout); hmapout = 0; return ZR_NOALLOC; }
2412 | }
2413 | ocanseek = true;
2414 | opos = 0; mapsize = size;
2415 | return ZR_OK;
2416 | }
2417 | else return ZR_ARGS;
2418 | }
2419 |
2420 | unsigned TZip::sflush(void *param, const char *buf, unsigned *size)
2421 | { // static
2422 | if (*size == 0) return 0;
2423 | TZip *zip = (TZip*)param;
2424 | unsigned int writ = zip->write(buf, *size);
2425 | if (writ != 0) *size = 0;
2426 | return writ;
2427 | }
2428 | unsigned TZip::swrite(void *param, const char *buf, unsigned size)
2429 | { // static
2430 | if (size == 0) return 0;
2431 | TZip *zip = (TZip*)param; return zip->write(buf, size);
2432 | }
2433 | unsigned int TZip::write(const char *buf, unsigned int size)
2434 | {
2435 | const char *srcbuf = buf;
2436 | if (encwriting)
2437 | {
2438 | if (encbuf != 0 && encbufsize= mapsize) { oerr = ZR_MEMSIZE; return 0; }
2447 | memcpy(obuf + opos, srcbuf, size);
2448 | opos += size;
2449 | return size;
2450 | }
2451 | else if (hfout != 0)
2452 | {
2453 |
2454 | DWORD writ; WriteFile(hfout, srcbuf, size, &writ, NULL);
2455 | return writ;
2456 | }
2457 | oerr = ZR_NOTINITED; return 0;
2458 | }
2459 |
2460 | bool TZip::oseek(unsigned int pos)
2461 | {
2462 | if (!ocanseek) { oerr = ZR_SEEK; return false; }
2463 | if (obuf != 0)
2464 | {
2465 | if (pos >= mapsize) { oerr = ZR_MEMSIZE; return false; }
2466 | opos = pos;
2467 | return true;
2468 | }
2469 | else if (hfout != 0)
2470 | {
2471 |
2472 | SetFilePointer(hfout, pos + ooffset, NULL, FILE_BEGIN);
2473 | return true;
2474 | }
2475 | oerr = ZR_NOTINITED; return 0;
2476 | }
2477 |
2478 | ZRESULT TZip::GetMemory(void **pbuf, unsigned long *plen)
2479 | { // When the user calls GetMemory, they're presumably at the end
2480 | // of all their adding. In any case, we have to add the central
2481 | // directory now, otherwise the memory we tell them won't be complete.
2482 | if (!hasputcen) AddCentral(); hasputcen = true;
2483 | if (pbuf != NULL) *pbuf = (void*)obuf;
2484 | if (plen != NULL) *plen = writ;
2485 | if (obuf == NULL) return ZR_NOTMMAP;
2486 | return ZR_OK;
2487 | }
2488 |
2489 | ZRESULT TZip::Close()
2490 | { // if the directory hadn't already been added through a call to GetMemory,
2491 | // then we do it now
2492 | ZRESULT res = ZR_OK; if (!hasputcen) res = AddCentral(); hasputcen = true;
2493 |
2494 | if (obuf != 0 && hmapout != 0) UnmapViewOfFile(obuf); obuf = 0;
2495 | if (hmapout != 0) CloseHandle(hmapout); hmapout = 0;
2496 | if (hfout != 0 && mustclosehfout) CloseHandle(hfout); hfout = 0; mustclosehfout = false;
2497 | return res;
2498 | }
2499 |
2500 |
2501 |
2502 |
2503 | ZRESULT TZip::open_file(const TCHAR *fn)
2504 | {
2505 | hfin = 0; bufin = 0; selfclosehf = false; crc = CRCVAL_INITIAL; isize = 0; csize = 0; ired = 0;
2506 | if (fn == 0) return ZR_ARGS;
2507 |
2508 | HANDLE hf = CreateFile(fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
2509 | if (hf == INVALID_HANDLE_VALUE) return ZR_NOFILE;
2510 | ZRESULT res = open_handle(hf, 0);
2511 | if (res != ZR_OK) { CloseHandle(hf); return res; }
2512 | selfclosehf = true;
2513 | return ZR_OK;
2514 | }
2515 | ZRESULT TZip::open_handle(HANDLE hf, unsigned int len)
2516 | {
2517 | hfin = 0; bufin = 0; selfclosehf = false; crc = CRCVAL_INITIAL; isize = 0; csize = 0; ired = 0;
2518 | if (hf == 0 || hf == INVALID_HANDLE_VALUE) return ZR_ARGS;
2519 | bool canseek;
2520 |
2521 | DWORD res = SetFilePointer(hfout, 0, 0, FILE_CURRENT);
2522 | canseek = (res != 0xFFFFFFFF);
2523 | if (canseek)
2524 | {
2525 | ZRESULT res = GetFileInfo(hf, &attr, &isize, ×, ×tamp);
2526 | if (res != ZR_OK) return res;
2527 |
2528 | SetFilePointer(hf, 0, NULL, FILE_BEGIN); // because GetFileInfo will have screwed it up
2529 | iseekable = true; hfin = hf;
2530 | return ZR_OK;
2531 | }
2532 | else
2533 | {
2534 | attr = 0x80000000; // just a normal file
2535 | isize = -1; // can't know size until at the end
2536 | if (len != 0) isize = len; // unless we were told explicitly!
2537 | iseekable = false;
2538 | WORD dosdate, dostime; GetNow(×.atime, &dosdate, &dostime);
2539 | times.mtime = times.atime;
2540 | times.ctime = times.atime;
2541 | timestamp = (WORD)dostime | (((DWORD)dosdate) << 16);
2542 | hfin = hf;
2543 | return ZR_OK;
2544 | }
2545 | }
2546 | ZRESULT TZip::open_mem(void *src, unsigned int len)
2547 | {
2548 | hfin = 0; bufin = (const char*)src; selfclosehf = false; crc = CRCVAL_INITIAL; ired = 0; csize = 0; ired = 0;
2549 | lenin = len; posin = 0;
2550 | if (src == 0 || len == 0) return ZR_ARGS;
2551 | attr = 0x80000000; // just a normal file
2552 | isize = len;
2553 | iseekable = true;
2554 | WORD dosdate, dostime; GetNow(×.atime, &dosdate, &dostime);
2555 | times.mtime = times.atime;
2556 | times.ctime = times.atime;
2557 | timestamp = (WORD)dostime | (((DWORD)dosdate) << 16);
2558 | return ZR_OK;
2559 | }
2560 | ZRESULT TZip::open_dir()
2561 | {
2562 | hfin = 0; bufin = 0; selfclosehf = false; crc = CRCVAL_INITIAL; isize = 0; csize = 0; ired = 0;
2563 | attr = 0x41C00010; // a readable writable directory, and again directory
2564 | isize = 0;
2565 | iseekable = false;
2566 | WORD dosdate, dostime; GetNow(×.atime, &dosdate, &dostime);
2567 | times.mtime = times.atime;
2568 | times.ctime = times.atime;
2569 | timestamp = (WORD)dostime | (((DWORD)dosdate) << 16);
2570 | return ZR_OK;
2571 | }
2572 |
2573 | unsigned TZip::sread(TState &s, char *buf, unsigned size)
2574 | { // static
2575 | TZip *zip = (TZip*)s.param;
2576 | return zip->read(buf, size);
2577 | }
2578 |
2579 | unsigned TZip::read(char *buf, unsigned size)
2580 | {
2581 | if (bufin != 0)
2582 | {
2583 | if (posin >= lenin) return 0; // end of input
2584 | ulg red = lenin - posin;
2585 | if (red>size) red = size;
2586 | memcpy(buf, bufin + posin, red);
2587 | posin += red;
2588 | ired += red;
2589 | crc = crc32(crc, (uch*)buf, red);
2590 | return red;
2591 | }
2592 | else if (hfin != 0)
2593 | {
2594 | DWORD red;
2595 |
2596 | BOOL ok = ReadFile(hfin, buf, size, &red, NULL);
2597 | if (!ok) return 0;
2598 | ired += red;
2599 | crc = crc32(crc, (uch*)buf, red);
2600 | return red;
2601 | }
2602 | else { oerr = ZR_NOTINITED; return 0; }
2603 | }
2604 |
2605 | ZRESULT TZip::iclose()
2606 | {
2607 |
2608 | if (selfclosehf && hfin != 0) CloseHandle(hfin); hfin = 0;
2609 | bool mismatch = (isize != -1 && isize != ired);
2610 | isize = ired; // and crc has been being updated anyway
2611 | if (mismatch) return ZR_MISSIZE;
2612 | else return ZR_OK;
2613 | }
2614 |
2615 |
2616 |
2617 | ZRESULT TZip::ideflate(TZipFileInfo *zfi)
2618 | {
2619 | if (state == 0) state = new TState();
2620 | // It's a very big object! 500k! We allocate it on the heap, because PocketPC's
2621 | // stack breaks if we try to put it all on the stack. It will be deleted lazily
2622 | state->err = 0;
2623 | state->readfunc = sread; state->flush_outbuf = sflush;
2624 | state->param = this; state->level = 8; state->seekable = iseekable; state->err = NULL;
2625 | // the following line will make ct_init realise it has to perform the init
2626 | state->ts.static_dtree[0].dl.len = 0;
2627 | // Thanks to Alvin77 for this crucial fix:
2628 | state->ds.window_size = 0;
2629 | // I think that covers everything that needs to be initted.
2630 | //
2631 | bi_init(*state, buf, sizeof(buf), 1); // it used to be just 1024-size, not 16384 as here
2632 | ct_init(*state, &zfi->att);
2633 | lm_init(*state, state->level, &zfi->flg);
2634 | ulg sz = deflate(*state);
2635 | csize = sz;
2636 | ZRESULT r = ZR_OK; if (state->err != NULL) r = ZR_FLATE;
2637 | return r;
2638 | }
2639 |
2640 | ZRESULT TZip::istore()
2641 | {
2642 | ulg size = 0;
2643 | for (;;)
2644 | {
2645 | unsigned int cin = read(buf, 16384); if (cin <= 0 || cin == (unsigned int)EOF) break;
2646 | unsigned int cout = write(buf, cin); if (cout != cin) return ZR_MISSIZE;
2647 | size += cin;
2648 | }
2649 | csize = size;
2650 | return ZR_OK;
2651 | }
2652 |
2653 |
2654 |
2655 |
2656 |
2657 | bool has_seeded = false;
2658 | ZRESULT TZip::Add(const TCHAR *odstzn, void *src, unsigned int len, DWORD flags)
2659 | {
2660 | if (oerr) return ZR_FAILED;
2661 | if (hasputcen) return ZR_ENDED;
2662 |
2663 | // if we use password encryption, then every isize and csize is 12 bytes bigger
2664 | int passex = 0; if (password != 0 && flags != ZIP_FOLDER) passex = 12;
2665 |
2666 | // zip has its own notion of what its names should look like: i.e. dir/file.stuff
2667 | TCHAR dstzn[MAX_PATH]; _tcsncpy(dstzn, odstzn, MAX_PATH); dstzn[MAX_PATH - 1] = 0;
2668 | if (*dstzn == 0) return ZR_ARGS;
2669 | TCHAR *d = dstzn; while (*d != 0) { if (*d == '\\') *d = '/'; d++; }
2670 | bool isdir = (flags == ZIP_FOLDER);
2671 | bool needs_trailing_slash = (isdir && dstzn[_tcslen(dstzn) - 1] != '/');
2672 | int method = DEFLATE; if (isdir || HasZipSuffix(dstzn)) method = STORE;
2673 |
2674 | // now open whatever was our input source:
2675 | ZRESULT openres;
2676 | if (flags == ZIP_FILENAME) openres = open_file((const TCHAR*)src);
2677 | else if (flags == ZIP_HANDLE) openres = open_handle((HANDLE)src, len);
2678 | else if (flags == ZIP_MEMORY) openres = open_mem(src, len);
2679 | else if (flags == ZIP_FOLDER) openres = open_dir();
2680 | else return ZR_ARGS;
2681 | if (openres != ZR_OK) return openres;
2682 |
2683 | // A zip "entry" consists of a local header (which includes the file name),
2684 | // then the compressed data, and possibly an extended local header.
2685 |
2686 | // Initialize the local header
2687 | TZipFileInfo zfi; zfi.nxt = NULL;
2688 |
2689 | strcpy(zfi.name, "");
2690 |
2691 | #ifdef UNICODE
2692 | WideCharToMultiByte(ZIP_UNICODE, 0, dstzn, -1, zfi.iname, MAX_PATH, 0, 0);
2693 | #else
2694 | strncpy(zfi.iname, dstzn, MAX_PATH); zfi.iname[MAX_PATH - 1] = 0;
2695 | #endif
2696 |
2697 |
2698 | zfi.nam = strlen(zfi.iname);
2699 | if (needs_trailing_slash) { strcat(zfi.iname, "/"); zfi.nam++; }
2700 | strcpy(zfi.zname, "");
2701 | zfi.extra = NULL; zfi.ext = 0; // extra header to go after this compressed data, and its length
2702 | zfi.cextra = NULL; zfi.cext = 0; // extra header to go in the central end-of-zip directory, and its length
2703 | zfi.comment = NULL; zfi.com = 0; // comment, and its length
2704 | zfi.mark = 1;
2705 | zfi.dosflag = 0;
2706 | zfi.att = (ush)BINARY;
2707 | zfi.vem = (ush)0xB17; // 0xB00 is win32 os-code. 0x17 is 23 in decimal: zip 2.3
2708 | zfi.ver = (ush)20; // Needs PKUNZIP 2.0 to unzip it
2709 | zfi.tim = timestamp;
2710 | // Even though we write the header now, it will have to be rewritten, since we don't know compressed size or crc.
2711 | zfi.crc = 0; // to be updated later
2712 | zfi.flg = 8; // 8 means 'there is an extra header'. Assume for the moment that we need it.
2713 | if (password != 0 && !isdir) zfi.flg = 9; // and 1 means 'password-encrypted'
2714 | zfi.lflg = zfi.flg; // to be updated later
2715 | zfi.how = (ush)method; // to be updated later
2716 | zfi.siz = (ulg)(method == STORE && isize >= 0 ? isize + passex : 0); // to be updated later
2717 | zfi.len = (ulg)(isize); // to be updated later
2718 | zfi.dsk = 0;
2719 | zfi.atx = attr;
2720 | zfi.off = writ + ooffset; // offset within file of the start of this local record
2721 | // stuff the 'times' structure into zfi.extra
2722 |
2723 | // nb. apparently there's a problem with PocketPC CE(zip)->CE(unzip) fails. And removing the following block fixes it up.
2724 | char xloc[EB_L_UT_SIZE]; zfi.extra = xloc; zfi.ext = EB_L_UT_SIZE;
2725 | char xcen[EB_C_UT_SIZE]; zfi.cextra = xcen; zfi.cext = EB_C_UT_SIZE;
2726 | xloc[0] = 'U';
2727 | xloc[1] = 'T';
2728 | xloc[2] = EB_UT_LEN(3); // length of data part of e.f.
2729 | xloc[3] = 0;
2730 | xloc[4] = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME;
2731 | xloc[5] = (char)(times.mtime);
2732 | xloc[6] = (char)(times.mtime >> 8);
2733 | xloc[7] = (char)(times.mtime >> 16);
2734 | xloc[8] = (char)(times.mtime >> 24);
2735 | xloc[9] = (char)(times.atime);
2736 | xloc[10] = (char)(times.atime >> 8);
2737 | xloc[11] = (char)(times.atime >> 16);
2738 | xloc[12] = (char)(times.atime >> 24);
2739 | xloc[13] = (char)(times.ctime);
2740 | xloc[14] = (char)(times.ctime >> 8);
2741 | xloc[15] = (char)(times.ctime >> 16);
2742 | xloc[16] = (char)(times.ctime >> 24);
2743 | memcpy(zfi.cextra, zfi.extra, EB_C_UT_SIZE);
2744 | zfi.cextra[EB_LEN] = EB_UT_LEN(1);
2745 |
2746 |
2747 | // (1) Start by writing the local header:
2748 | int r = putlocal(&zfi, swrite, this);
2749 | if (r != ZE_OK) { iclose(); return ZR_WRITE; }
2750 | writ += 4 + LOCHEAD + (unsigned int)zfi.nam + (unsigned int)zfi.ext;
2751 | if (oerr != ZR_OK) { iclose(); return oerr; }
2752 |
2753 | // (1.5) if necessary, write the encryption header
2754 | keys[0] = 305419896L;
2755 | keys[1] = 591751049L;
2756 | keys[2] = 878082192L;
2757 | for (const char *cp = password; cp != 0 && *cp != 0; cp++) update_keys(keys, *cp);
2758 | // generate some random bytes
2759 |
2760 | if (!has_seeded) srand(GetTickCount() ^ (unsigned long)GetDesktopWindow());
2761 | char encbuf[12]; for (int i = 0; i<12; i++) encbuf[i] = (char)((rand() >> 7) & 0xff);
2762 | encbuf[11] = (char)((zfi.tim >> 8) & 0xff);
2763 | for (int ei = 0; ei<12; ei++) encbuf[ei] = zencode(keys, encbuf[ei]);
2764 | if (password != 0 && !isdir) { swrite(this, encbuf, 12); writ += 12; }
2765 |
2766 | //(2) Write deflated/stored file to zip file
2767 | ZRESULT writeres = ZR_OK;
2768 | encwriting = (password != 0 && !isdir); // an object member variable to say whether we write to disk encrypted
2769 | if (!isdir && method == DEFLATE) writeres = ideflate(&zfi);
2770 | else if (!isdir && method == STORE) writeres = istore();
2771 | else if (isdir) csize = 0;
2772 | encwriting = false;
2773 | iclose();
2774 | writ += csize;
2775 | if (oerr != ZR_OK) return oerr;
2776 | if (writeres != ZR_OK) return ZR_WRITE;
2777 |
2778 | // (3) Either rewrite the local header with correct information...
2779 | bool first_header_has_size_right = (zfi.siz == csize + passex);
2780 | zfi.crc = crc;
2781 | zfi.siz = csize + passex;
2782 | zfi.len = isize;
2783 | if (ocanseek && (password == 0 || isdir))
2784 | {
2785 | zfi.how = (ush)method;
2786 | if ((zfi.flg & 1) == 0) zfi.flg &= ~8; // clear the extended local header flag
2787 | zfi.lflg = zfi.flg;
2788 | // rewrite the local header:
2789 | if (!oseek(zfi.off - ooffset)) return ZR_SEEK;
2790 | if ((r = putlocal(&zfi, swrite, this)) != ZE_OK) return ZR_WRITE;
2791 | if (!oseek(writ)) return ZR_SEEK;
2792 | }
2793 | else
2794 | { // (4) ... or put an updated header at the end
2795 | if (zfi.how != (ush)method) return ZR_NOCHANGE;
2796 | if (method == STORE && !first_header_has_size_right) return ZR_NOCHANGE;
2797 | if ((r = putextended(&zfi, swrite, this)) != ZE_OK) return ZR_WRITE;
2798 | writ += 16L;
2799 | zfi.flg = zfi.lflg; // if flg modified by inflate, for the central index
2800 | }
2801 | if (oerr != ZR_OK) return oerr;
2802 |
2803 | // Keep a copy of the zipfileinfo, for our end-of-zip directory
2804 | char *cextra = new char[zfi.cext]; memcpy(cextra, zfi.cextra, zfi.cext); zfi.cextra = cextra;
2805 | TZipFileInfo *pzfi = new TZipFileInfo; memcpy(pzfi, &zfi, sizeof(zfi));
2806 | if (zfis == NULL) zfis = pzfi;
2807 | else { TZipFileInfo *z = zfis; while (z->nxt != NULL) z = z->nxt; z->nxt = pzfi; }
2808 | return ZR_OK;
2809 | }
2810 |
2811 | ZRESULT TZip::AddCentral()
2812 | { // write central directory
2813 | int numentries = 0;
2814 | ulg pos_at_start_of_central = writ;
2815 | //ulg tot_unc_size=0, tot_compressed_size=0;
2816 | bool okay = true;
2817 | for (TZipFileInfo *zfi = zfis; zfi != NULL;)
2818 | {
2819 | if (okay)
2820 | {
2821 | int res = putcentral(zfi, swrite, this);
2822 | if (res != ZE_OK) okay = false;
2823 | }
2824 | writ += 4 + CENHEAD + (unsigned int)zfi->nam + (unsigned int)zfi->cext + (unsigned int)zfi->com;
2825 | //tot_unc_size += zfi->len;
2826 | //tot_compressed_size += zfi->siz;
2827 | numentries++;
2828 | //
2829 | TZipFileInfo *zfinext = zfi->nxt;
2830 | if (zfi->cextra != 0) delete[] zfi->cextra;
2831 | delete zfi;
2832 | zfi = zfinext;
2833 | }
2834 | ulg center_size = writ - pos_at_start_of_central;
2835 | if (okay)
2836 | {
2837 | int res = putend(numentries, center_size, pos_at_start_of_central + ooffset, 0, NULL, swrite, this);
2838 | if (res != ZE_OK) okay = false;
2839 | writ += 4 + ENDHEAD + 0;
2840 | }
2841 | if (!okay) return ZR_WRITE;
2842 | return ZR_OK;
2843 | }
2844 |
2845 |
2846 |
2847 |
2848 |
2849 | ZRESULT lasterrorZ = ZR_OK;
2850 |
2851 | unsigned int FormatZipMessageZ(ZRESULT code, char *buf, unsigned int len)
2852 | {
2853 | if (code == ZR_RECENT) code = lasterrorZ;
2854 | const char *msg = "unknown zip result code";
2855 | switch (code)
2856 | {
2857 | case ZR_OK: msg = "Success"; break;
2858 | case ZR_NODUPH: msg = "Culdn't duplicate handle"; break;
2859 | case ZR_NOFILE: msg = "Couldn't create/open file"; break;
2860 | case ZR_NOALLOC: msg = "Failed to allocate memory"; break;
2861 | case ZR_WRITE: msg = "Error writing to file"; break;
2862 | case ZR_NOTFOUND: msg = "File not found in the zipfile"; break;
2863 | case ZR_MORE: msg = "Still more data to unzip"; break;
2864 | case ZR_CORRUPT: msg = "Zipfile is corrupt or not a zipfile"; break;
2865 | case ZR_READ: msg = "Error reading file"; break;
2866 | case ZR_ARGS: msg = "Caller: faulty arguments"; break;
2867 | case ZR_PARTIALUNZ: msg = "Caller: the file had already been partially unzipped"; break;
2868 | case ZR_NOTMMAP: msg = "Caller: can only get memory of a memory zipfile"; break;
2869 | case ZR_MEMSIZE: msg = "Caller: not enough space allocated for memory zipfile"; break;
2870 | case ZR_FAILED: msg = "Caller: there was a previous error"; break;
2871 | case ZR_ENDED: msg = "Caller: additions to the zip have already been ended"; break;
2872 | case ZR_ZMODE: msg = "Caller: mixing creation and opening of zip"; break;
2873 | case ZR_NOTINITED: msg = "Zip-bug: internal initialisation not completed"; break;
2874 | case ZR_SEEK: msg = "Zip-bug: trying to seek the unseekable"; break;
2875 | case ZR_MISSIZE: msg = "Zip-bug: the anticipated size turned out wrong"; break;
2876 | case ZR_NOCHANGE: msg = "Zip-bug: tried to change mind, but not allowed"; break;
2877 | case ZR_FLATE: msg = "Zip-bug: an internal error during flation"; break;
2878 | }
2879 | unsigned int mlen = (unsigned int)strlen(msg);
2880 | if (buf == 0 || len == 0) return mlen;
2881 | unsigned int n = mlen; if (n + 1>len) n = len - 1;
2882 | strncpy(buf, msg, n); buf[n] = 0;
2883 | return mlen;
2884 | }
2885 |
2886 |
2887 |
2888 | typedef struct
2889 | {
2890 | DWORD flag;
2891 | TZip *zip;
2892 | } TZipHandleData;
2893 |
2894 |
2895 | HZIP CreateZipInternal(void *z, unsigned int len, DWORD flags, const char *password)
2896 | {
2897 | TZip *zip = new TZip(password);
2898 | lasterrorZ = zip->Create(z, len, flags);
2899 | if (lasterrorZ != ZR_OK) { delete zip; return 0; }
2900 | TZipHandleData *han = new TZipHandleData;
2901 | han->flag = 2; han->zip = zip; return (HZIP)han;
2902 | }
2903 | HZIP CreateZipHandle(HANDLE h, const char *password) { return CreateZipInternal(h, 0, ZIP_HANDLE, password); }
2904 | HZIP CreateZip(const TCHAR *fn, const char *password) { return CreateZipInternal((void*)fn, 0, ZIP_FILENAME, password); }
2905 | HZIP CreateZip(void *z, unsigned int len, const char *password) { return CreateZipInternal(z, len, ZIP_MEMORY, password); }
2906 |
2907 |
2908 | ZRESULT ZipAddInternal(HZIP hz, const TCHAR *dstzn, void *src, unsigned int len, DWORD flags)
2909 | {
2910 | if (hz == 0) { lasterrorZ = ZR_ARGS; return ZR_ARGS; }
2911 | TZipHandleData *han = (TZipHandleData*)hz;
2912 | if (han->flag != 2) { lasterrorZ = ZR_ZMODE; return ZR_ZMODE; }
2913 | TZip *zip = han->zip;
2914 | lasterrorZ = zip->Add(dstzn, src, len, flags);
2915 | return lasterrorZ;
2916 | }
2917 | ZRESULT ZipAdd(HZIP hz, const TCHAR *dstzn, const TCHAR *fn) { return ZipAddInternal(hz, dstzn, (void*)fn, 0, ZIP_FILENAME); }
2918 | ZRESULT ZipAdd(HZIP hz, const TCHAR *dstzn, void *src, unsigned int len){ return ZipAddInternal(hz, dstzn, src, len, ZIP_MEMORY); }
2919 | ZRESULT ZipAddHandle(HZIP hz, const TCHAR *dstzn, HANDLE h) { return ZipAddInternal(hz, dstzn, h, 0, ZIP_HANDLE); }
2920 | ZRESULT ZipAddHandle(HZIP hz, const TCHAR *dstzn, HANDLE h, unsigned int len) { return ZipAddInternal(hz, dstzn, h, len, ZIP_HANDLE); }
2921 | ZRESULT ZipAddFolder(HZIP hz, const TCHAR *dstzn) { return ZipAddInternal(hz, dstzn, 0, 0, ZIP_FOLDER); }
2922 |
2923 |
2924 |
2925 | ZRESULT ZipGetMemory(HZIP hz, void **buf, unsigned long *len)
2926 | {
2927 | if (hz == 0) { if (buf != 0) *buf = 0; if (len != 0) *len = 0; lasterrorZ = ZR_ARGS; return ZR_ARGS; }
2928 | TZipHandleData *han = (TZipHandleData*)hz;
2929 | if (han->flag != 2) { lasterrorZ = ZR_ZMODE; return ZR_ZMODE; }
2930 | TZip *zip = han->zip;
2931 | lasterrorZ = zip->GetMemory(buf, len);
2932 | return lasterrorZ;
2933 | }
2934 |
2935 | ZRESULT CloseZipZ(HZIP hz)
2936 | {
2937 | if (hz == 0) { lasterrorZ = ZR_ARGS; return ZR_ARGS; }
2938 | TZipHandleData *han = (TZipHandleData*)hz;
2939 | if (han->flag != 2) { lasterrorZ = ZR_ZMODE; return ZR_ZMODE; }
2940 | TZip *zip = han->zip;
2941 | lasterrorZ = zip->Close();
2942 | delete zip;
2943 | delete han;
2944 | return lasterrorZ;
2945 | }
2946 |
2947 | bool IsZipHandleZ(HZIP hz)
2948 | {
2949 | if (hz == 0) return false;
2950 | TZipHandleData *han = (TZipHandleData*)hz;
2951 | return (han->flag == 2);
2952 | }
2953 |
2954 |
--------------------------------------------------------------------------------
/Zip/zip/zip.h:
--------------------------------------------------------------------------------
1 | #ifndef _zip_H
2 | #define _zip_H
3 | #include
4 | //
5 |
6 | //#ifdef ZIP_STD
7 | //#include
8 | //#include
9 | //#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
10 | //#ifndef MAX_PATH
11 | //#define MAX_PATH 1024
12 | //#endif
13 | //typedef unsigned long DWORD;
14 | //typedef char TCHAR;
15 | //typedef FILE* CHANDLE;
16 | //typedef time_t CFILETIME;
17 | //#endif
18 |
19 | // ZIP functions -- for creating zip files
20 | // This file is a repackaged form of the Info-Zip source code available
21 | // at www.info-zip.org. The original copyright notice may be found in
22 | // zip.cpp. The repackaging was done by Lucian Wischik to simplify and
23 | // extend its use in Windows/C++. Also to add encryption and unicode.
24 |
25 | #ifndef _unzip_H
26 | typedef void* HZIP;
27 | #endif
28 | // An HZIP identifies a zip file that is being created
29 |
30 | typedef DWORD ZRESULT;
31 | // return codes from any of the zip functions. Listed later.
32 |
33 |
34 |
35 | HZIP CreateZip(const TCHAR *fn, const char *password);
36 | HZIP CreateZip(void *buf, unsigned int len, const char *password);
37 | HZIP CreateZipHandle(HANDLE h, const char *password);
38 | // CreateZip - call this to start the creation of a zip file.
39 | // As the zip is being created, it will be stored somewhere:
40 | // to a pipe: CreateZipHandle(hpipe_write);
41 | // in a file (by handle): CreateZipHandle(hfile);
42 | // in a file (by name): CreateZip("c:\\test.zip");
43 | // in memory: CreateZip(buf, len);
44 | // or in pagefile memory: CreateZip(0, len);
45 | // The final case stores it in memory backed by the system paging file,
46 | // where the zip may not exceed len bytes. This is a bit friendlier than
47 | // allocating memory with new[]: it won't lead to fragmentation, and the
48 | // memory won't be touched unless needed. That means you can give very
49 | // large estimates of the maximum-size without too much worry.
50 | // As for the password, it lets you encrypt every file in the archive.
51 | // (This api doesn't support per-file encryption.)
52 | // Note: because pipes don't allow random access, the structure of a zipfile
53 | // created into a pipe is slightly different from that created into a file
54 | // or memory. In particular, the compressed-size of the item cannot be
55 | // stored in the zipfile until after the item itself. (Also, for an item added
56 | // itself via a pipe, the uncompressed-size might not either be known until
57 | // after.) This is not normally a problem. But if you try to unzip via a pipe
58 | // as well, then the unzipper will not know these things about the item until
59 | // after it has been unzipped. Therefore: for unzippers which don't just write
60 | // each item to disk or to a pipe, but instead pre-allocate memory space into
61 | // which to unzip them, then either you have to create the zip not to a pipe,
62 | // or you have to add items not from a pipe, or at least when adding items
63 | // from a pipe you have to specify the length.
64 | // Note: for windows-ce, you cannot close the handle until after CloseZip.
65 | // but for real windows, the zip makes its own copy of your handle, so you
66 | // can close yours anytime.
67 |
68 |
69 | ZRESULT ZipAdd(HZIP hz, const TCHAR *dstzn, const TCHAR *fn);
70 | ZRESULT ZipAdd(HZIP hz, const TCHAR *dstzn, void *src, unsigned int len);
71 | ZRESULT ZipAddHandle(HZIP hz, const TCHAR *dstzn, HANDLE h);
72 | ZRESULT ZipAddHandle(HZIP hz, const TCHAR *dstzn, HANDLE h, unsigned int len);
73 | ZRESULT ZipAddFolder(HZIP hz, const TCHAR *dstzn);
74 | ZRESULT ZipAddFolder(HZIP hz, const TCHAR *dstzn, TCHAR* src, int len);
75 | // ZipAdd - call this for each file to be added to the zip.
76 | // dstzn is the name that the file will be stored as in the zip file.
77 | // The file to be added to the zip can come
78 | // from a pipe: ZipAddHandle(hz,"file.dat", hpipe_read);
79 | // from a file: ZipAddHandle(hz,"file.dat", hfile);
80 | // from a filen: ZipAdd(hz,"file.dat", "c:\\docs\\origfile.dat");
81 | // from memory: ZipAdd(hz,"subdir\\file.dat", buf,len);
82 | // (folder): ZipAddFolder(hz,"subdir");
83 | // Note: if adding an item from a pipe, and if also creating the zip file itself
84 | // to a pipe, then you might wish to pass a non-zero length to the ZipAddHandle
85 | // function. This will let the zipfile store the item's size ahead of the
86 | // compressed item itself, which in turn makes it easier when unzipping the
87 | // zipfile from a pipe.
88 |
89 | ZRESULT ZipGetMemory(HZIP hz, void **buf, unsigned long *len);
90 | // ZipGetMemory - If the zip was created in memory, via ZipCreate(0,len),
91 | // then this function will return information about that memory block.
92 | // buf will receive a pointer to its start, and len its length.
93 | // Note: you can't add any more after calling this.
94 |
95 | ZRESULT CloseZip(HZIP hz);
96 | // CloseZip - the zip handle must be closed with this function.
97 |
98 | unsigned int FormatZipMessage(ZRESULT code, TCHAR *buf, unsigned int len);
99 | // FormatZipMessage - given an error code, formats it as a string.
100 | // It returns the length of the error message. If buf/len points
101 | // to a real buffer, then it also writes as much as possible into there.
102 |
103 |
104 |
105 | // These are the result codes:
106 | #define ZR_OK 0x00000000 // nb. the pseudo-code zr-recent is never returned,
107 | #define ZR_RECENT 0x00000001 // but can be passed to FormatZipMessage.
108 | // The following come from general system stuff (e.g. files not openable)
109 | #define ZR_GENMASK 0x0000FF00
110 | #define ZR_NODUPH 0x00000100 // couldn't duplicate the handle
111 | #define ZR_NOFILE 0x00000200 // couldn't create/open the file
112 | #define ZR_NOALLOC 0x00000300 // failed to allocate some resource
113 | #define ZR_WRITE 0x00000400 // a general error writing to the file
114 | #define ZR_NOTFOUND 0x00000500 // couldn't find that file in the zip
115 | #define ZR_MORE 0x00000600 // there's still more data to be unzipped
116 | #define ZR_CORRUPT 0x00000700 // the zipfile is corrupt or not a zipfile
117 | #define ZR_READ 0x00000800 // a general error reading the file
118 | // The following come from mistakes on the part of the caller
119 | #define ZR_CALLERMASK 0x00FF0000
120 | #define ZR_ARGS 0x00010000 // general mistake with the arguments
121 | #define ZR_NOTMMAP 0x00020000 // tried to ZipGetMemory, but that only works on mmap zipfiles, which yours wasn't
122 | #define ZR_MEMSIZE 0x00030000 // the memory size is too small
123 | #define ZR_FAILED 0x00040000 // the thing was already failed when you called this function
124 | #define ZR_ENDED 0x00050000 // the zip creation has already been closed
125 | #define ZR_MISSIZE 0x00060000 // the indicated input file size turned out mistaken
126 | #define ZR_PARTIALUNZ 0x00070000 // the file had already been partially unzipped
127 | #define ZR_ZMODE 0x00080000 // tried to mix creating/opening a zip
128 | // The following come from bugs within the zip library itself
129 | #define ZR_BUGMASK 0xFF000000
130 | #define ZR_NOTINITED 0x01000000 // initialisation didn't work
131 | #define ZR_SEEK 0x02000000 // trying to seek in an unseekable file
132 | #define ZR_NOCHANGE 0x04000000 // changed its mind on storage, but not allowed
133 | #define ZR_FLATE 0x05000000 // an internal error in the de/inflation code
134 |
135 |
136 |
137 |
138 |
139 |
140 | // e.g.
141 | //
142 | // (1) Traditional use, creating a zipfile from existing files
143 | // HZIP hz = CreateZip("c:\\simple1.zip",0);
144 | // ZipAdd(hz,"znsimple.bmp", "c:\\simple.bmp");
145 | // ZipAdd(hz,"znsimple.txt", "c:\\simple.txt");
146 | // CloseZip(hz);
147 | //
148 | // (2) Memory use, creating an auto-allocated mem-based zip file from various sources
149 | // HZIP hz = CreateZip(0,100000, 0);
150 | // // adding a conventional file...
151 | // ZipAdd(hz,"src1.txt", "c:\\src1.txt");
152 | // // adding something from memory...
153 | // char buf[1000]; for (int i=0; i<1000; i++) buf[i]=(char)(i&0x7F);
154 | // ZipAdd(hz,"file.dat", buf,1000);
155 | // // adding something from a pipe...
156 | // CHANDLE hread,hwrite; CreatePipe(&hread,&hwrite,NULL,0);
157 | // CHANDLE hthread = CreateThread(0,0,ThreadFunc,(void*)hwrite,0,0);
158 | // ZipAdd(hz,"unz3.dat", hread,1000); // the '1000' is optional.
159 | // WaitForSingleObject(hthread,INFINITE);
160 | // CloseHandle(hthread); CloseHandle(hread);
161 | // ... meanwhile DWORD WINAPI ThreadFunc(void *dat)
162 | // { CHANDLE hwrite = (CHANDLE)dat;
163 | // char buf[1000]={17};
164 | // DWORD writ; WriteFile(hwrite,buf,1000,&writ,NULL);
165 | // CloseHandle(hwrite);
166 | // return 0;
167 | // }
168 | // // and now that the zip is created, let's do something with it:
169 | // void *zbuf; unsigned long zlen; ZipGetMemory(hz,&zbuf,&zlen);
170 | // CHANDLE hfz = CreateFile("test2.zip",GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
171 | // DWORD writ; WriteFile(hfz,zbuf,zlen,&writ,NULL);
172 | // CloseHandle(hfz);
173 | // CloseZip(hz);
174 | //
175 | // (3) Handle use, for file handles and pipes
176 | // CHANDLE hzread,hzwrite; CreatePipe(&hzread,&hzwrite,0,0);
177 | // CHANDLE hthread = CreateThread(0,0,ZipReceiverThread,(void*)hzread,0,0);
178 | // HZIP hz = CreateZipHandle(hzwrite,0);
179 | // // ... add to it
180 | // CloseZip(hz);
181 | // CloseHandle(hzwrite);
182 | // WaitForSingleObject(hthread,INFINITE);
183 | // CloseHandle(hthread);
184 | // ... meanwhile DWORD WINAPI ZipReceiverThread(void *dat)
185 | // { CHANDLE hread = (CHANDLE)dat;
186 | // char buf[1000];
187 | // while (true)
188 | // { DWORD red; ReadFile(hread,buf,1000,&red,NULL);
189 | // // ... and do something with this zip data we're receiving
190 | // if (red==0) break;
191 | // }
192 | // CloseHandle(hread);
193 | // return 0;
194 | // }
195 |
196 |
197 |
198 | // Now we indulge in a little skullduggery so that the code works whether
199 | // the user has included just zip or both zip and unzip.
200 | // Idea: if header files for both zip and unzip are present, then presumably
201 | // the cpp files for zip and unzip are both present, so we will call
202 | // one or the other of them based on a dynamic choice. If the header file
203 | // for only one is present, then we will bind to that particular one.
204 | ZRESULT CloseZipZ(HZIP hz);
205 | unsigned int FormatZipMessageZ(ZRESULT code, char *buf, unsigned int len);
206 | bool IsZipHandleZ(HZIP hz);
207 | #ifdef _unzip_H
208 | #undef CloseZip
209 | #define CloseZip(hz) (IsZipHandleZ(hz)?CloseZipZ(hz):CloseZipU(hz))
210 | #else
211 | #define CloseZip CloseZipZ
212 | #define FormatZipMessage FormatZipMessageZ
213 | #endif
214 |
215 |
216 |
217 | #endif
218 |
--------------------------------------------------------------------------------