├── 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 | --------------------------------------------------------------------------------