/// low-level access to ZLib compression (1.2.5 engine version) // - this unit is a part of the freeware Synopse framework, // licensed under a MPL/GPL/LGPL tri-license; version 1.18 unit SynZip; { This file is part of Synopse framework. Synopse framework. Copyright (C) 2022 Arnaud Bouchez Synopse Informatique - https://synopse.info *** BEGIN LICENSE BLOCK ***** Version: MPL 1.1/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is Synopse framework. The Initial Developer of the Original Code is Arnaud Bouchez. Portions created by the Initial Developer are Copyright (C) 2022 the Initial Developer. All Rights Reserved. Contributor(s): - Alf - Andre Heider (dhewg) - ehansen - jpdk - Gigo Alternatively, the contents of this file may be used under the terms of either the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the MPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. ***** END LICENSE BLOCK ***** ORIGINAL LICENSE: zlib.h -- interface of the 'zlib' general purpose compression library version 1.2.5, April 19th, 2010 Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler Cross-platform ZLib implementation ==================================== Link to original C-compiled ZLib library - Win32: use fast obj and inline asm - Linux: use available system library libz.so Also defines .zip file structure (TFileInfo TFileHeader TLastHeader) } {$I Synopse.inc} // define HASINLINE CPU32 CPU64 {.$define USEZLIBSSE} // if defined (only FPC+Win64), will link static\x86_64-win64sse\*.o static libraries // from https://github.com/cloudflare/zlib (warning: SSE3/SSE4.2 CPUs only) {.$define USECFZLIB} // https://github.com/cloudflare/zlib as external dll {$ifdef USECFZLIB} {$define USEEXTZLIB} {$else} {$ifdef FPC} {$ifdef MSWINDOWS} // avoid link to zlib1.dll {.$define USEPASZLIB} // paszlib makes Z_BUF_ERROR with bits = -MAX_WBITS {$ifdef Win32} {.$define USEZLIBSSE} // SynZLibSSE static .o files for FPC + Win32 fails {$endif} {$ifdef Win64} {.$define USEEXTZLIB} // use zlib-64.dll as in \fpc-win64 sub-folder {$endif} {$else} // will use zlib.so under Linux/Posix {$ifdef ANDROID} {$define USEPASZLIB} // Alf: problem with external zlib.so under Android {$else} {$define USEEXTZLIB} {$endif} {$endif} {$else} {$undef USEZLIBSSE} // Delphi linker is buggy as hell {$ifndef USEEXTZLIB} // define USEEXTZLIB for the project for better performance {$ifdef MSWINDOWS} {$ifdef Win32} {$define USEINLINEASM} // if defined, we use a special inlined asm version for uncompress: // seems 50% faster than BC++ generated .obj, and is 3KB smaller in code size {$endif} {$ifdef Win64} {$define USEDELPHIZLIB} // System.ZLib is (much) slower, but static {.$define USEEXTZLIB} // use faster zlib-64.dll as in \fpc-win64 sub-folder {$endif} {$else} {$define USEEXTZLIB} // e.g. for Kylix {$endif} {$endif USEEXTZLIB} {$endif} {$endif USECFZLIB} interface uses {$ifdef MSWINDOWS} Windows, {$else} {$ifdef KYLIX3} LibC, {$else} {$ifndef ANDROID} clocale, {$endif} {$endif} Types, {$endif} {$ifdef USEPASZLIB} zbase, paszlib, {$endif} SysUtils, Classes; type /// the format used for storing data TSynZipCompressorFormat = (szcfRaw, szcfZip, szcfGZ); {$ifdef DELPHI5OROLDER} type // Delphi 5 doesn't have those base types defined :( PInteger = ^Integer; PCardinal = ^Cardinal; IntegerArray = array[0..$effffff] of Integer; const PathDelim = '\'; soCurrent = soFromCurrent; function IncludeTrailingPathDelimiter(const FileName: TFileName): TFileName; {$endif} /// in-memory ZLib DEFLATE compression // - by default, will use the deflate/.zip header-less format, but you may set // ZlibFormat=true to add an header, as expected by zlib (and pdf) function CompressMem(src, dst: pointer; srcLen, dstLen: integer; CompressionLevel: integer=6; ZlibFormat: Boolean=false) : integer; /// in-memory ZLib INFLATE decompression // - by default, will use the deflate/.zip header-less format, but you may set // ZlibFormat=true to add an header, as expected by zlib (and pdf) function UnCompressMem(src, dst: pointer; srcLen, dstLen: integer; ZlibFormat: Boolean=false) : integer; /// ZLib DEFLATE compression from memory into a stream // - by default, will use the deflate/.zip header-less format, but you may set // ZlibFormat=true to add an header, as expected by zlib (and pdf) function CompressStream(src: pointer; srcLen: integer; tmp: TStream; CompressionLevel: integer=6; ZlibFormat: Boolean=false; TempBufSize: integer=0): cardinal; /// ZLib INFLATE decompression from memory into a stream // - return the number of bytes written into the stream // - if checkCRC if not nil, it will contain the crc32; if aStream is nil, it // will only calculate the crc of the the uncompressed memory block // - by default, will use the deflate/.zip header-less format, but you may set // ZlibFormat=true to add an header, as expected by zlib (and pdf) function UnCompressStream(src: pointer; srcLen: integer; tmp: TStream; checkCRC: PCardinal; ZlibFormat: Boolean=false; TempBufSize: integer=0): cardinal; type {$ifdef HASCODEPAGE} ZipString = type RawByteString; {$else} /// define a raw storage string type, used for data buffer management ZipString = type AnsiString; {$endif} {$ifdef FPC} ZipPtrUInt = PtrUInt; ZipPtrInt = PtrInt; {$else} /// as available in FPC ZipPtrUInt = {$ifdef CPU64}UInt64{$else}cardinal{$endif}; ZipPtrInt = {$ifdef CPU64}Int64{$else}integer{$endif}; {$endif} /// ZLib INFLATE decompression from memory into a AnsiString (ZipString) variable // - return the number of bytes written into the string // - if checkCRC if not nil, it will contain the crc32; if aStream is nil, it // will only calculate the crc of the the uncompressed memory block // - by default, will use the deflate/.zip header-less format, but you may set // ZlibFormat=true to add an header, as expected by zlib (and pdf) function UnCompressZipString(src: pointer; srcLen: integer; out data: ZipString; checkCRC: PCardinal; ZlibFormat: Boolean; TempBufSize: integer=0): cardinal; /// compress some data, with a proprietary format (including CRC) function CompressString(const data: ZipString; failIfGrow: boolean = false; CompressionLevel: integer=6) : ZipString; /// uncompress some data, with a proprietary format (including CRC) // - return '' in case of a decompression failure function UncompressString(const data: ZipString) : ZipString; /// (un)compress a data content using the gzip algorithm // - as expected by THttpSocket.RegisterCompress // - will use internaly a level compression of 1, i.e. fastest available (content // of 4803 bytes is compressed into 700, and time is 440 us instead of 220 us) function CompressGZip(var DataRawByteString; Compress: boolean): AnsiString; /// (un)compress a data content using the Deflate algorithm (i.e. "raw deflate") // - as expected by THttpSocket.RegisterCompress // - will use internaly a level compression of 1, i.e. fastest available (content // of 4803 bytes is compressed into 700, and time is 440 us instead of 220 us) // - deflate content encoding is pretty inconsistent in practice, so slightly // slower CompressGZip() is preferred - http://stackoverflow.com/a/9186091 function CompressDeflate(var DataRawByteString; Compress: boolean): AnsiString; /// (un)compress a data content using the zlib algorithm // - as expected by THttpSocket.RegisterCompress // - will use internaly a level compression of 1, i.e. fastest available (content // of 4803 bytes is compressed into 700, and time is 440 us instead of 220 us) // - zlib content encoding is pretty inconsistent in practice, so slightly // slower CompressGZip() is preferred - http://stackoverflow.com/a/9186091 function CompressZLib(var DataRawByteString; Compress: boolean): AnsiString; /// low-level check of the code returned by the ZLib library function Check(const Code: Integer; const ValidCodes: array of Integer; const Context: string=''): integer; type PCardinalArray = ^TCardinalArray; TCardinalArray = array[0..(MaxLongint div SizeOf(cardinal))-1] of cardinal; /// just hash aString with CRC32 algorithm // - crc32 is better than adler32 for short strings function CRC32string(const aString: ZipString): cardinal; type /// exception raised internaly in case of Zip errors ESynZipException = class(Exception); {$ifdef USEZLIBSSE} // statically linked with new 64-bit TZStream type TZLong = ZipPtrUint; TZCRC = Int64; {$else} {$ifdef USECFZLIB} // dynamically linked with new 64-bit TZStream type TZLong = ZipPtrUint; TZCRC = Int64; const {$ifdef WIN64} libz='zlibcf64.dll'; {$else} libz='zlibcf32.dll'; {$endif} {$else} {$ifdef USEEXTZLIB} {$ifdef MSWINDOWS} // dynamically linked with old 32-bit TZStream type TZLong = cardinal; TZCRC = cardinal; const {$ifdef WIN2} libz='zlib-32.dll'; // as available in \fpc-win32 sub-folder {$endif} {$ifdef WIN64} libz='zlib-64.dll'; // as available in \fpc-win64 sub-folder {$endif} {$endif MSWINDOWS} {$ifdef KYLIX3} type TZLong = cardinal; TZCRC = cardinal; const libz = 'libz.so.1'; {$else} {$ifdef UNIX} // dynamically linked with new 64-bit TZStream type TZLong = ZipPtrUint; TZCRC = cardinal; const libz='z'; {$linklib libz} {$endif UNIX} {$endif KYLIX3} {$else} // statically linked with old 32-bit TZStream type TZLong = cardinal; TZCRC = cardinal; {$endif USEEXTZLIB} {$endif USECFZLIB} {$endif USEZLIBSSE} type {$ifdef USEPASZLIB} TZStream = z_stream; {$else} /// the internal memory structure as expected by the ZLib library TZStream = record next_in: PAnsiChar; avail_in: cardinal; total_in: TZLong; next_out: PAnsiChar; avail_out: cardinal; total_out: TZLong; msg: PAnsiChar; state: pointer; zalloc: pointer; zfree: pointer; opaque: pointer; data_type: integer; adler: TZLong; reserved: TZLong; end; {$endif USEPASZLIB} /// initialize the internal memory structure as expected by the ZLib library procedure StreamInit(var Stream: TZStream); overload; /// prepare the internal memory structure as expected by the ZLib library for compression function DeflateInit(var Stream: TZStream; CompressionLevel: integer; ZlibFormat: Boolean): Boolean; overload; // don't know why using objects below produce an Internal Error DT5830 // under Delphi 2009 Update 3 !!!!! // -> see http://qc.embarcadero.com/wc/qcmain.aspx?d=79792 // it seems that this compiler doesn't like to compile packed objects, // but all other versions (including Delphi 2009 Update 2) did // -> do Codegear knows about regression tests? type {$A-} { force packed object (not allowed under Delphi 2009) } PFileInfo = ^TFileInfo; /// generic file information structure, as used in .zip file format // - used in any header, contains info about following block {$ifndef USERECORDWITHMETHODS}TFileInfo = object {$else}TFileInfo = record{$endif} neededVersion : word; // $14 flags : word; // 0 zzipMethod : word; // 0=Z_STORED 8=Z_DEFLATED 12=BZ2 14=LZMA zlastMod : integer; // time in dos format zcrc32 : dword; // crc32 checksum of uncompressed data zzipSize : dword; // size of compressed data zfullSize : dword; // size of uncompressed data nameLen : word; // length(name) extraLen : word; // 0 function SameAs(aInfo: PFileInfo): boolean; function AlgoID: integer; // 1..15 (1=SynLZ e.g.) from flags procedure SetAlgoID(Algorithm: integer); function GetUTF8FileName: boolean; procedure SetUTF8FileName; procedure UnSetUTF8FileName; end; /// directory file information structure, as used in .zip file format // - used at the end of the zip file to recap all entries TFileHeader = {$ifdef USERECORDWITHMETHODS}record {$else}object{$endif} signature : dword; // $02014b50 PK#1#2 madeBy : word; // $0314 = OS + version fileInfo : TFileInfo; commentLen : word; // 0 firstDiskNo : word; // 0 intFileAttr : word; // 0 = binary; 1 = text extFileAttr : dword; // dos file attributes localHeadOff : dword; // @TLocalFileHeader function IsFolder: boolean; {$ifdef HASINLINE}inline;{$endif} procedure Init; end; PFileHeader = ^TFileHeader; /// internal file information structure, as used in .zip file format // - used locally inside the file stream, followed by the name and then the data {$ifdef USERECORDWITHMETHODS}TLocalFileHeader = record {$else}TLocalFileHeader = object{$endif} signature : dword; // $04034b50 PK#3#4 fileInfo : TFileInfo; function LocalData: PAnsiChar; end; PLocalFileHeader = ^TLocalFileHeader; /// last header structure, as used in .zip file format // - this header ends the file and is used to find the TFileHeader entries TLastHeader = record signature : dword; // $06054b50 PK#5#6 thisDisk : word; // 0 headerDisk : word; // 0 thisFiles : word; // 1 totalFiles : word; // 1 headerSize : dword; // sizeOf(TFileHeaders + names) headerOffset : dword; // @TFileHeader commentLen : word; // 0 end; PLastHeader = ^TLastHeader; {$A+} const ZLIB_VERSION = '1.2.3'; ZLIB_VERNUM = $1230; Z_NO_FLUSH = 0; Z_PARTIAL_FLUSH = 1; Z_SYNC_FLUSH = 2; Z_FULL_FLUSH = 3; Z_FINISH = 4; Z_BLOCK = 5; Z_OK = 0; Z_STREAM_END = 1; Z_NEED_DICT = 2; Z_ERRNO = -1; Z_STREAM_ERROR = -2; Z_DATA_ERROR = -3; Z_MEM_ERROR = -4; Z_BUF_ERROR = -5; Z_VERSION_ERROR = -6; Z_NO_COMPRESSION = 0; Z_BEST_SPEED = 1; Z_BEST_COMPRESSION = 9; Z_DEFAULT_COMPRESSION = -1; Z_FILTERED = 1; Z_HUFFMAN_ONLY = 2; Z_RLE = 3; Z_FIXED = 4; Z_DEFAULT_STRATEGY = 0; Z_BINARY = 0; Z_ASCII = 1; Z_UNKNOWN = 2; Z_STORED = 0; Z_DEFLATED = 8; MAX_WBITS = 15; // 32K LZ77 window DEF_MEM_LEVEL = 8; Z_NULL = 0; {$ifdef USEPASZLIB} function deflateInit2_(var strm: TZStream; level, method, windowBits, memLevel, strategy: integer; version: PAnsiChar; stream_size: integer): integer; function deflate(var strm: TZStream; flush: integer): integer; function deflateEnd(var strm: TZStream): integer; function inflateInit2_(var strm: TZStream; windowBits: integer; version: PAnsiChar; stream_size: integer): integer; function inflate(var strm: TZStream; flush: integer): integer; function inflateEnd(var strm: TZStream): integer; function adler32(adler: cardinal; buf: PAnsiChar; len: cardinal): cardinal; function crc32(crc: cardinal; buf: PAnsiChar; len: cardinal): cardinal; function get_crc_table: pointer; {$else} { our very own short implementation of ZLibH } {$ifdef USEINLINEASM} function deflateInit2_(var strm: TZStream; level, method, windowBits, memLevel, strategy: integer; version: PAnsiChar; stream_size: integer): integer; function deflate(var strm: TZStream; flush: integer): integer; function deflateEnd(var strm: TZStream): integer; function inflateInit2_(var strm: TZStream; windowBits: integer; version: PAnsiChar; stream_size: integer): integer; stdcall; function inflate(var strm: TZStream; flush: integer): integer; stdcall; function inflateEnd(var strm: TZStream): integer; stdcall; function adler32(adler: cardinal; buf: PAnsiChar; len: cardinal): cardinal; function crc32(crc: cardinal; buf: PAnsiChar; len: cardinal): cardinal; function get_crc_table: pointer; {$else USEINLINEASM} function deflate(var strm: TZStream; flush: integer): integer; cdecl; function deflateEnd(var strm: TZStream): integer; cdecl; function inflate(var strm: TZStream; flush: integer): integer; cdecl; function inflateEnd(var strm: TZStream): integer; cdecl; function adler32(adler: TZCRC; buf: PAnsiChar; len: cardinal): TZCRC; cdecl; function crc32(crc: TZCRC; buf: PAnsiChar; len: cardinal): TZCRC; cdecl; function deflateInit_(var strm: TZStream; level: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; function inflateInit_(var strm: TZStream; version: PAnsiChar; stream_size: integer): integer; cdecl; function deflateInit2_(var strm: TZStream; level, method, windowBits, memLevel, strategy: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; function inflateInit2_(var strm: TZStream; windowBits: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; {$endif USEINLINEASM} {$endif USEPASZLIB} type /// simple wrapper class to decompress a .gz file into memory or stream/file {$ifdef USERECORDWITHMETHODS}TGZRead = record {$else}TGZRead = object{$endif} private comp, zsdest: pointer; zscrc: cardinal; zssize, zscode: integer; zs: TZStream; public complen: ZipPtrInt; uncomplen32: cardinal; // modulo 2^32 by gzip design crc32: cardinal; unixmodtime: cardinal; fname, fcomment, extra: PAnsiChar; /// read and validate the .gz header // - on success, return true and fill complen/uncomplen/crc32c properties function Init(gz: PAnsiChar; gzLen: ZipPtrInt): boolean; /// uncompress the .gz content into a memory buffer // - warning: won't work as expected if uncomplen32 was truncated to 2^32 function ToMem: ZipString; /// uncompress the .gz content into a stream function ToStream(stream: TStream; tempBufSize: integer=0): boolean; /// uncompress the .gz content into a file function ToFile(const filename: TFileName; tempBufSize: integer=0): boolean; /// allow low level iterative decompression using an internal TZStream structure function ZStreamStart(dest: pointer; destsize: integer): boolean; /// return true if ZStreamStart() has been successfully called function ZStreamStarted: boolean; {$ifdef HASINLINE}inline;{$endif} /// will uncompress into dest/destsize buffer as supplied to ZStreamStart // - return the number of bytes uncompressed (<=destsize) // - return 0 if the input stream is finished function ZStreamNext: integer; /// any successfull call to ZStreamStart should always run ZStreamDone // - return true if the crc and the uncompressed size are ok function ZStreamDone: boolean; end; /// uncompress a .gz file content // - return '' if the .gz content is invalid (e.g. bad crc) function GZRead(gz: PAnsiChar; gzLen: integer): ZipString; /// compress a file content into a new .gz file // - will use TSynZipCompressor for minimal memory use during file compression function GZFile(const orig, destgz: TFileName; CompressionLevel: Integer=6): boolean; const /// operating-system dependent wildchar to match all files in a folder ZIP_FILES_ALL = {$ifdef MSWINDOWS}'*.*'{$else}'*'{$endif}; type /// a simple TStream descendant for compressing data into a stream // - this simple version don't use any internal buffer, but rely // on Zip library buffering system // - the version in SynZipFiles is much more powerfull, but this one // is sufficient for most common cases (e.g. for on the fly .gz backup) TSynZipCompressor = class(TStream) private fInitialized: Boolean; fDestStream: TStream; fStrm: TZStream; fCRC: Cardinal; fGZFormat: boolean; fBufferOut: array[word] of byte; // a 64 KB buffer function FlushBufferOut: integer; public /// create a compression stream, writting the compressed data into // the specified stream (e.g. a file stream) constructor Create(outStream: TStream; CompressionLevel: Integer; Format: TSynZipCompressorFormat = szcfRaw); /// release memory destructor Destroy; override; /// this method will raise an error: it's a compression-only stream function Read(var Buffer; Count: Longint): Longint; override; /// add some data to be compressed function Write(const Buffer; Count: Longint): Longint; override; /// used to return the current position, i.e. the real byte written count // - for real seek, this method will raise an error: it's a compression-only stream function Seek(Offset: Longint; Origin: Word): Longint; override; /// the number of byte written, i.e. the current uncompressed size function SizeIn: cardinal; /// the number of byte sent to the destination stream, i.e. the current // compressed size function SizeOut: cardinal; /// write all pending compressed data into outStream procedure Flush; /// the current CRC of the written data, i.e. the uncompressed data CRC property CRC: cardinal read fCRC; end; /// stores an entry of a file inside a .zip archive TZipEntry = record /// the information of this file, as stored locally in the .zip archive // - note that infoLocal^.zzipSize/zfullSize/zcrc32 may be 0 if the info // was stored in a "data descriptor" block after the data: in this case, // you should use TZipRead.RetrieveFileInfo() instead of this structure infoLocal: PFileInfo; /// the information of this file, as stored at the end of the .zip archive // - may differ from infoLocal^ content, depending of the zipper tool used infoDirectory: PFileHeader; /// points to the compressed data in the .zip archive, mapped in memory data: PAnsiChar; /// name of the file inside the .zip archive // - not ASCIIZ: length = infoLocal.nameLen storedName: PAnsiChar; /// name of the file inside the .zip archive // - converted from DOS/OEM or UTF-8 into generic (Unicode) string zipName: TFileName; end; /// read-only access to a .zip archive file // - can open directly a specified .zip file (will be memory mapped for fast access) // - can open a .zip archive file content from a resource (embedded in the executable) // - can open a .zip archive file content from memory TZipRead = class private buf: PByteArray; FirstFileHeader: PFileHeader; ReadOffset: cardinal; {$ifdef MSWINDOWS} file_, map: ZipPtrUint; {$else} file_: THandle; mapSize: cardinal; {$endif} procedure UnMap; function UnZipStream(aIndex: integer; const aInfo: TFileInfo; aDest: TStream): boolean; public /// the number of files inside a .zip archive Count: integer; /// the files inside the .zip archive Entry: array of TZipEntry; /// open a .zip archive file as Read Only constructor Create(const aFileName: TFileName; ZipStartOffset: cardinal=0; Size: cardinal=0); overload; /// open a .zip archive file directly from a resource constructor Create(Instance: THandle; const ResName: string; ResType: PChar); overload; /// open a .zip archive file from its File Handle constructor Create(aFile: THandle; ZipStartOffset: cardinal=0; Size: cardinal=0); overload; /// open a .zip archive file directly from memory constructor Create(BufZip: PByteArray; Size: cardinal); overload; /// release associated memory destructor Destroy; override; /// get the index of a file inside the .zip archive function NameToIndex(const aName: TFileName): integer; /// uncompress a file stored inside the .zip archive into memory function UnZip(aIndex: integer): ZipString; overload; /// uncompress a file stored inside the .zip archive into a stream function UnZip(aIndex: integer; aDest: TStream): boolean; overload; /// uncompress a file stored inside the .zip archive into a destination directory function UnZip(aIndex: integer; const DestDir: TFileName; DestDirIsFileName: boolean=false): boolean; overload; /// uncompress a file stored inside the .zip archive into memory function UnZip(const aName: TFileName): ZipString; overload; /// uncompress a file stored inside the .zip archive into a destination directory function UnZip(const aName, DestDir: TFileName; DestDirIsFileName: boolean=false): boolean; overload; /// uncompress all fields stored inside the .zip archive into the supplied // destination directory // - returns -1 on success, or the index in Entry[] of the failing file function UnZipAll(DestDir: TFileName): integer; /// retrieve information about a file // - in some cases (e.g. for a .zip created by latest Java JRE), // infoLocal^.zzipSize/zfullSize/zcrc32 may equal 0: this method is able // to retrieve the information either from the ending "central directory", // or by searching the "data descriptor" block // - returns TRUE if the Index is correct and the info was retrieved // - returns FALSE if the information was not successfully retrieved function RetrieveFileInfo(Index: integer; var Info: TFileInfo): boolean; end; /// abstract write-only access for creating a .zip archive // - update can be done manualy by using a TZipRead instance and the // AddFromZip() method TZipWriteAbstract = class protected fAppendOffset: cardinal; fMagic: cardinal; function InternalAdd(const zipName: TFileName; Buf: pointer; Size: integer): cardinal; function InternalWritePosition: cardinal; virtual; abstract; procedure InternalWrite(const buf; len: cardinal); virtual; abstract; public /// the total number of entries Count: integer; /// the resulting file entries, ready to be written as a .zip catalog // - those will be appended after the data blocks at the end of the .zip file Entry: array of record /// the file name, as stored in the .zip internal directory intName: ZipString; /// the corresponding file header fhr: TFileHeader; end; /// initialize the .zip archive // - a new .zip file content is prepared constructor Create; /// compress (using the deflate method) a memory buffer, and add it to the zip file // - by default, the 1st of January, 2010 is used if not date is supplied procedure AddDeflated(const aZipName: TFileName; Buf: pointer; Size: integer; CompressLevel: integer=6; FileAge: integer=1+1 shl 5+30 shl 9); overload; /// add a memory buffer to the zip file, without compression // - content is stored, not deflated // (in that case, no deflate code is added to the executable) // - by default, the 1st of January, 2010 is used if not date is supplied procedure AddStored(const aZipName: TFileName; Buf: pointer; Size: integer; FileAge: integer=1+1 shl 5+30 shl 9); /// add a file from an already compressed zip entry procedure AddFromZip(Source: TZipRead; EntryIndex: integer); /// append a file content into the destination file // - useful to add the initial Setup.exe file, e.g. procedure Append(const Content: ZipString); /// release associated memory, and close destination archive destructor Destroy; override; end; /// write-only access for creating a .zip archive file // - not to be used to update a .zip file, but to create a new one TZipWrite = class(TZipWriteAbstract) protected fFileName: TFileName; function InternalWritePosition: cardinal; override; procedure InternalWrite(const buf; len: cardinal); override; public /// the associated file handle Handle: integer; /// initialize the .zip file // - a new .zip file content is created constructor Create(const aFileName: TFileName); overload; /// initialize an existing .zip file in order to add some content to it // - warning: AddStored/AddDeflated() won't check for duplicate zip entries // - this method is very fast, and will increase the .zip file in-place // (the old content is not copied, new data is appended at the file end) // - "dummy" parameter exists only to disambiguate constructors for C++ constructor CreateFrom(const aFileName: TFileName; dummy: integer=0); /// compress (using the deflate method) a file, and add it to the zip file procedure AddDeflated(const aFileName: TFileName; RemovePath: boolean=true; CompressLevel: integer=6; ZipName: TFileName=''); overload; /// compress (using the deflate method) all files within a folder, and // add it to the zip file // - if Recursive is TRUE, would include files from nested sub-folders procedure AddFolder(const FolderName: TFileName; const Mask: TFileName=ZIP_FILES_ALL; Recursive: boolean=true; CompressLevel: integer=6); /// release associated memory, and close destination file destructor Destroy; override; end; /// write-only access for creating a .zip archive into a stream TZipWriteToStream = class(TZipWriteAbstract) protected fDest: TStream; function InternalWritePosition: cardinal; override; procedure InternalWrite(const buf; len: cardinal); override; public /// initialize the .zip archive // - a new .zip file content is prepared constructor Create(aDest: TStream); end; /// a TSynLogArchiveEvent handler which will compress older .log files // into .zip archive files // - resulting file will be named YYYYMM.zip and will be located in the // aDestinationPath directory, i.e. TSynLogFamily.ArchivePath+'\log\YYYYMM.zip' function EventArchiveZip(const aOldLogFileName, aDestinationPath: TFileName): boolean; implementation {$ifdef USEDELPHIZLIB} uses ZLib; {$endif USEDELPHIZLIB} {$ifdef Linux} uses {$ifdef FPC} SynFPCLinux, BaseUnix; {$else} SynKylix; {$endif} {$endif Linux} {$ifdef DELPHI5OROLDER} function IncludeTrailingPathDelimiter(const FileName: TFileName): TFileName; begin result := IncludeTrailingBackslash(FileName); end; {$endif} const // those constants have +1 to avoid finding it in the exe FIRSTHEADER_SIGNATURE_INC = $04034b50+1; // PK#3#4 LASTHEADER_SIGNATURE_INC = $06054b50+1; // PK#5#6 ENTRY_SIGNATURE_INC = $02014b50+1; // PK#1#2 { TZipWrite } var EventArchiveZipWrite: TZipWrite = nil; function EventArchiveZip(const aOldLogFileName, aDestinationPath: TFileName): boolean; var n: integer; begin result := false; if aOldLogFileName='' then FreeAndNil(EventArchiveZipWrite) else begin if not FileExists(aOldLogFileName) then exit; if EventArchiveZipWrite=nil then EventArchiveZipWrite := TZipWrite.CreateFrom( system.copy(aDestinationPath,1,length(aDestinationPath)-1)+'.zip'); n := EventArchiveZipWrite.Count; EventArchiveZipWrite.AddDeflated(aOldLogFileName,True); if (EventArchiveZipWrite.Count=n+1) and DeleteFile(aOldLogFileName) then result := True; end; end; function Is7BitAnsi(P: PChar): boolean; begin if P<>nil then while true do if ord(P^)=0 then break else if ord(P^)<=126 then inc(P) else begin result := false; exit; end; result := true; end; { TZipWriteAbstract } constructor TZipWriteAbstract.Create; begin fMagic := FIRSTHEADER_SIGNATURE_INC; // +1 to avoid finding it in the exe generated code dec(fMagic); end; function TZipWriteAbstract.InternalAdd(const zipName: TFileName; Buf: pointer; Size: integer): cardinal; begin with Entry[Count] do begin fHr.signature := ENTRY_SIGNATURE_INC; // +1 to avoid finding it in the exe dec(fHr.signature); fHr.madeBy := $0314; // where $03=Unix (for proper UTF8 filenames) and $14=version fHr.fileInfo.neededVersion := $14; result := InternalWritePosition; fHr.localHeadOff := result-fAppendOffset; {$ifndef DELPHI5OROLDER} // Delphi 5 doesn't have UTF8Decode/UTF8Encode functions -> make 7 bit version if Is7BitAnsi(pointer(zipName)) then begin {$endif} {$ifdef UNICODE} intName := AnsiString(zipName); {$else} // intName := zipName -> error reference count under Delphi 6 SetString(intName,PAnsiChar(pointer(zipName)),length(zipName)); {$endif} fHr.fileInfo.UnSetUTF8FileName; {$ifndef DELPHI5OROLDER} end else begin intName := UTF8Encode(WideString(zipName)); fHr.fileInfo.SetUTF8FileName; end; {$endif} fHr.fileInfo.nameLen := length(intName); fhr.fileInfo.extraLen := 0; // source may have something here InternalWrite(fMagic,sizeof(fMagic)); InternalWrite(fhr.fileInfo,sizeof(fhr.fileInfo)); InternalWrite(pointer(intName)^,fhr.fileInfo.nameLen); end; if Buf<>nil then begin InternalWrite(Buf^,Size); // write stored data inc(Count); end; end; procedure TZipWriteAbstract.AddDeflated(const aZipName: TFileName; Buf: pointer; Size, CompressLevel, FileAge: integer); var tmp: pointer; tmpsize: integer; begin if self=nil then exit; if Count>=length(Entry) then SetLength(Entry,length(Entry)+20); with Entry[Count] do begin with fhr.fileInfo do begin zcrc32 := SynZip.crc32(0,Buf,Size); zfullSize := Size; zzipMethod := Z_DEFLATED; zlastMod := FileAge; tmpsize := (Int64(Size)*11) div 10+12; Getmem(tmp,tmpSize); zzipSize := CompressMem(Buf,tmp,Size,tmpSize,CompressLevel); InternalAdd(aZipName,tmp,zzipSize); // write deflated data and inc(Count) Freemem(tmp); end; end; end; procedure TZipWriteAbstract.AddStored(const aZipName: TFileName; Buf: pointer; Size, FileAge: integer); begin if self=nil then exit; if Count>=length(Entry) then SetLength(Entry,length(Entry)+20); with Entry[Count], fhr.fileInfo do begin zcrc32 := SynZip.crc32(0,Buf,Size); zfullSize := Size; zzipSize := Size; zlastMod := FileAge; InternalAdd(aZipName,Buf,Size); // write stored data and inc(Count) end; end; procedure TZipWriteAbstract.AddFromZip(Source: TZipRead; EntryIndex: integer); var s: ^TZipEntry; origZipName: TFileName; begin if (self=nil) or (Source=nil) then exit; if Count>=length(Entry) then SetLength(Entry,length(Entry)+20); with Entry[Count] do if Source.RetrieveFileInfo(EntryIndex, fhr.FileInfo) then begin s := @Source.Entry[EntryIndex]; // backslash in s^.storedName are replaced to '\' by TZipRead.Create, // accoding to ZIP file format "All slashes MUST be forward slashes '/' as opposed to // backwards slashes '\'" SetString(origZipName,s^.storedName,s^.infoLocal.nameLen); InternalAdd(origZipName,s^.data,fhr.fileInfo.zzipSize); end; end; procedure TZipWriteAbstract.Append(const Content: ZipString); begin if (self=nil) or (fAppendOffset<>0) then exit; fAppendOffset := length(Content); InternalWrite(pointer(Content)^,fAppendOffset); end; destructor TZipWriteAbstract.Destroy; var lhr: TLastHeader; i: integer; begin fillchar(lhr,sizeof(lhr),0); lhr.signature := LASTHEADER_SIGNATURE_INC; dec(lhr.signature); // +1 to avoid finding it in the exe lhr.thisFiles := Count; lhr.totalFiles := Count; lhr.headerOffset := InternalWritePosition-fAppendOffset; for i := 0 to Count-1 do with Entry[i] do begin assert(fhr.fileInfo.nameLen=length(intName)); inc(lhr.headerSize,sizeof(TFileHeader)+fhr.fileInfo.nameLen); InternalWrite(fhr,sizeof(fhr)); InternalWrite(pointer(IntName)^,fhr.fileInfo.nameLen); end; InternalWrite(lhr,sizeof(lhr)); inherited Destroy; end; { TZipWrite } function TZipWrite.InternalWritePosition: cardinal; begin result := SetFilePointer(Handle,0,nil,{$ifdef Linux}SEEK_CUR{$else}FILE_CURRENT{$endif}); end; procedure TZipWrite.InternalWrite(const buf; len: cardinal); begin FileWrite(Handle,buf,len); end; procedure TZipWrite.AddFolder(const FolderName: TFileName; const Mask: TFileName; Recursive: boolean; CompressLevel: integer); procedure RecursiveAdd(const fileDir,zipDir: TFileName); var f: TSearchRec; begin if Recursive then if FindFirst(fileDir+ZIP_FILES_ALL,faDirectory,f)=0 then begin repeat if f.Name[1]<>'.' then RecursiveAdd(fileDir+f.Name+PathDelim,zipDir+f.Name+'\'); until FindNext(f)<>0; FindClose(f); end; if FindFirst(fileDir+Mask,faAnyfile-faDirectory,f)=0 then begin repeat if f.Name[1]<>'.' then {$ifndef DELPHI5OROLDER} {$WARN SYMBOL_DEPRECATED OFF} // for faVolumeID {$endif} if f.Attr and (faDirectory+faVolumeID+faSysFile+faHidden)=0 then AddDeflated(fileDir+f.Name,false,CompressLevel,zipDir+f.Name) {$ifndef DELPHI5OROLDER} {$WARN SYMBOL_DEPRECATED ON} {$endif} until FindNext(f)<>0; FindClose(f); end; end; begin RecursiveAdd(IncludeTrailingPathDelimiter(FolderName),''); end; procedure TZipWrite.AddDeflated(const aFileName: TFileName; RemovePath: boolean=true; CompressLevel: integer=6; ZipName: TFileName=''); var {$ifdef MSWINDOWS} Time: TFileTime; FileTime: LongRec; {$endif} Size: Int64; Size64: Int64Rec absolute Size; OffsHead, OffsEnd: cardinal; S: TFileStream; D: THandleStream; Z: TSynZipCompressor; begin S := TFileStream.Create(aFileName,fmOpenRead or fmShareDenyNone); try if ZipName='' then if RemovePath then ZipName := ExtractFileName(aFileName) else {$ifdef MSWINDOWS} ZipName := aFileName; GetFileTime(S.Handle,nil,nil,@Time); FileTimeToLocalFileTime(Time,Time); FileTimeToDosDateTime(Time,FileTime.Hi,FileTime.Lo); {$else} ZipName := StringReplace(aFileName,'/','\',[rfReplaceAll]); {$endif} Size := S.Size; if Size64.Hi<>0 then raise ESynZipException.CreateFmt('%s file too big for .zip',[aFileName]); if Count>=length(Entry) then SetLength(Entry,length(Entry)+20); OffsHead := InternalAdd(ZipName,nil,0); // write data and inc(Count) D := THandleStream.Create(Handle); Z := TSynZipCompressor.Create(D,CompressLevel); try Z.CopyFrom(S,Size64.Lo); Z.Flush; assert(Z.SizeIn=Size64.Lo); with Entry[Count] do begin with fhr.fileInfo do begin zcrc32 := Z.CRC; zfullSize := Z.SizeIn; zzipSize := Z.SizeOut; zzipMethod := Z_DEFLATED; {$ifdef MSWINDOWS} zlastMod := integer(FileTime); {$else} zlastMod := FileAge(ZipName); {$endif} end; OffsEnd := D.Position; D.Position := OffsHead+sizeof(fMagic); D.WriteBuffer(fhr.fileInfo,sizeof(fhr.fileInfo)); D.Position := OffsEnd; end; inc(Count); finally Z.Free; D.Free; end; finally S.Free; end; end; constructor TZipWrite.Create(const aFileName: TFileName); begin Create; fFileName := aFileName; if Handle=0 then Handle := FileCreate(aFileName); end; constructor TZipWrite.CreateFrom(const aFileName: TFileName; dummy: integer); var R: TZipRead; i: Integer; begin Handle := FileOpen(aFileName,fmOpenReadWrite or fmShareDenyNone); if Handle<0 then begin R := nil; Handle := 0; end else R := TZipRead.Create(Handle); Create(aFileName); if R<>nil then try Count := R.Count; SetLength(Entry,Count+10); for i := 0 to Count-1 do with Entry[i], R.Entry[i] do begin fhr.Init; fhr.localHeadOff := ZipPtrUint(infoLocal)-ZipPtrUint(R.Entry[0].infoLocal); R.RetrieveFileInfo(i,fhr.fileInfo); SetString(intName,storedName,infoLocal^.nameLen); end; {$ifdef MSWINDOWS} SetFilePointer(Handle,R.ReadOffset,nil,FILE_BEGIN); {$else} FileSeek(Handle,R.ReadOffset,soFromBeginning); {$endif} finally R.Free; end; end; destructor TZipWrite.Destroy; begin inherited Destroy; // will write TLastHeader content SetEndOfFile(Handle); FileClose(Handle); end; { TZipWriteToStream } constructor TZipWriteToStream.Create(aDest: TStream); begin fDest := aDest; inherited Create; end; function TZipWriteToStream.InternalWritePosition: cardinal; begin result := fDest.Seek(0,soCurrent); end; procedure TZipWriteToStream.InternalWrite(const buf; len: cardinal); begin fDest.WriteBuffer(buf,len); end; { TZipRead } procedure TZipRead.UnMap; begin Count := 0; {$ifdef MSWINDOWS} if map<>0 then begin UnmapViewOfFile(Buf); CloseHandle(map); map := 0; end; {$else} if (mapSize<>0) and (buf<>nil) then begin {$ifdef KYLIX3}munmap{$else}fpmunmap{$endif}(buf,mapSize); mapSize := 0; end; {$endif MSWINDOWS} if file_>0 then begin FileClose(file_); file_ := 0; end; end; {$ifdef UNICODE} function UTF8Decode(const tmp: UTF8String): TFileName; begin result := TFileName(tmp); end; {$endif} constructor TZipRead.Create(BufZip: PByteArray; Size: cardinal); var lhr: PLastHeader; H: PFileHeader; lfhr: PLocalFileHeader; i,j: integer; {$ifndef DELPHI5OROLDER} tmp: UTF8String; {$else} tmp: ZipString; {$endif} begin for i := 0 to 127 do begin // resources size may be rounded up to alignment lhr := @BufZip[Size-sizeof(TLastHeader)]; if lhr^.signature+1=LASTHEADER_SIGNATURE_INC then break; dec(Size); if Size<=sizeof(lhr^) then break; end; if lhr^.signature+1<>LASTHEADER_SIGNATURE_INC then begin UnMap; raise ESynZipException.Create('ZIP format'); end; SetLength(Entry,lhr^.totalFiles); // fill Entry[] with the Zip headers ReadOffset := lhr^.headerOffset; FirstFileHeader := @BufZip[lhr^.headerOffset]; H := FirstFileHeader; for i := 1 to lhr^.totalFiles do begin if H^.signature+1<>ENTRY_SIGNATURE_INC then begin // +1 to avoid match in exe UnMap; raise ESynZipException.Create('ZIP format'); end; lfhr := @BufZip[H^.localHeadOff]; with lfhr^.fileInfo do if flags and (1 shl 3)<>0 then begin // crc+sizes in "data descriptor" if (zcrc32<>0) or (zzipSize<>0) or (zfullSize<>0) then raise ESynZipException.Create('ZIP extended format'); // UnZip() will call RetrieveFileInfo() end else if (zzipSize=cardinal(-1)) or (zfullSize=cardinal(-1)) then raise ESynZipException.Create('ZIP64 format not supported - use mORMot 2'); with Entry[Count] do begin infoLocal := @lfhr^.fileInfo; infoDirectory := H; storedName := PAnsiChar(lfhr)+sizeof(lfhr^); data := storedName+infoLocal^.NameLen+infoLocal^.extraLen; // data mapped in memory SetString(tmp,storedName,infoLocal^.nameLen); for j := 0 to infoLocal^.nameLen-1 do if storedName[j]='/' then // normalize path delimiter PAnsiChar(Pointer(tmp))[j] := '\'; {$ifndef DELPHI5OROLDER} // Delphi 5 lacks UTF-8 functions -> 7 bit if infoLocal^.GetUTF8FileName then // decode UTF-8 file name into native string/TFileName type zipName := TFileName(UTF8Decode(tmp)) else {$endif DELPHI5OROLDER} begin {$ifdef MSWINDOWS} // decode OEM/DOS file name into native encoding SetLength(zipName,infoLocal^.nameLen); OemToChar(Pointer(tmp),Pointer(zipName)); // OemToCharW/OemToCharA {$else} zipName := TFileName(UTF8Decode(tmp)); // let's assume UTF-8 under Linux {$endif MSWINDOWS} end; inc(PByte(H),sizeof(H^)+infoLocal^.NameLen+H^.fileInfo.extraLen+H^.commentLen); if not(infoLocal^.zZipMethod in [Z_STORED,Z_DEFLATED]) then raise ESynZipException.CreateFmt( 'Unsupported compression method %d for %s',[infoLocal^.zZipMethod,zipName]); if (zipName='') or (zipName[length(zipName)]='\') then continue; // ignore folder inc(Count); // add file to Entry[] end; end; end; constructor TZipRead.Create(Instance: THandle; const ResName: string; ResType: PChar); // locked resources are memory map of the executable -> direct access is easy var HResInfo: THandle; HGlobal: THandle; begin if Instance=0 then Instance := HInstance; HResInfo := FindResource(Instance,PChar(ResName),ResType); if HResInfo=0 then exit; HGlobal := LoadResource(Instance, HResInfo); if HGlobal<>0 then // warning: resources size may be rounded up to alignment -> handled in Create() Create(LockResource(HGlobal),SizeofResource(Instance, HResInfo)); end; constructor TZipRead.Create(aFile: THandle; ZipStartOffset,Size: cardinal); var i, ExeOffset: integer; begin if aFile<=0 then exit; if Size=0 then Size := GetFileSize(aFile, nil); {$ifdef MSWINDOWS} map := CreateFileMapping(aFile, nil, PAGE_READONLY, 0, 0, nil); if map=0 then begin Unmap; raise ESynZipException.Create('Missing File'); end; buf := MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0); {$else} mapSize := Size; buf := {$ifdef KYLIX3}mmap{$else}fpmmap{$endif}(nil,Size,PROT_READ,MAP_SHARED,aFile,0); if buf=MAP_FAILED then buf := nil; {$endif} if buf=nil then begin Unmap; raise ESynZipException.Create('FileMap failed'); end; ExeOffset := -1; for i := ZipStartOffset to Size-5 do // search for first local header if PCardinal(@buf[i])^+1=FIRSTHEADER_SIGNATURE_INC then begin // +1 above to avoid finding it in the exe part ExeOffset := i; break; end; if ExeOffset<0 then // try if adding files to an empty archive for i := ZipStartOffset to Size-5 do if PCardinal(@buf[i])^+1=LASTHEADER_SIGNATURE_INC then begin // +1 avoids false positive ExeOffset := i; break; end; if ExeOffset<0 then begin Unmap; raise ESynZipException.Create('No ZIP header found'); end; Create(@Buf[ExeOffset],integer(Size)-ExeOffset); end; constructor TZipRead.Create(const aFileName: TFileName; ZipStartOffset, Size: cardinal); begin {$ifdef MSWINDOWS} file_ := CreateFile(pointer(aFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); {$else} file_ := FileOpen(aFileName,fmOpenRead or fmShareDenyNone); {$endif} Create(file_,ZipStartOffset, Size); end; destructor TZipRead.Destroy; begin UnMap; inherited Destroy; end; function TZipRead.NameToIndex(const aName: TFileName): integer; begin if (self<>nil) and (aName<>'') then for result := 0 to Count-1 do if SameText(Entry[result].zipName,aName) then exit; result := -1; end; type TDataDescriptor = packed record signature: dword; crc32: dword; zipSize: dword; fullSize: dword; end; function TZipRead.RetrieveFileInfo(Index: integer; var Info: TFileInfo): boolean; var P: ^TDataDescriptor; PDataStart: ZipPtrUint; begin if (self=nil) or (cardinal(Index)>=cardinal(Count)) then begin result := false; exit; end; // copy information from "local file header" Info := Entry[Index].infoLocal^; if Info.flags and (1 shl 3)=0 then begin result := true; // local information is correct exit; end; // get info from ending "central directory" (faster than "data descriptor") with Entry[Index].infoDirectory^.fileInfo do if (zzipSize<>dword(-1)) and (zfullSize<>dword(-1)) then begin // ZIP64 format not supported yet (sizes=-1) Info.zcrc32 := zcrc32; Info.zzipSize := zzipSize; Info.zfullSize := zfullSize; result := true; exit; end; // search manually the "data descriptor" from the binary local data if Index$08074b50 then if ZipPtrUint(P)>PDataStart then dec(PByte(P)) else break else if P^.zipSize=ZipPtrUint(P)-PDataStart then begin if (P^.zipSize=0) or (P^.fullSize=0) or (P^.zipSize=dword(-1)) or (P^.fullSize=dword(-1)) then break; // we expect sizes to be there! Info.zcrc32 := P^.crc32; Info.zzipSize := P^.zipSize; Info.zfullSize := P^.fullSize; result := true; exit; end else if ZipPtrUint(P)>PDataStart then dec(PByte(P)) else break; until false; result := false; // data descriptor block not found end; function TZipRead.UnZip(aIndex: integer): ZipString; var len: cardinal; info: TFileInfo; begin result := ''; // somewhat faster if memory is reallocated each time if not RetrieveFileInfo(aIndex,info) then exit; SetString(result,nil,info.zfullSize); case info.zZipMethod of Z_STORED: begin len := info.zfullsize; move(Entry[aIndex].data^,pointer(result)^,len); end; Z_DEFLATED: len := UnCompressMem(Entry[aIndex].data,pointer(result),info.zzipsize,info.zfullsize); else raise ESynZipException.CreateFmt('Unsupported method %d for %s', [info.zZipMethod,Entry[aIndex].zipName]); end; if (len<>info.zfullsize) or (info.zcrc32<>SynZip.crc32(0,pointer(result),info.zfullSize)) then raise ESynZipException.CreateFmt('Error decompressing %s',[Entry[aIndex].zipName]); end; {$ifdef DELPHI5OROLDER} /// DirectoryExists returns a boolean value that indicates whether the // specified directory exists (and is actually a directory) function DirectoryExists(const Directory: string): boolean; var res: Integer; begin res := GetFileAttributes(PChar(Directory)); result := (res<>-1) and (FILE_ATTRIBUTE_DIRECTORY and res<> 0); end; {$endif} function EnsurePath(var Path: TFileName): boolean; var Parent: TFileName; begin result := false; if Path='' then exit; {$IFDEF FPC} Path := IncludeTrailingPathDelimiter(SetDirSeparators(Path)); {$ELSE} // We assume Delphi for Windows here if Path[length(Path)]<>'\' then Path := Path+'\'; {$ENDIF} if DirectoryExists(Path) then result := true else begin Parent := ExtractFilePath(system.copy(Path,1,length(Path)-1)); if (Parent<>'') and not DirectoryExists(Parent) then if not EnsurePath(Parent) then exit; if CreateDir(path) then result := true; end; end; function TZipRead.UnZipStream(aIndex: integer; const aInfo: TFileInfo; aDest: TStream): boolean; var crc: cardinal; begin result := false; case aInfo.zZipMethod of Z_STORED: begin aDest.WriteBuffer(Entry[aIndex].data^,aInfo.zfullsize); crc := SynZip.crc32(0,Entry[aIndex].data,aInfo.zfullSize); end; Z_DEFLATED: if UnCompressStream(Entry[aIndex].data,aInfo.zzipsize,aDest,@crc)<>aInfo.zfullsize then exit; else raise ESynZipException.CreateFmt('Unsupported method %d for %s', [aInfo.zZipMethod,Entry[aIndex].zipName]); end; result := crc=aInfo.zcrc32; end; function TZipRead.UnZip(aIndex: integer; aDest: TStream): boolean; var info: TFileInfo; begin if not RetrieveFileInfo(aIndex,info) then result := false else result := UnZipStream(aIndex,info,aDest); end; function TZipRead.UnZip(aIndex: integer; const DestDir: TFileName; DestDirIsFileName: boolean): boolean; var FS: TFileStream; Path: TFileName; info: TFileInfo; begin result := false; if not RetrieveFileInfo(aIndex,info) then exit; with Entry[aIndex] do if DestDirIsFileName then Path := DestDir else begin Path := DestDir+ExtractFilePath(zipName); // include sub directories if not EnsurePath(Path) then exit; Path := Path+ExtractFileName(zipName); end; FS := TFileStream.Create(Path,fmCreate); try result := UnZipStream(aIndex,info,FS); {$ifdef MSWINDOWS} {$ifdef CONDITIONALEXPRESSIONS} {$WARN SYMBOL_PLATFORM OFF} // zip expects a Windows timestamp {$endif} if result and (info.zlastMod<>0) then FileSetDate(FS.Handle,info.zlastMod); {$ifdef CONDITIONALEXPRESSIONS} {$WARN SYMBOL_PLATFORM ON} {$endif} {$endif MSWINDOWS} finally FS.Free; end; end; function TZipRead.UnZipAll(DestDir: TFileName): integer; begin if DestDir<>'' then {$ifdef DELPHI5OROLDER} DestDir := IncludeTrailingBackslash(DestDir); {$else} DestDir := IncludeTrailingPathDelimiter(DestDir); {$endif} for result := 0 to Count-1 do if not UnZip(result,DestDir) then exit; result := -1; end; function TZipRead.UnZip(const aName, DestDir: TFileName; DestDirIsFileName: boolean): boolean; var aIndex: integer; begin aIndex := NameToIndex(aName); if aIndex<0 then result := false else result := UnZip(aIndex,DestDir,DestDirIsFileName); end; function TZipRead.UnZip(const aName: TFileName): ZipString; var aIndex: integer; begin aIndex := NameToIndex(aName); if aIndex<0 then result := '' else result := UnZip(aIndex); end; const GZHEAD: array [0..2] of cardinal = ($088B1F,0,0); GZHEAD_SIZE = 10; type TGZFlags = set of (gzfText, gzfHCRC, gzfExtra, gzfName, gzfComment); { TGZRead } function TGZRead.Init(gz: PAnsiChar; gzLen: ZipPtrInt): boolean; var offset: ZipPtrInt; flags: TGZFlags; begin // see https://www.ietf.org/rfc/rfc1952.txt comp := nil; complen := 0; uncomplen32 := 0; zsdest := nil; result := false; extra := nil; fname := nil; fcomment := nil; if (gz=nil) or (gzLen<=18) or (PCardinal(gz)^ and $ffffff<>GZHEAD[0]) then exit; // .gz file as header + compressed + crc32 + len32 format flags := TGZFlags(gz[3]); unixmodtime := PCardinal(gz+4)^; offset := GZHEAD_SIZE; if gzfExtra in flags then begin extra := gz+offset; inc(offset,PWord(extra)^+SizeOf(word)); end; if gzfName in flags then begin // FNAME flag (as created e.g. by 7Zip) fname := gz+offset; while (offset#0) do inc(offset); inc(offset); end; if gzfComment in flags then begin fcomment := gz+offset; while (offset#0) do inc(offset); inc(offset); end; if gzfHCRC in flags then if PWord(gz+offset)^<>SynZip.crc32(0,gz,offset) and $ffff then exit else inc(offset,SizeOf(word)); if offset>=gzlen-8 then exit; uncomplen32 := PCardinal(@gz[gzLen-4])^; // modulo 2^32 by design (may be 0) comp := gz+offset; complen := gzLen-offset-8; crc32 := PCardinal(@gz[gzLen-8])^; result := true; end; function TGZRead.ToMem: ZipString; begin result := ''; if (comp=nil) or ((uncomplen32=0) and (crc32=0){0 length stream}) then exit; SetLength(result,uncomplen32); if (UnCompressMem(comp,pointer(result),complen,uncomplen32)<>integer(uncomplen32)) or (SynZip.crc32(0,pointer(result),uncomplen32)<>crc32) then result := ''; // invalid CRC end; function TGZRead.ToStream(stream: TStream; tempBufSize: integer): boolean; var crc: cardinal; begin crc := 0; result := (comp<>nil) and (stream<>nil) and (UnCompressStream(comp,complen,stream,@crc,{zlib=}false,tempBufSize)=uncomplen32) and (crc=crc32); end; function TGZRead.ToFile(const filename: TFileName; tempBufSize: integer): boolean; var f: TStream; begin result := false; if (comp=nil) or (filename='') then exit; f := TFileStream.Create(filename,fmCreate); try result := ToStream(f,tempBufSize); finally f.Free; end; end; function TGZRead.ZStreamStart(dest: pointer; destsize: integer): boolean; begin result := false; zscode := Z_STREAM_ERROR; if (comp=nil) or (dest=nil) or (destsize<=0) then exit; StreamInit(zs); zs.next_in := comp; zs.avail_in := complen; zs.next_out := dest; zs.avail_out := destsize; zscode := inflateInit2_(zs, -MAX_WBITS, ZLIB_VERSION, sizeof(zs)); if zscode>=0 then begin zscrc := 0; zsdest := dest; zssize := destsize; result := true; end; end; function TGZRead.ZStreamStarted: boolean; begin result := zsdest<>nil; end; function TGZRead.ZStreamNext: integer; begin result := 0; if (comp=nil) or (zsdest=nil) or not ((zscode=Z_OK) or (zscode=Z_STREAM_END) or (zscode=Z_BUF_ERROR)) then exit; if zscode<>Z_STREAM_END then begin zscode := Check(inflate(zs, Z_FINISH),[Z_OK,Z_STREAM_END,Z_BUF_ERROR],'ZStreamNext'); result := zssize-integer(zs.avail_out); if result=0 then exit; zscrc := SynZip.crc32(zscrc,zsdest,result); zs.next_out := zsdest; zs.avail_out := zssize; end; end; function TGZRead.ZStreamDone: boolean; begin result := false; if (comp<>nil) and (zsdest<>nil) then begin inflateEnd(zs); zsdest := nil; result := (zscrc=crc32) and (cardinal(zs.total_out)=uncomplen32); end; end; function GZRead(gz: PAnsiChar; gzLen: integer): ZipString; var gzr: TGZRead; begin if gzr.Init(gz,gzlen) then result := gzr.ToMem else result := ''; end; function GZFile(const orig, destgz: TFileName; CompressionLevel: Integer=6): boolean; var gz: TSynZipCompressor; s,d: TFileStream; begin try s := TFileStream.Create(orig,fmOpenRead or fmShareDenyNone); try d := TFileStream.Create(destgz,fmCreate); try gz := TSynZipCompressor.Create(d,CompressionLevel,szcfGZ); try gz.CopyFrom(s,0); // Count=0 for whole stream copy result := true; finally gz.Free; end; finally d.Free; end; finally s.Free; end; except result := false; end; end; {$ifdef USEEXTZLIB} function deflate(var strm: TZStream; flush: integer): integer; cdecl; external libz name 'deflate'; function deflateEnd(var strm: TZStream): integer; cdecl; external libz name 'deflateEnd'; function inflate(var strm: TZStream; flush: integer): integer; cdecl; external libz name 'inflate'; function inflateEnd(var strm: TZStream): integer; cdecl; external libz name 'inflateEnd'; function adler32(adler: TZCRC; buf: PAnsiChar; len: cardinal): TZCRC; cdecl; external libz name 'adler32'; function crc32(crc: TZCRC; buf: PAnsiChar; len: cardinal): TZCRC; cdecl; external libz name 'crc32'; function deflateInit_(var strm: TZStream; level: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; external libz name 'deflateInit_'; function inflateInit_(var strm: TZStream; version: PAnsiChar; stream_size: integer): integer; cdecl; external libz name 'inflateInit_'; function deflateInit2_(var strm: TZStream; level, method, windowBits, memLevel, strategy: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; external libz name 'deflateInit2_'; function inflateInit2_(var strm: TZStream; windowBits: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; external libz name 'inflateInit2_'; function get_crc_table: pointer; cdecl; external libz name 'get_crc_table'; {$else USEEXTZLIB} {$ifdef USEPASZLIB} function adler32(adler: cardinal; buf: PAnsiChar; len: cardinal): cardinal; begin result := paszlib.adler32(adler,pointer(buf),len); end; function crc32(crc: cardinal; buf: PAnsiChar; len: cardinal): cardinal; begin result := paszlib.crc32(crc,pointer(buf),len); end; function deflateInit2_(var strm: TZStream; level: integer; method: integer; windowBits: integer; memLevel: integer;strategy: integer; version: PAnsiChar; stream_size: integer): integer; begin result := paszlib.deflateInit2_(strm,level,method,windowBits,memLevel,strategy,version,stream_size); end; function deflate(var strm: TZStream; flush: integer): integer; begin result := paszlib.deflate(strm,flush); end; function deflateEnd(var strm: TZStream): integer; begin result := paszlib.deflateEnd(strm); end; function inflateInit2_(var strm: TZStream; windowBits: integer; version: PAnsiChar; stream_size: integer): integer; begin result := paszlib.inflateInit2_(strm,windowBits,version,stream_size); end; function inflate(var strm: TZStream; flush: integer): integer; begin result := paszlib.inflate(strm,flush); end; function inflateEnd(var strm: TZStream): integer; begin result := paszlib.inflateEnd(strm); end; function get_crc_table: pointer; begin result := paszlib.get_crc_table; end; {$else USEPASZLIB} {$ifdef USEINLINEASM} // some small functions (adler32.obj, zutil.obj, compress.obj, uncompress.obj, // crc32.obj) are coded directly in this unit, not as external .obj files // this external obj code was compiled with pascal register call conventions {$LINK deflate.obj} {$LINK trees.obj} function deflateInit2_(var strm: TZStream; level: integer; method: integer; windowBits: integer; memLevel: integer;strategy: integer; version: PAnsiChar; stream_size: integer): integer; external; function deflate(var strm: TZStream; flush: integer): integer; external; function deflateEnd(var strm: TZStream): integer; external; const _z_errmsg: array[0..9] of PAnsiChar = ( 'need dictionary', // Z_NEED_DICT 2 'stream end', // Z_STREAM_END 1 '', // Z_OK 0 'file error', // Z_ERRNO (-1) 'stream error', // Z_STREAM_ERROR (-2) 'data error', // Z_DATA_ERROR (-3) 'insufficient memory', // Z_MEM_ERROR (-4) 'buffer error', // Z_BUF_ERROR (-5) 'incompatible version',// Z_VERSION_ERROR (-6) ''); Err246: array[0..3] of AnsiChar = 'lit'; Err247: array[0..3] of AnsiChar = 'dst'; Err248: array[0..3] of AnsiChar = 'inv'; procedure Inline018; asm sub esp, 60 push ebx push ebp push esi push edi mov eax, dword ptr [esp + 50H] mov edx, dword ptr [eax] mov ecx, dword ptr [eax + 04H] mov ebx, dword ptr [esp + 54H] dec edx lea ecx, [ecx + edx - 05H] mov ebp, dword ptr [eax + 1CH] mov dword ptr [esp + 30H], ecx mov esi, dword ptr [eax + 0CH] mov eax, dword ptr [eax + 10H] mov ecx, eax sub ecx, ebx dec esi lea eax, [eax + esi - 00000101H] add ecx, esi mov dword ptr [esp + 34H], eax mov eax, dword ptr [ebp + 2CH] mov dword ptr [esp + 44H], ecx mov ecx, dword ptr [ebp + 28H] mov dword ptr [esp + 48H], eax mov eax, dword ptr [ebp + 34H] mov ebx, dword ptr [ebp + 3CH] mov dword ptr [esp + 28H], ecx mov ecx, dword ptr [ebp + 30H] mov dword ptr [esp + 2CH], eax mov eax, dword ptr [ebp + 50H] mov dword ptr [esp + 1CH], ecx mov ecx, dword ptr [ebp + 4CH] mov dword ptr [esp + 24H], eax mov dword ptr [esp + 20H], ecx mov ecx, dword ptr [ebp + 54H] mov eax, 1 shl eax, cl mov ecx, dword ptr [ebp + 58H] mov edi, dword ptr [ebp + 38H] dec eax mov dword ptr [esp + 38H], eax mov eax, 1 shl eax, cl mov dword ptr [esp + 18H], ebp mov dword ptr [esp + 14H], edx dec eax mov dword ptr [esp + 3CH], eax @@019: cmp ebx, 15 jnc @@020 movzx eax, byte ptr [edx + 01H] inc edx mov ecx, ebx shl eax, cl add ebx, 8 mov ecx, ebx add edi, eax movzx eax, byte ptr [edx + 01H] inc edx shl eax, cl mov dword ptr [esp + 14H], edx add edi, eax add ebx, 8 @@020: mov ecx, dword ptr [esp + 38H] mov eax, dword ptr [esp + 20H] and ecx, edi mov eax, dword ptr [eax + ecx*4] movzx ecx, ah mov dword ptr [esp + 10H], eax movzx eax, al shr edi, cl sub ebx, ecx test eax, eax jz @@022 @@021: test al, 10H jnz @@023 test al, 40H jne @@046 mov ecx, 1 mov dword ptr [esp + 54H], ecx mov ecx, eax mov eax, dword ptr [esp + 54H] shl eax, cl mov ecx, dword ptr [esp + 10H] shr ecx, 16 dec eax and eax, edi add eax, ecx mov ecx, dword ptr [esp + 20H] mov eax, dword ptr [ecx + eax*4] movzx ecx, ah mov dword ptr [esp + 10H], eax movzx eax, al shr edi, cl sub ebx, ecx test eax, eax jnz @@021 @@022: mov eax, dword ptr [esp + 10H] inc esi shr eax, 16 mov byte ptr [esi], al jmp @@043 @@023: mov ecx, dword ptr [esp + 10H] shr ecx, 16 and eax, 0000000FH mov dword ptr [esp + 54H], ecx jz @@025 cmp ebx, eax jnc @@024 movzx ebp, byte ptr [edx + 01H] inc edx mov ecx, ebx shl ebp, cl mov dword ptr [esp + 14H], edx add edi, ebp add ebx, 8 @@024: mov ecx, eax mov ebp, 1 shl ebp, cl mov ecx, dword ptr [esp + 54H] dec ebp and ebp, edi add ecx, ebp mov ebp, dword ptr [esp + 18H] mov dword ptr [esp + 54H], ecx mov ecx, eax shr edi, cl sub ebx, eax @@025: cmp ebx, 15 jnc @@026 movzx eax, byte ptr [edx + 01H] inc edx mov ecx, ebx shl eax, cl add ebx, 8 mov ecx, ebx add edi, eax movzx eax, byte ptr [edx + 01H] inc edx shl eax, cl mov dword ptr [esp + 14H], edx add edi, eax add ebx, 8 @@026: mov ecx, dword ptr [esp + 3CH] mov eax, dword ptr [esp + 24H] and ecx, edi mov eax, dword ptr [eax + ecx*4] movzx ecx, ah mov dword ptr [esp + 10H], eax movzx eax, al shr edi, cl sub ebx, ecx test al, 10H jnz @@028 @@027: test al, 40H jne @@045 mov ecx, 1 mov dword ptr [esp + 40H], ecx mov ecx, eax mov eax, dword ptr [esp + 40H] shl eax, cl mov ecx, dword ptr [esp + 10H] shr ecx, 16 dec eax and eax, edi add eax, ecx mov ecx, dword ptr [esp + 24H] mov eax, dword ptr [ecx + eax*4] movzx ecx, ah mov dword ptr [esp + 10H], eax movzx eax, al shr edi, cl sub ebx, ecx test al, 10H jz @@027 @@028: mov ecx, dword ptr [esp + 10H] shr ecx, 16 and eax, 0000000FH cmp ebx, eax mov dword ptr [esp + 10H], ecx jnc @@029 movzx ebp, byte ptr [edx + 01H] inc edx mov ecx, ebx shl ebp, cl add ebx, 8 mov dword ptr [esp + 14H], edx add edi, ebp cmp ebx, eax jnc @@029 movzx ebp, byte ptr [edx + 01H] inc edx mov ecx, ebx shl ebp, cl mov dword ptr [esp + 14H], edx add edi, ebp add ebx, 8 @@029: mov ecx, 1 mov ebp, ecx mov ecx, eax shl ebp, cl sub ebx, eax dec ebp and ebp, edi mov ecx, ebp mov ebp, dword ptr [esp + 10H] add ebp, ecx mov ecx, eax shr edi, cl mov ecx, dword ptr [esp + 44H] mov eax, esi sub eax, ecx cmp ebp, eax mov dword ptr [esp + 10H], ebp jbe @@040 sub ebp, eax cmp ebp, dword ptr [esp + 48H] ja @@044 mov ecx, dword ptr [esp + 2CH] mov eax, dword ptr [esp + 1CH] dec ecx test eax, eax jnz @@031 mov eax, dword ptr [esp + 28H] sub eax, ebp add ecx, eax mov eax, dword ptr [esp + 54H] cmp ebp, eax jae @@037 sub eax, ebp mov dword ptr [esp + 54H], eax @@030: mov al, byte ptr [ecx + 01H] inc ecx inc esi dec ebp mov byte ptr [esi], al jnz @@030 jmp @@036 @@031: cmp eax, ebp jnc @@034 sub eax, ebp add eax, dword ptr [esp + 28H] add ecx, eax sub ebp, dword ptr [esp + 1CH] mov eax, dword ptr [esp + 54H] cmp ebp, eax jnc @@037 sub eax, ebp mov dword ptr [esp + 54H], eax @@032: mov al, byte ptr [ecx + 01H] inc ecx inc esi dec ebp mov byte ptr [esi], al jnz @@032 mov ecx, dword ptr [esp + 2CH] mov eax, dword ptr [esp + 1CH] mov ebp, dword ptr [esp + 54H] dec ecx cmp eax, ebp jnc @@037 sub ebp, eax mov dword ptr [esp + 54H], ebp mov dword ptr [esp + 40H], eax mov ebp, eax @@033: mov al, byte ptr [ecx + 01H] inc ecx inc esi dec ebp mov byte ptr [esi], al jnz @@033 jmp @@036 @@034: sub eax, ebp add ecx, eax mov eax, dword ptr [esp + 54H] cmp ebp, eax jnc @@037 sub eax, ebp mov dword ptr [esp + 54H], eax @@035: mov al, byte ptr [ecx + 01H] inc ecx inc esi dec ebp mov byte ptr [esi], al jnz @@035 @@036: mov eax, dword ptr [esp + 10H] mov ecx, esi sub ecx, eax @@037: mov eax, dword ptr [esp + 54H] cmp eax, 2 jbe @@039 lea edx, [eax - 03H] mov eax, -1431655765 mul edx mov ebp, edx shr ebp, 1 inc ebp nop @@038: mov al, byte ptr [ecx + 01H] inc ecx inc esi mov byte ptr [esi], al mov dl, byte ptr [ecx + 01H] inc ecx inc esi mov byte ptr [esi], dl mov edx, dword ptr [esp + 54H] mov al, byte ptr [ecx + 01H] inc ecx inc esi sub edx, 3 dec ebp mov byte ptr [esi], al mov dword ptr [esp + 54H], edx jnz @@038 mov edx, dword ptr [esp + 14H] @@039: mov eax, dword ptr [esp + 54H] test eax, eax jz @@042 mov al, byte ptr [ecx + 01H] inc ecx inc esi mov byte ptr [esi], al cmp dword ptr [esp + 54H], 1 jbe @@042 mov cl, byte ptr [ecx + 01H] inc esi mov byte ptr [esi], cl jmp @@042 @@040: mov eax, esi sub eax, ebp @@041: mov cl, byte ptr [eax + 01H] inc eax inc esi mov byte ptr [esi], cl mov cl, byte ptr [eax + 01H] inc eax inc esi mov byte ptr [esi], cl mov cl, byte ptr [eax + 01H] inc eax inc esi mov byte ptr [esi], cl mov ecx, dword ptr [esp + 54H] sub ecx, 3 cmp ecx, 2 mov dword ptr [esp + 54H], ecx ja @@041 test ecx, ecx jz @@042 mov cl, byte ptr [eax + 01H] inc eax inc esi mov byte ptr [esi], cl cmp dword ptr [esp + 54H], 1 jbe @@042 mov al, byte ptr [eax + 01H] inc esi mov byte ptr [esi], al @@042: mov ebp, dword ptr [esp + 18H] @@043: cmp edx, dword ptr [esp + 30H] jnc @@049 cmp esi, dword ptr [esp + 34H] jb @@019 jmp @@049 @@044: mov ecx, dword ptr [esp + 50H] mov eax, dword ptr [esp + 18H] mov dword ptr [ecx + 18H],offset Err248 mov dword ptr [eax], 27 mov ebp, eax jmp @@049 @@045: mov ecx, dword ptr [esp + 50H] mov dword ptr [ecx + 18H], offset Err247 jmp @@048 @@046: test al, 20H jz @@047 mov dword ptr [ebp], 11 jmp @@049 @@047: mov eax, dword ptr [esp + 50H] mov dword ptr [eax + 18H], offset Err246 @@048: mov dword ptr [ebp], 27 @@049: mov eax, ebx shr eax, 3 lea ecx, [eax*8] sub edx, eax sub ebx, ecx mov ecx, ebx mov eax, 1 shl eax, cl mov ecx, dword ptr [esp + 50H] dec eax and edi, eax lea eax, [edx + 01H] mov dword ptr [ecx], eax lea eax, [esi + 01H] mov dword ptr [ecx + 0CH], eax mov eax, dword ptr [esp + 30H] sub eax, edx add eax, 5 mov dword ptr [ecx + 04H], eax mov eax, dword ptr [esp + 34H] sub eax, esi add eax, 257 mov dword ptr [ecx + 10H], eax mov dword ptr [ebp + 38H], edi pop edi pop esi mov dword ptr [ebp + 3CH], ebx pop ebp pop ebx add esp, 60 ret 8 end; procedure inflateReset; asm mov edx, dword ptr [esp + 04H] xor ecx, ecx cmp edx, ecx jz @@050 mov eax, dword ptr [edx + 1CH] cmp eax, ecx jz @@050 mov dword ptr [eax + 1CH], ecx mov dword ptr [edx + 14H], ecx mov dword ptr [edx + 08H], ecx mov dword ptr [edx + 18H], ecx mov dword ptr [edx + 30H], 1 mov dword ptr [eax], ecx mov dword ptr [eax + 04H], ecx mov dword ptr [eax + 0CH], ecx mov dword ptr [eax + 20H], ecx mov dword ptr [eax + 28H], ecx mov dword ptr [eax + 2CH], ecx mov dword ptr [eax + 30H], ecx mov dword ptr [eax + 38H], ecx mov dword ptr [eax + 3CH], ecx lea ecx, [eax + 00000530H] mov dword ptr [eax + 14H], 32768 mov dword ptr [eax + 6CH], ecx mov dword ptr [eax + 50H], ecx mov dword ptr [eax + 4CH], ecx xor eax, eax ret 4 @@050: mov eax, -2 ret 4 end; function zsalloc(AppData: Pointer; Items, Size: cardinal): Pointer; stdcall; begin // direct use of the (FastMM4) delphi heap for all inflate memory allocation Getmem(result,Items * Size); end; procedure zsfree(AppData, Block: Pointer); stdcall; begin // direct use of the (FastMM4) delphi heap for all inflate memory allocation FreeMem(Block); end; function inflateInit2_; asm pop ebp // auto-generated push ebp; mov ebp,esp mov eax, dword ptr [esp + 0CH] push edi xor edi, edi cmp eax, edi je @@058 cmp byte ptr [eax], 49 jne @@058 cmp dword ptr [esp + 14H], 56 jnz @@058 push esi mov esi, dword ptr [esp + 0CH] cmp esi, edi jz @@057 mov [esi].TZStream.zFree,offset zsfree mov [esi].TZStream.zAlloc,offset zsalloc mov dword ptr [esi + 18H], edi mov eax,9520 call System.@GetMem mov [esi].TZStream.State,eax mov ecx, dword ptr [esp + 10H] cmp ecx, edi jge @@054 mov dword ptr [eax + 08H], edi neg ecx jmp @@055 @@054: mov edx, ecx sar edx, 4 inc edx mov dword ptr [eax + 08H], edx @@055: cmp ecx, 8 jl @@056 cmp ecx, 15 jg @@056 push esi mov dword ptr [eax + 24H], ecx mov dword ptr [eax + 34H], edi call inflateReset pop esi pop edi ret 16 @@056: push eax mov eax, dword ptr [esi + 28H] push eax call dword ptr [esi + 24H] mov dword ptr [esi + 1CH], edi @@057: pop esi mov eax, -2 pop edi ret 16 @@058: mov eax, -6 pop edi ret 16 end; procedure Inline059; asm push ebx push ebp mov ebp, dword ptr [esp + 0CH] mov ebx, dword ptr [ebp + 1CH] push esi push edi mov esi, eax mov eax, dword ptr [ebx + 34H] xor edi, edi cmp eax, edi jnz @@060 mov ecx, dword ptr [ebx + 24H] mov eax, 1 shl eax, cl mov ecx, dword ptr [ebp + 28H] push 1 push eax push ecx call dword ptr [ebp + 20H] cmp eax, edi mov dword ptr [ebx + 34H], eax jnz @@060 pop edi pop esi pop ebp mov eax, 1 pop ebx ret 4 @@060: cmp dword ptr [ebx + 28H], edi jnz @@061 mov ecx, dword ptr [ebx + 24H] mov edx, 1 shl edx, cl mov dword ptr [ebx + 30H], edi mov dword ptr [ebx + 2CH], edi mov dword ptr [ebx + 28H], edx @@061: mov edi, dword ptr [ebp + 10H] mov ecx, dword ptr [ebx + 28H] sub esi, edi mov eax, esi cmp eax, ecx jc @@062 mov esi, dword ptr [ebp + 0CH] mov edi, dword ptr [ebx + 34H] sub esi, ecx mov eax, ecx shr ecx, 2 rep movsd mov ecx, eax and ecx, 00000003H rep movsb mov ecx, dword ptr [ebx + 28H] pop edi pop esi pop ebp mov dword ptr [ebx + 30H], 0 mov dword ptr [ebx + 2CH], ecx xor eax, eax pop ebx ret 4 @@062: sub ecx, dword ptr [ebx + 30H] cmp ecx, eax mov dword ptr [esp + 14H], ecx jbe @@063 mov ecx, eax mov dword ptr [esp + 14H], ecx @@063: mov edx, dword ptr [ebx + 30H] mov edi, dword ptr [ebx + 34H] mov esi, dword ptr [ebp + 0CH] add edi, edx mov edx, ecx shr ecx, 2 sub esi, eax rep movsd mov ecx, edx and ecx, 00000003H rep movsb mov ecx, dword ptr [esp + 14H] sub eax, ecx jz @@064 mov esi, dword ptr [ebp + 0CH] mov edi, dword ptr [ebx + 34H] mov ecx, eax mov edx, ecx sub esi, eax shr ecx, 2 rep movsd mov ecx, edx and ecx, 00000003H rep movsb pop edi mov dword ptr [ebx + 30H], eax mov eax, dword ptr [ebx + 28H] pop esi mov dword ptr [ebx + 2CH], eax pop ebp xor eax, eax pop ebx ret 4 @@064: mov edi, dword ptr [ebx + 30H] mov eax, dword ptr [ebx + 28H] add edi, ecx mov edx, edi cmp edx, eax mov dword ptr [ebx + 30H], edi jnz @@065 mov dword ptr [ebx + 30H], 0 @@065: mov edx, dword ptr [ebx + 2CH] cmp edx, eax jnc @@066 add edx, ecx mov dword ptr [ebx + 2CH], edx @@066: pop edi pop esi pop ebp xor eax, eax pop ebx ret 4 end; function inflate; asm pop ebp // auto-generated push ebp; mov ebp,esp mov eax, dword ptr [esp + 04H] sub esp, 52 test eax, eax push ebx je @@191 mov ebx, dword ptr [eax + 1CH] test ebx, ebx je @@191 mov ecx, dword ptr [eax + 0CH] test ecx, ecx je @@191 cmp dword ptr [eax], 0 jnz @@067 mov ecx, dword ptr [eax + 04H] test ecx, ecx jne @@191 @@067: cmp dword ptr [ebx], 11 jnz @@068 mov dword ptr [ebx], 12 @@068: mov ecx, dword ptr [eax + 0CH] mov edx, dword ptr [ebx + 38H] push ebp mov ebp, dword ptr [ebx + 3CH] push esi mov esi, dword ptr [eax] push edi mov edi, dword ptr [eax + 04H] mov dword ptr [esp + 24H], ecx mov ecx, dword ptr [eax + 10H] mov eax, dword ptr [ebx] cmp eax, 28 mov dword ptr [esp + 1CH], ecx mov dword ptr [esp + 14H], esi mov dword ptr [esp + 18H], edi mov dword ptr [esp + 10H], edx mov dword ptr [esp + 38H], edi mov dword ptr [esp + 28H], ecx mov dword ptr [esp + 2CH], 0 ja @@176 @@069: jmp dword ptr [@@192 + eax*4] @@070: mov eax, dword ptr [ebx + 08H] test eax, eax jnz @@071 mov dword ptr [ebx], 12 jmp @@175 @@071: cmp ebp, 16 jnc @@073 @@072: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl dec edi add ebp, 8 mov dword ptr [esp + 18H], edi add edx, eax inc esi cmp ebp, 16 mov dword ptr [esp + 10H], edx mov dword ptr [esp + 14H], esi jc @@072 @@073: mov eax, edx and eax, 000000FFH shr edx, 8 shl eax, 8 add eax, edx xor edx, edx mov ecx, 31 div ecx test edx, edx jz @@074 mov edx, dword ptr [esp + 48H] mov dword ptr [edx + 18H], offset Err248 mov edx, dword ptr [esp + 10H] jmp @@174 @@074: mov ecx, dword ptr [esp + 10H] mov eax, ecx and al, 0FH cmp al, 8 jz @@075 mov ecx, dword ptr [esp + 48H] mov edx, dword ptr [esp + 10H] mov dword ptr [ecx + 18H], offset Err248 jmp @@174 @@075: mov eax, dword ptr [ebx + 24H] shr ecx, 4 mov dword ptr [esp + 10H], ecx and ecx, 0000000FH add ecx, 8 sub ebp, 4 cmp ecx, eax jbe @@076 mov edx, dword ptr [esp + 48H] mov dword ptr [edx + 18H], offset Err248 mov edx, dword ptr [esp + 10H] jmp @@174 @@076: mov eax, 1 shl eax, cl mov dword ptr [ebx + 14H], eax xor eax,eax xor ecx,ecx xor edx,edx xor ebp,ebp call Adler32 mov edx, dword ptr [esp + 10H] mov ecx, dword ptr [esp + 48H] shr edx, 8 not edx and edx, 00000002H or edx, 00000009H mov dword ptr [ebx + 18H], eax mov dword ptr [ecx + 30H], eax mov dword ptr [ebx], edx mov dword ptr [esp + 10H], ebp mov edx, ebp jmp @@175 @@077: cmp ebp, 32 jnc @@079 @@078: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl dec edi add ebp, 8 mov dword ptr [esp + 18H], edi add edx, eax inc esi cmp ebp, 32 mov dword ptr [esp + 10H], edx mov dword ptr [esp + 14H], esi jc @@078 @@079: mov ecx, edx and ecx, 0000FF00H mov eax, edx shl eax, 16 add ecx, eax xor eax, eax mov ah, byte ptr [esp + 12H] shl ecx, 8 shr edx, 24 add ecx, eax lea eax, [ecx + edx] mov ecx, dword ptr [esp + 48H] xor ebp, ebp mov dword ptr [ebx + 18H], eax mov dword ptr [ecx + 30H], eax mov dword ptr [esp + 10H], ebp mov dword ptr [ebx], 10 mov edx, ebp @@080: mov eax, dword ptr [ebx + 0CH] test eax, eax je @@178 xor eax,eax xor ecx,ecx xor edx,edx call Adler32 mov edx, dword ptr [esp + 48H] mov dword ptr [ebx + 18H], eax mov dword ptr [edx + 30H], eax mov edx, dword ptr [esp + 10H] mov dword ptr [ebx], 11 @@081: cmp dword ptr [esp + 4CH], 5 je @@183 @@082: mov eax, dword ptr [ebx + 04H] test eax, eax jz @@083 mov ecx, ebp and ecx, 00000007H shr edx, cl sub ebp, ecx mov dword ptr [ebx], 24 mov dword ptr [esp + 10H], edx jmp @@175 @@083: cmp ebp, 3 jnc @@085 @@084: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl dec edi add ebp, 8 mov dword ptr [esp + 18H], edi add edx, eax inc esi cmp ebp, 3 mov dword ptr [esp + 14H], esi jc @@084 @@085: mov ecx, edx shr edx, 1 and ecx, 00000001H mov eax, edx and eax, 00000003H dec ebp cmp eax, 3 mov dword ptr [ebx + 04H], ecx ja @@090 jmp dword ptr [@@193 + eax*4] @@086: shr edx, 2 mov dword ptr [ebx], 13 mov dword ptr [esp + 10H], edx sub ebp, 2 jmp @@175 @@087: shr edx, 2 mov dword ptr [ebx + 4CH], offset @@249 mov dword ptr [ebx + 54H], 9 mov dword ptr [ebx + 50H], offset @@250 mov dword ptr [ebx + 58H], 5 mov dword ptr [ebx], 18 mov dword ptr [esp + 10H], edx sub ebp, 2 jmp @@175 @@088: shr edx, 2 mov dword ptr [ebx], 15 mov dword ptr [esp + 10H], edx sub ebp, 2 jmp @@175 @@089: mov eax, dword ptr [esp + 48H] mov dword ptr [eax + 18H], offset Err248 mov dword ptr [ebx], 27 @@090: shr edx, 2 mov dword ptr [esp + 10H], edx sub ebp, 2 jmp @@175 @@091: mov ecx, ebp and ecx, 00000007H shr edx, cl sub ebp, ecx cmp ebp, 32 mov dword ptr [esp + 10H], edx jnc @@093 @@092: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl dec edi add ebp, 8 mov dword ptr [esp + 18H], edi add edx, eax inc esi cmp ebp, 32 mov dword ptr [esp + 10H], edx mov dword ptr [esp + 14H], esi jc @@092 @@093: mov ecx, edx mov eax, edx not ecx and eax, 0000FFFFH shr ecx, 16 cmp eax, ecx jz @@094 mov eax, dword ptr [esp + 48H] mov dword ptr [eax + 18H], offset Err248 jmp @@174 @@094: xor ebp, ebp mov dword ptr [ebx + 40H], eax mov dword ptr [esp + 10H], ebp mov dword ptr [ebx], 14 mov edx, ebp @@095: mov ecx, dword ptr [ebx + 40H] test ecx, ecx mov dword ptr [esp + 20H], ecx je @@142 cmp ecx, edi jbe @@096 mov ecx, edi mov dword ptr [esp + 20H], ecx @@096: mov eax, dword ptr [esp + 1CH] cmp ecx, eax jbe @@097 mov ecx, eax mov dword ptr [esp + 20H], ecx @@097: test ecx, ecx je @@183 mov esi, dword ptr [esp + 14H] mov edi, dword ptr [esp + 24H] mov eax, ecx shr ecx, 2 rep movsd mov ecx, eax mov eax, dword ptr [esp + 20H] and ecx, 00000003H rep movsb mov esi, dword ptr [esp + 18H] mov ecx, dword ptr [esp + 14H] mov edi, dword ptr [esp + 1CH] sub esi, eax mov dword ptr [esp + 18H], esi mov esi, dword ptr [esp + 24H] add ecx, eax mov dword ptr [esp + 14H], ecx mov ecx, dword ptr [ebx + 40H] sub edi, eax add esi, eax sub ecx, eax mov dword ptr [esp + 1CH], edi mov edi, dword ptr [esp + 18H] mov dword ptr [esp + 24H], esi mov esi, dword ptr [esp + 14H] mov dword ptr [ebx + 40H], ecx jmp @@175 @@098: cmp ebp, 14 jnc @@100 @@099: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl dec edi add ebp, 8 mov dword ptr [esp + 18H], edi add edx, eax inc esi cmp ebp, 14 mov dword ptr [esp + 14H], esi jc @@099 @@100: mov ecx, edx and ecx, 0000001FH shr edx, 5 add ecx, 257 mov eax, edx mov dword ptr [ebx + 60H], ecx and eax, 0000001FH shr edx, 5 inc eax mov ecx, edx and ecx, 0000000FH mov dword ptr [ebx + 64H], eax mov eax, dword ptr [ebx + 60H] add ecx, 4 shr edx, 4 sub ebp, 14 cmp eax, 286 mov dword ptr [ebx + 5CH], ecx mov dword ptr [esp + 10H], edx ja @@108 cmp dword ptr [ebx + 64H], 30 ja @@108 mov dword ptr [ebx + 68H], 0 mov dword ptr [ebx], 16 @@101: mov ecx, dword ptr [ebx + 68H] cmp ecx, dword ptr [ebx + 5CH] jnc @@105 @@102: cmp ebp, 3 jnc @@104 @@103: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl dec edi add ebp, 8 mov dword ptr [esp + 18H], edi add edx, eax inc esi cmp ebp, 3 mov dword ptr [esp + 14H], esi jc @@103 @@104: mov eax, dword ptr [ebx + 68H] movzx eax, word ptr [@@251 + eax*2] xor ecx, ecx mov cl, dl shr edx, 3 sub ebp, 3 mov dword ptr [esp + 10H], edx and ecx, 00000007H mov word ptr [ebx + eax*2 + 70H], cx mov ecx, dword ptr [ebx + 68H] inc ecx mov dword ptr [ebx + 68H], ecx cmp ecx, dword ptr [ebx + 5CH] jc @@102 @@105: mov ecx, dword ptr [ebx + 68H] mov eax, 19 cmp ecx, eax jnc @@107 xor ecx, ecx @@106: mov edx, dword ptr [ebx + 68H] movzx edx, word ptr [@@251 + edx*2] mov word ptr [ebx + edx*2 + 70H], cx mov edx, dword ptr [ebx + 68H] inc edx cmp edx, eax mov dword ptr [ebx + 68H], edx jc @@106 @@107: lea eax, [ebx + 00000530H] lea ecx, [ebx + 6CH] mov dword ptr [ecx], eax mov dword ptr [ebx + 4CH], eax lea edx, [ebx + 000002F0H] push edx lea eax, [ebx + 54H] push eax push ecx mov dword ptr [eax], 7 push 19 lea eax, [ebx + 70H] push eax push 0 call @@196 test eax, eax mov edx, dword ptr [esp + 10H] mov dword ptr [esp + 2CH], eax jz @@109 mov ecx, dword ptr [esp + 48H] mov dword ptr [ecx + 18H], offset Err248 jmp @@174 @@108: mov eax, dword ptr [esp + 48H] mov dword ptr [eax + 18H], offset Err248 jmp @@174 @@109: mov dword ptr [ebx + 68H], 0 mov dword ptr [ebx], 17 @@110: mov ecx, dword ptr [ebx + 60H] mov eax, dword ptr [ebx + 64H] add eax, ecx cmp dword ptr [ebx + 68H], eax jae @@129 @@111: mov ecx, dword ptr [ebx + 54H] mov eax, 1 shl eax, cl mov ecx, dword ptr [ebx + 4CH] dec eax and eax, edx mov eax, dword ptr [ecx + eax*4] movzx ecx, ah cmp ecx, ebp mov dword ptr [esp + 3CH], eax jbe @@113 @@112: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl mov ecx, dword ptr [ebx + 54H] dec edi add ebp, 8 add edx, eax mov eax, 1 shl eax, cl mov ecx, dword ptr [ebx + 4CH] inc esi mov dword ptr [esp + 18H], edi dec eax and eax, edx mov eax, dword ptr [ecx + eax*4] movzx ecx, ah cmp ecx, ebp mov dword ptr [esp + 14H], esi mov dword ptr [esp + 3CH], eax ja @@112 @@113: mov ecx, dword ptr [esp + 3CH] shr ecx, 16 cmp cx, 16 jnc @@116 movzx ecx, ah cmp ebp, ecx mov dword ptr [esp + 20H], ecx jnc @@115 @@114: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl mov ecx, dword ptr [esp + 20H] dec edi add ebp, 8 add edx, eax inc esi cmp ebp, ecx mov dword ptr [esp + 18H], edi mov dword ptr [esp + 14H], esi jc @@114 @@115: mov ax, word ptr [esp + 3EH] shr edx, cl sub ebp, ecx mov ecx, dword ptr [ebx + 68H] mov word ptr [ebx + ecx*2 + 70H], ax mov eax, dword ptr [ebx + 68H] inc eax mov dword ptr [esp + 10H], edx mov dword ptr [ebx + 68H], eax jmp @@128 @@116: jnz @@119 movzx ecx, ah lea eax, [ecx + 02H] cmp ebp, eax mov dword ptr [esp + 20H], ecx jnc @@118 @@117: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl mov ecx, dword ptr [esp + 20H] dec edi add ebp, 8 add edx, eax inc esi lea eax, [ecx + 02H] cmp ebp, eax mov dword ptr [esp + 18H], edi mov dword ptr [esp + 14H], esi jc @@117 @@118: mov eax, dword ptr [ebx + 68H] shr edx, cl sub ebp, ecx test eax, eax mov dword ptr [esp + 10H], edx je @@130 movzx ecx, word ptr [ebx + eax*2 + 6EH] mov eax, edx and eax, 00000003H add eax, 3 shr edx, 2 mov dword ptr [esp + 30H], ecx mov dword ptr [esp + 20H], eax sub ebp, 2 jmp @@126 @@119: cmp cx, 17 movzx ecx, ah mov dword ptr [esp + 20H], ecx jnz @@122 lea eax, [ecx + 03H] cmp ebp, eax jnc @@121 @@120: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl mov ecx, dword ptr [esp + 20H] dec edi add ebp, 8 add edx, eax inc esi lea eax, [ecx + 03H] cmp ebp, eax mov dword ptr [esp + 18H], edi mov dword ptr [esp + 14H], esi jc @@120 @@121: shr edx, cl mov eax, edx and eax, 00000007H add eax, 3 mov dword ptr [esp + 20H], eax shr edx, 3 mov eax, -3 jmp @@125 @@122: lea eax, [ecx + 07H] cmp ebp, eax jnc @@124 @@123: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl mov ecx, dword ptr [esp + 20H] dec edi add ebp, 8 add edx, eax inc esi lea eax, [ecx + 07H] cmp ebp, eax mov dword ptr [esp + 18H], edi mov dword ptr [esp + 14H], esi jc @@123 @@124: shr edx, cl mov eax, edx and eax, 0000007FH add eax, 11 mov dword ptr [esp + 20H], eax shr edx, 7 mov eax, -7 @@125: sub eax, ecx mov dword ptr [esp + 30H], 0 add ebp, eax @@126: mov eax, dword ptr [ebx + 60H] mov ecx, dword ptr [ebx + 64H] add ecx, eax mov eax, dword ptr [ebx + 68H] add eax, dword ptr [esp + 20H] mov dword ptr [esp + 10H], edx cmp eax, ecx ja @@131 mov eax, dword ptr [esp + 20H] test eax, eax jz @@128 mov dword ptr [esp + 20H], eax mov eax, dword ptr [esp + 30H] @@127: mov ecx, dword ptr [ebx + 68H] mov word ptr [ebx + ecx*2 + 70H], ax inc dword ptr [ebx + 68H] dec dword ptr [esp + 20H] jnz @@127 @@128: mov ecx, dword ptr [ebx + 60H] mov eax, dword ptr [ebx + 64H] add eax, ecx cmp dword ptr [ebx + 68H], eax jb @@111 @@129: cmp dword ptr [ebx], 27 je @@175 lea eax, [ebx + 00000530H] lea ecx, [ebx + 6CH] mov dword ptr [ecx], eax lea edx, [ebx + 000002F0H] push edx mov dword ptr [ebx + 4CH], eax lea eax, [ebx + 54H] push eax push ecx mov ecx, dword ptr [ebx + 60H] push ecx lea edx, [ebx + 70H] push edx push 1 mov dword ptr [eax], 9 call @@196 test eax, eax mov dword ptr [esp + 2CH], eax jz @@132 mov eax, dword ptr [esp + 48H] mov edx, dword ptr [esp + 10H] mov dword ptr [eax + 18H], offset Err248 jmp @@174 @@130: mov ecx, dword ptr [esp + 48H] mov dword ptr [ecx + 18H], offset Err248 jmp @@174 @@131: mov eax, dword ptr [esp + 48H] mov dword ptr [eax + 18H], offset Err248 jmp @@174 @@132: mov edx, dword ptr [ebx + 6CH] lea ecx, [ebx + 6CH] mov dword ptr [ebx + 50H], edx lea edx, [ebx + 000002F0H] push edx lea eax, [ebx + 58H] push eax push ecx mov ecx, dword ptr [ebx + 60H] mov dword ptr [eax], 6 mov eax, dword ptr [ebx + 64H] push eax lea edx, [ebx + ecx*2 + 70H] push edx push 2 call @@196 test eax, eax mov edx, dword ptr [esp + 10H] mov dword ptr [esp + 2CH], eax jz @@133 mov eax, dword ptr [esp + 48H] mov dword ptr [eax + 18H], offset Err248 jmp @@174 @@133: mov dword ptr [ebx], 18 @@134: cmp edi, 6 jc @@135 cmp dword ptr [esp + 1CH], 258 jc @@135 mov eax, dword ptr [esp + 48H] mov ecx, dword ptr [esp + 24H] mov dword ptr [eax + 0CH], ecx mov ecx, dword ptr [esp + 1CH] mov dword ptr [eax + 10H], ecx mov dword ptr [eax], esi mov dword ptr [eax + 04H], edi mov dword ptr [ebx + 38H], edx mov edx, dword ptr [esp + 28H] push edx push eax mov dword ptr [ebx + 3CH], ebp call Inline018 mov eax, dword ptr [esp + 48H] mov edx, dword ptr [eax + 10H] mov ecx, dword ptr [eax + 0CH] mov esi, dword ptr [eax] mov edi, dword ptr [eax + 04H] mov eax, dword ptr [ebx + 38H] mov ebp, dword ptr [ebx + 3CH] mov dword ptr [esp + 1CH], edx mov dword ptr [esp + 24H], ecx mov dword ptr [esp + 14H], esi mov dword ptr [esp + 18H], edi mov dword ptr [esp + 10H], eax mov edx, eax jmp @@175 @@135: mov ecx, dword ptr [ebx + 54H] mov eax, 1 shl eax, cl dec eax and eax, edx mov ecx, eax mov eax, dword ptr [ebx + 4CH] mov eax, dword ptr [eax + ecx*4] movzx ecx, ah cmp ecx, ebp mov dword ptr [esp + 3CH], eax jbe @@137 @@136: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl mov ecx, dword ptr [ebx + 54H] dec edi add ebp, 8 add edx, eax mov eax, 1 shl eax, cl mov ecx, dword ptr [ebx + 4CH] inc esi mov dword ptr [esp + 18H], edi dec eax and eax, edx mov eax, dword ptr [ecx + eax*4] movzx ecx, ah cmp ecx, ebp mov dword ptr [esp + 14H], esi mov dword ptr [esp + 3CH], eax ja @@136 @@137: test al, al je @@140 test al, 0F0H jne @@140 movzx ecx, ah mov dword ptr [esp + 20H], ecx xor ecx, ecx mov cl, al mov dword ptr [esp + 10H], eax add ecx, dword ptr [esp + 20H] mov eax, 1 shl eax, cl mov ecx, dword ptr [esp + 20H] dec eax and eax, edx shr eax, cl mov ecx, dword ptr [esp + 3CH] shr ecx, 16 add eax, ecx mov ecx, eax mov eax, dword ptr [ebx + 4CH] mov eax, dword ptr [eax + ecx*4] mov ecx, dword ptr [esp + 10H] shr ecx, 8 mov dword ptr [esp + 3CH], eax movzx ecx, cl movzx eax, ah add eax, ecx cmp eax, ebp mov dword ptr [esp + 20H], ecx jbe @@139 @@138: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl xor ecx, ecx mov cl, byte ptr [esp + 10H] dec edi add edx, eax mov eax, dword ptr [esp + 20H] inc esi add ebp, 8 mov dword ptr [esp + 18H], edi add ecx, eax mov eax, 1 shl eax, cl mov ecx, dword ptr [esp + 20H] mov dword ptr [esp + 14H], esi dec eax and eax, edx shr eax, cl movzx ecx, word ptr [esp + 12H] add eax, ecx mov ecx, dword ptr [ebx + 4CH] mov eax, dword ptr [ecx + eax*4] mov ecx, dword ptr [esp + 20H] mov dword ptr [esp + 3CH], eax movzx eax, ah add eax, ecx cmp eax, ebp ja @@138 @@139: mov eax, dword ptr [esp + 3CH] shr edx, cl sub ebp, ecx @@140: movzx ecx, ah shr edx, cl movzx ecx, ah sub ebp, ecx mov ecx, dword ptr [esp + 3CH] shr ecx, 16 test al, al mov dword ptr [esp + 10H], edx mov dword ptr [ebx + 40H], ecx jnz @@141 mov dword ptr [ebx], 23 jmp @@175 @@141: test al, 20H jz @@143 @@142: mov dword ptr [ebx], 11 jmp @@175 @@143: test al, 40H jz @@144 mov eax, dword ptr [esp + 48H] mov dword ptr [eax + 18H], offset Err248 jmp @@174 @@144: and eax, 0000000FH mov dword ptr [ebx + 48H], eax mov dword ptr [ebx], 19 @@145: mov eax, dword ptr [ebx + 48H] test eax, eax jz @@148 cmp ebp, eax jnc @@147 @@146: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl dec edi add ebp, 8 mov dword ptr [esp + 18H], edi add edx, eax mov eax, dword ptr [ebx + 48H] inc esi cmp ebp, eax mov dword ptr [esp + 14H], esi jc @@146 @@147: mov ecx, dword ptr [ebx + 48H] mov eax, 1 shl eax, cl mov ecx, dword ptr [ebx + 40H] dec eax and eax, edx add ecx, eax mov dword ptr [ebx + 40H], ecx mov ecx, dword ptr [ebx + 48H] shr edx, cl sub ebp, ecx @@148: mov dword ptr [ebx], 20 @@149: mov ecx, dword ptr [ebx + 58H] mov eax, 1 shl eax, cl dec eax and eax, edx mov ecx, eax mov eax, dword ptr [ebx + 50H] mov eax, dword ptr [eax + ecx*4] movzx ecx, ah cmp ecx, ebp mov dword ptr [esp + 3CH], eax jbe @@151 @@150: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl mov ecx, dword ptr [ebx + 58H] dec edi add ebp, 8 add edx, eax mov eax, 1 shl eax, cl mov ecx, dword ptr [ebx + 50H] inc esi mov dword ptr [esp + 18H], edi dec eax and eax, edx mov eax, dword ptr [ecx + eax*4] movzx ecx, ah cmp ecx, ebp mov dword ptr [esp + 14H], esi mov dword ptr [esp + 3CH], eax ja @@150 @@151: test al, 0F0H jne @@154 movzx ecx, ah mov dword ptr [esp + 20H], ecx xor ecx, ecx mov cl, al mov dword ptr [esp + 10H], eax add ecx, dword ptr [esp + 20H] mov eax, 1 shl eax, cl mov ecx, dword ptr [esp + 20H] dec eax and eax, edx shr eax, cl mov ecx, dword ptr [esp + 3CH] shr ecx, 16 add eax, ecx mov ecx, eax mov eax, dword ptr [ebx + 50H] mov eax, dword ptr [eax + ecx*4] mov ecx, dword ptr [esp + 10H] shr ecx, 8 mov dword ptr [esp + 3CH], eax movzx ecx, cl movzx eax, ah add eax, ecx cmp eax, ebp mov dword ptr [esp + 20H], ecx jbe @@153 @@152: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl xor ecx, ecx mov cl, byte ptr [esp + 10H] dec edi add edx, eax mov eax, dword ptr [esp + 20H] inc esi add ebp, 8 mov dword ptr [esp + 18H], edi add ecx, eax mov eax, 1 shl eax, cl mov ecx, dword ptr [esp + 20H] mov dword ptr [esp + 14H], esi dec eax and eax, edx shr eax, cl movzx ecx, word ptr [esp + 12H] add eax, ecx mov ecx, dword ptr [ebx + 50H] mov eax, dword ptr [ecx + eax*4] mov ecx, dword ptr [esp + 20H] mov dword ptr [esp + 3CH], eax movzx eax, ah add eax, ecx cmp eax, ebp ja @@152 @@153: mov eax, dword ptr [esp + 3CH] shr edx, cl sub ebp, ecx @@154: movzx ecx, ah shr edx, cl movzx ecx, ah sub ebp, ecx test al, 40H mov dword ptr [esp + 10H], edx jz @@155 mov ecx, dword ptr [esp + 48H] mov dword ptr [ecx + 18H], offset Err248 jmp @@174 @@155: mov ecx, dword ptr [esp + 3CH] shr ecx, 16 and eax, 0000000FH mov dword ptr [ebx + 44H], ecx mov dword ptr [ebx + 48H], eax mov dword ptr [ebx], 21 @@156: mov eax, dword ptr [ebx + 48H] test eax, eax jz @@159 cmp ebp, eax jnc @@158 @@157: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl dec edi add ebp, 8 mov dword ptr [esp + 18H], edi add edx, eax mov eax, dword ptr [ebx + 48H] inc esi cmp ebp, eax mov dword ptr [esp + 14H], esi jc @@157 @@158: mov ecx, dword ptr [ebx + 48H] mov eax, 1 shl eax, cl mov ecx, dword ptr [ebx + 44H] dec eax and eax, edx add ecx, eax mov dword ptr [ebx + 44H], ecx mov ecx, dword ptr [ebx + 48H] shr edx, cl sub ebp, ecx mov dword ptr [esp + 10H], edx @@159: mov eax, dword ptr [esp + 1CH] mov ecx, dword ptr [ebx + 2CH] sub ecx, eax add ecx, dword ptr [esp + 28H] cmp dword ptr [ebx + 44H], ecx jbe @@160 mov eax, dword ptr [esp + 48H] mov dword ptr [eax + 18H], offset Err248 jmp @@174 @@160: mov dword ptr [ebx], 22 @@161: mov eax, dword ptr [esp + 1CH] test eax, eax je @@183 mov ecx, dword ptr [esp + 28H] sub ecx, eax mov eax, dword ptr [ebx + 44H] cmp eax, ecx jbe @@164 sub eax, ecx mov ecx, dword ptr [ebx + 30H] cmp eax, ecx mov dword ptr [esp + 20H], eax jbe @@162 sub eax, ecx mov ecx, dword ptr [ebx + 34H] add ecx, dword ptr [ebx + 28H] mov dword ptr [esp + 20H], eax sub ecx, eax jmp @@163 @@162: mov ecx, dword ptr [ebx + 34H] sub ecx, eax add ecx, dword ptr [ebx + 30H] mov eax, dword ptr [esp + 20H] @@163: mov dword ptr [esp + 30H], ecx mov ecx, dword ptr [ebx + 40H] cmp eax, ecx mov dword ptr [esp + 34H], ecx jbe @@166 mov eax, ecx jmp @@165 @@164: mov ecx, dword ptr [esp + 24H] sub ecx, eax mov eax, dword ptr [ebx + 40H] mov dword ptr [esp + 30H], ecx mov dword ptr [esp + 34H], eax @@165: mov dword ptr [esp + 20H], eax @@166: mov ecx, dword ptr [esp + 1CH] cmp eax, ecx jbe @@167 mov eax, ecx mov dword ptr [esp + 20H], eax @@167: sub ecx, eax mov dword ptr [esp + 1CH], ecx mov ecx, dword ptr [esp + 34H] sub ecx, eax mov eax, dword ptr [esp + 24H] mov dword ptr [ebx + 40H], ecx @@168: mov ecx, dword ptr [esp + 30H] mov cl, byte ptr [ecx] mov byte ptr [eax], cl mov ecx, dword ptr [esp + 30H] inc eax inc ecx mov dword ptr [esp + 30H], ecx dec dword ptr [esp + 20H] jnz @@168 mov dword ptr [esp + 24H], eax mov eax, dword ptr [ebx + 40H] test eax, eax jne @@175 mov dword ptr [ebx], 18 jmp @@175 @@169: mov eax, dword ptr [esp + 1CH] test eax, eax je @@183 mov eax, dword ptr [esp + 24H] mov cl, byte ptr [ebx + 40H] mov byte ptr [eax], cl inc eax mov dword ptr [esp + 24H], eax dec dword ptr [esp + 1CH] mov dword ptr [ebx], 18 jmp @@175 @@170: mov eax, dword ptr [ebx + 08H] test eax, eax je @@180 cmp ebp, 32 jnc @@172 @@171: test edi, edi je @@183 movzx eax, byte ptr [esi] mov ecx, ebp shl eax, cl dec edi add ebp, 8 mov dword ptr [esp + 18H], edi add edx, eax inc esi cmp ebp, 32 mov dword ptr [esp + 10H], edx mov dword ptr [esp + 14H], esi jc @@171 @@172: mov eax, dword ptr [esp + 28H] sub eax, dword ptr [esp + 1CH] mov ecx, dword ptr [esp + 48H] add dword ptr [ecx + 14H], eax mov ecx, dword ptr [ebx + 1CH] add ecx, eax test eax, eax mov dword ptr [esp + 28H], eax mov dword ptr [ebx + 1CH], ecx jz @@173 mov ecx, dword ptr [esp + 24H] mov edx, dword ptr [ebx + 18H] push eax sub ecx, eax push ecx push edx // parameters on stack pop eax pop edx pop ecx // register calling convention call Adler32 mov ecx, dword ptr [esp + 48H] mov edx, dword ptr [esp + 10H] mov dword ptr [ebx + 18H], eax mov dword ptr [ecx + 30H], eax @@173: mov eax, dword ptr [esp + 1CH] mov dword ptr [esp + 28H], eax mov ecx, edx and ecx, 0000FF00H mov eax, edx shl eax, 16 add ecx, eax xor eax, eax mov ah, byte ptr [esp + 12H] shl ecx, 8 add ecx, eax mov eax, edx shr eax, 24 add ecx, eax cmp ecx, dword ptr [ebx + 18H] jz @@179 mov ecx, dword ptr [esp + 48H] mov dword ptr [ecx + 18H], offset Err248 @@174: mov dword ptr [ebx], 27 @@175: mov eax, dword ptr [ebx] cmp eax, 28 jbe @@069 @@176: mov eax, -2 @@177: pop edi pop esi pop ebp pop ebx add esp, 52 ret 8 @@178: mov eax, dword ptr [esp + 48H] mov ecx, dword ptr [esp + 24H] mov dword ptr [eax + 0CH], ecx mov ecx, dword ptr [esp + 1CH] mov dword ptr [eax + 04H], edi mov dword ptr [eax], esi pop edi mov dword ptr [eax + 10H], ecx pop esi mov dword ptr [ebx + 3CH], ebp pop ebp mov dword ptr [ebx + 38H], edx mov eax, 2 pop ebx add esp, 52 ret 8 @@179: xor ebp, ebp mov dword ptr [esp + 10H], ebp mov edx, ebp @@180: mov dword ptr [ebx], 26 @@181: mov dword ptr [esp + 2CH], 1 jmp @@183 @@182: mov dword ptr [esp + 2CH], -3 @@183: mov eax, dword ptr [esp + 48H] mov ecx, dword ptr [esp + 24H] mov dword ptr [eax + 0CH], ecx mov ecx, dword ptr [esp + 1CH] mov dword ptr [eax + 10H], ecx mov dword ptr [eax], esi mov dword ptr [eax + 04H], edi mov eax, dword ptr [ebx + 28H] test eax, eax mov dword ptr [ebx + 38H], edx mov dword ptr [ebx + 3CH], ebp jnz @@184 cmp dword ptr [ebx], 24 jge @@186 mov eax, dword ptr [esp + 48H] mov edx, dword ptr [esp + 28H] cmp edx, dword ptr [eax + 10H] jz @@186 @@184: mov ecx, dword ptr [esp + 48H] mov eax, dword ptr [esp + 28H] push ecx call Inline059; test eax, eax jz @@186 mov dword ptr [ebx], 28 @@185: pop edi pop esi pop ebp mov eax, -4 pop ebx add esp, 52 ret 8 @@186: mov esi, dword ptr [esp + 48H] mov edx, dword ptr [esi + 04H] mov ecx, dword ptr [esi + 10H] mov ebp, dword ptr [esp + 38H] mov edi, dword ptr [esp + 28H] mov eax, dword ptr [esi + 08H] sub ebp, edx mov edx, dword ptr [esi + 14H] sub edi, ecx add eax, ebp add edx, edi mov dword ptr [esi + 08H], eax mov dword ptr [esi + 14H], edx mov ecx, dword ptr [ebx + 1CH] mov eax, dword ptr [ebx + 08H] add ecx, edi test eax, eax mov dword ptr [ebx + 1CH], ecx jz @@187 test edi, edi jz @@187 mov edx, dword ptr [esi + 0CH] mov eax, dword ptr [ebx + 18H] mov ecx,edi sub edx, edi call Adler32 // register calling convention mov dword ptr [ebx + 18H], eax mov dword ptr [esi + 30H], eax @@187: mov ecx, dword ptr [ebx + 04H] mov eax, dword ptr [ebx] neg ecx sbb ecx, ecx xor edx, edx and ecx, 00000040H cmp eax, 11 setne dl dec edx and edx, 00000080H add ecx, edx add ecx, dword ptr [ebx + 3CH] test ebp, ebp mov dword ptr [esi + 2CH], ecx jnz @@188 test edi, edi jz @@189 @@188: cmp dword ptr [esp + 4CH], 4 jnz @@190 @@189: mov eax, dword ptr [esp + 2CH] test eax, eax jne @@177 pop edi pop esi pop ebp mov eax, -5 pop ebx add esp, 52 ret 8 @@190: mov eax, dword ptr [esp + 2CH] pop edi pop esi pop ebp pop ebx add esp, 52 ret 8 @@191: mov eax, -2 pop ebx add esp, 52 ret 8 @@196: sub esp, 124 mov edx, dword ptr [esp + 00000088H] xor eax, eax test edx, edx mov dword ptr [esp + 3CH], eax mov dword ptr [esp + 40H], eax mov dword ptr [esp + 44H], eax mov dword ptr [esp + 48H], eax mov dword ptr [esp + 4CH], eax push ebx mov dword ptr [esp + 54H], eax push ebp mov ebp, dword ptr [esp + 0000008CH] mov dword ptr [esp + 5CH], eax push esi mov dword ptr [esp + 64H], eax jbe @@198 @@197: movzx ecx, word ptr [ebp + eax*2] inc word ptr [esp + ecx*2 + 48H] lea ecx, [esp + ecx*2 + 48H] inc eax cmp eax, edx jc @@197 @@198: mov esi, dword ptr [esp + 0000009CH] mov eax, dword ptr [esi] mov ebx, 15 mov dword ptr [esp + 10H], eax mov dword ptr [esp + 18H], ebx @@199: cmp word ptr [esp + ebx*2 + 48H], 0 jnz @@200 dec ebx cmp ebx, 1 jnc @@199 @@200: cmp eax, ebx mov dword ptr [esp + 18H], ebx jbe @@201 mov dword ptr [esp + 10H], ebx @@201: test ebx, ebx jnz @@202 mov eax, dword ptr [esp + 00000098H] mov edx, dword ptr [eax] mov word ptr [esp + 0EH], bx mov byte ptr [esp + 0CH], 64 mov byte ptr [esp + 0DH], 1 mov ecx, dword ptr [esp + 0CH] mov dword ptr [edx], ecx mov edx, dword ptr [eax] add edx, 4 mov dword ptr [eax], edx mov dword ptr [edx], ecx add dword ptr [eax], 4 mov dword ptr [esi], 1 pop esi pop ebp xor eax, eax pop ebx add esp, 124 ret 24 @@202: mov esi, 1 @@203: cmp word ptr [esp + esi*2 + 48H], 0 jnz @@208 cmp word ptr [esp + esi*2 + 4AH], 0 jnz @@204 cmp word ptr [esp + esi*2 + 4CH], 0 jnz @@205 cmp word ptr [esp + esi*2 + 4EH], 0 jnz @@206 cmp word ptr [esp + esi*2 + 50H], 0 jnz @@207 add esi, 5 cmp esi, 15 jbe @@203 jmp @@208 @@204: inc esi jmp @@208 @@205: add esi, 2 jmp @@208 @@206: add esi, 3 jmp @@208 @@207: add esi, 4 @@208: cmp dword ptr [esp + 10H], esi jnc @@209 mov dword ptr [esp + 10H], esi @@209: mov edx, 1 mov eax, edx @@210: movzx ecx, word ptr [esp + eax*2 + 48H] add edx, edx sub edx, ecx js @@212 inc eax cmp eax, 15 jbe @@210 test edx, edx push edi mov edi, dword ptr [esp + 00000090H] jle @@213 test edi, edi jz @@211 cmp ebx, 1 jz @@213 @@211: pop edi pop esi pop ebp or eax, 0FFFFFFFFH pop ebx add esp, 124 ret 24 @@212: pop esi pop ebp or eax, 0FFFFFFFFH pop ebx add esp, 124 ret 24 @@213: mov word ptr [esp + 6EH], 0 mov eax, 2 @@214: mov dx, word ptr [esp + eax + 6CH] add dx, word ptr [esp + eax + 4CH] mov cx, word ptr [esp + eax + 4EH] add cx, dx mov word ptr [esp + eax + 6EH], dx mov word ptr [esp + eax + 70H], cx add eax, 4 cmp eax, 30 jc @@214 mov ebx, dword ptr [esp + 00000098H] xor eax, eax test ebx, ebx jbe @@217 @@215: cmp word ptr [ebp + eax*2], 0 jz @@216 movzx edx, word ptr [ebp + eax*2] movzx ecx, word ptr [esp + edx*2 + 6CH] mov edx, dword ptr [esp + 000000A4H] mov word ptr [edx + ecx*2], ax movzx edx, word ptr [ebp + eax*2] inc word ptr [esp + edx*2 + 6CH] lea edx, [esp + edx*2 + 6CH] @@216: inc eax cmp eax, ebx jc @@215 @@217: mov eax, edi sub eax, 0 mov edx, -1 jz @@219 dec eax jz @@218 mov dword ptr [esp + 34H], offset @@265 mov dword ptr [esp + 30H], offset @@266 mov dword ptr [esp + 2CH], edx jmp @@221 @@218: mov eax, offset @@263 sub eax, 514 mov dword ptr [esp + 34H], eax mov eax, offset @@264 sub eax, 514 mov dword ptr [esp + 2CH], 256 jmp @@220 @@219: mov eax, dword ptr [esp + 000000A4H] mov dword ptr [esp + 34H], eax mov dword ptr [esp + 2CH], 19 @@220: mov dword ptr [esp + 30H], eax @@221: mov eax, dword ptr [esp + 0000009CH] mov ecx, dword ptr [eax] mov dword ptr [esp + 20H], ecx mov ecx, dword ptr [esp + 14H] mov eax, 1 shl eax, cl mov dword ptr [esp + 38H], edx xor ebp, ebp xor ebx, ebx cmp edi, 1 lea edx, [eax - 01H] mov dword ptr [esp + 18H], esi mov dword ptr [esp + 3CH], eax mov dword ptr [esp + 28H], eax mov dword ptr [esp + 40H], edx jnz @@222 cmp eax, 1456 jae @@244 @@222: mov eax, dword ptr [esp + 000000A4H] mov dword ptr [esp + 24H], eax @@223: mov cl, byte ptr [esp + 18H] mov esi, dword ptr [esp + 24H] mov ax, word ptr [esi] mov edx, dword ptr [esp + 2CH] sub cl, bl mov byte ptr [esp + 11H], cl movzx ecx, ax cmp ecx, edx jge @@224 mov byte ptr [esp + 10H], 0 mov word ptr [esp + 12H], ax jmp @@226 @@224: jle @@225 movzx eax, word ptr [esi] mov edx, dword ptr [esp + 30H] shl eax, 1 mov cl, byte ptr [eax + edx] mov edx, dword ptr [esp + 34H] mov ax, word ptr [eax + edx] mov byte ptr [esp + 10H], cl mov word ptr [esp + 12H], ax jmp @@226 @@225: mov byte ptr [esp + 10H], 96 mov word ptr [esp + 12H], 0 @@226: mov ecx, dword ptr [esp + 18H] mov eax, dword ptr [esp + 3CH] sub ecx, ebx mov edx, 1 shl edx, cl mov ecx, ebx mov edi, ebp shr edi, cl mov ecx, dword ptr [esp + 20H] mov dword ptr [esp + 44H], eax lea esi, [edx*4] add edi, eax lea ecx, [ecx + edi*4] mov edi, dword ptr [esp + 10H] @@227: sub eax, edx sub ecx, esi test eax, eax mov dword ptr [ecx], edi jnz @@227 mov edx, dword ptr [esp + 18H] lea ecx, [edx - 01H] mov eax, 1 shl eax, cl test ebp, eax jz @@229 @@228: shr eax, 1 test ebp, eax jnz @@228 @@229: test eax, eax jz @@230 lea ecx, [eax - 01H] and ecx, ebp add ecx, eax mov ebp, ecx jmp @@231 @@230: xor ebp, ebp @@231: mov esi, dword ptr [esp + 24H] add esi, 2 dec word ptr [esp + edx*2 + 4CH] cmp word ptr [esp + edx*2 + 4CH], 0 mov dword ptr [esp + 24H], esi jnz @@232 cmp edx, dword ptr [esp + 1CH] je @@238 mov ecx, dword ptr [esp + 00000094H] mov edx, esi movzx eax, word ptr [edx] movzx edx, word ptr [ecx + eax*2] mov dword ptr [esp + 18H], edx @@232: cmp edx, dword ptr [esp + 14H] jbe @@223 mov esi, dword ptr [esp + 40H] mov eax, dword ptr [esp + 38H] and esi, ebp cmp esi, eax mov dword ptr [esp + 48H], esi je @@223 test ebx, ebx jnz @@233 mov ebx, dword ptr [esp + 14H] @@233: mov eax, dword ptr [esp + 20H] mov ecx, dword ptr [esp + 44H] mov edi, dword ptr [esp + 1CH] lea edx, [eax + ecx*4] mov ecx, dword ptr [esp + 18H] sub ecx, ebx mov dword ptr [esp + 20H], edx mov eax, 1 lea edx, [ebx + ecx] shl eax, cl cmp edx, edi jnc @@236 lea esi, [esp + edx*2 + 4CH] @@234: movzx edi, word ptr [esi] sub eax, edi test eax, eax jle @@235 mov edi, dword ptr [esp + 1CH] inc ecx inc edx add esi, 2 shl eax, 1 cmp edx, edi jc @@234 @@235: mov esi, dword ptr [esp + 48H] @@236: mov edx, dword ptr [esp + 28H] mov eax, 1 shl eax, cl add edx, eax mov dword ptr [esp + 3CH], eax cmp dword ptr [esp + 00000090H], 1 mov dword ptr [esp + 28H], edx jnz @@237 mov eax, edx cmp eax, 1456 jae @@244 @@237: mov edx, esi mov esi, dword ptr [esp + 0000009CH] mov eax, dword ptr [esi] mov byte ptr [eax + edx*4], cl mov ecx, dword ptr [esi] mov al, byte ptr [esp + 14H] mov byte ptr [ecx + edx*4 + 01H], al mov eax, dword ptr [esi] mov ecx, dword ptr [esp + 20H] sub ecx, eax sar ecx, 2 mov dword ptr [esp + 38H], edx mov word ptr [eax + edx*4 + 02H], cx jmp @@223 @@238: mov edi, dword ptr [esp + 0000009CH] mov al, dl sub al, bl test ebp, ebp mov byte ptr [esp + 10H], 64 mov byte ptr [esp + 11H], al mov word ptr [esp + 12H], 0 jz @@243 mov esi, dword ptr [esp + 20H] @@239: test ebx, ebx jz @@240 mov ecx, dword ptr [esp + 40H] mov eax, dword ptr [esp + 38H] and ecx, ebp cmp ecx, eax jz @@240 mov eax, dword ptr [esp + 14H] mov esi, dword ptr [edi] xor ebx, ebx mov dword ptr [esp + 18H], eax mov byte ptr [esp + 11H], al mov edx, eax @@240: mov ecx, ebx mov eax, ebp shr eax, cl mov ecx, dword ptr [esp + 10H] mov dword ptr [esi + eax*4], ecx lea ecx, [edx - 01H] mov eax, 1 shl eax, cl test ebp, eax jz @@242 @@241: shr eax, 1 test ebp, eax jnz @@241 @@242: test eax, eax jz @@243 lea ecx, [eax - 01H] and ecx, ebp add ecx, eax mov ebp, ecx jnz @@239 @@243: mov edx, dword ptr [esp + 28H] mov ecx, dword ptr [edi] lea eax, [edx*4] mov edx, dword ptr [esp + 14H] add ecx, eax mov dword ptr [edi], ecx mov ecx, dword ptr [esp + 000000A0H] pop edi pop esi pop ebp mov dword ptr [ecx], edx xor eax, eax pop ebx add esp, 124 ret 24 @@244: pop edi pop esi pop ebp mov eax, 1 pop ebx add esp, 124 ret 24 nop; nop @@192: dd @@070 // buffer is 8 bytes aligned dd @@176 dd @@176 dd @@176 dd @@176 dd @@176 dd @@176 dd @@176 dd @@176 dd @@077 dd @@080 dd @@081 dd @@082 dd @@091 dd @@095 dd @@098 dd @@101 dd @@110 dd @@134 dd @@145 dd @@149 dd @@156 dd @@161 dd @@169 dd @@170 dd @@176 dd @@181 dd @@182 dd @@185 @@193: dd @@086 dd @@087 dd @@088 dd @@089 @@251: dw 0010H, 0011H, 0012H, 0000H dw 0008H, 0007H, 0009H, 0006H dw 000AH, 0005H, 000BH, 0004H dw 000CH, 0003H, 000DH, 0002H dw 000EH, 0001H, 000FH, 0000H @@249: db 60H, 07H, 00H, 00H, 00H, 08H, 50H, 00H db 00H, 08H, 10H, 00H, 14H, 08H, 73H, 00H db 12H, 07H, 1FH, 00H, 00H, 08H, 70H, 00H db 00H, 08H, 30H, 00H, 00H, 09H, 0C0H, 00H db 10H, 07H, 0AH, 00H, 00H, 08H, 60H, 00H db 00H, 08H, 20H, 00H, 00H, 09H, 0A0H, 00H db 00H, 08H, 00H, 00H, 00H, 08H, 80H, 00H db 00H, 08H, 40H, 00H, 00H, 09H, 0E0H, 00H db 10H, 07H, 06H, 00H, 00H, 08H, 58H, 00H db 00H, 08H, 18H, 00H, 00H, 09H, 90H, 00H db 13H, 07H, 3BH, 00H, 00H, 08H, 78H, 00H db 00H, 08H, 38H, 00H, 00H, 09H, 0D0H, 00H db 11H, 07H, 11H, 00H, 00H, 08H, 68H, 00H db 00H, 08H, 28H, 00H, 00H, 09H, 0B0H, 00H db 00H, 08H, 08H, 00H, 00H, 08H, 88H, 00H db 00H, 08H, 48H, 00H, 00H, 09H, 0F0H, 00H db 10H, 07H, 04H, 00H, 00H, 08H, 54H, 00H db 00H, 08H, 14H, 00H, 15H, 08H, 0E3H, 00H db 13H, 07H, 2BH, 00H, 00H, 08H, 74H, 00H db 00H, 08H, 34H, 00H, 00H, 09H, 0C8H, 00H db 11H, 07H, 0DH, 00H, 00H, 08H, 64H, 00H db 00H, 08H, 24H, 00H, 00H, 09H, 0A8H, 00H db 00H, 08H, 04H, 00H, 00H, 08H, 84H, 00H db 00H, 08H, 44H, 00H, 00H, 09H, 0E8H, 00H db 10H, 07H, 08H, 00H, 00H, 08H, 5CH, 00H db 00H, 08H, 1CH, 00H, 00H, 09H, 98H, 00H db 14H, 07H, 53H, 00H, 00H, 08H, 7CH, 00H db 00H, 08H, 3CH, 00H, 00H, 09H, 0D8H, 00H db 12H, 07H, 17H, 00H, 00H, 08H, 6CH, 00H db 00H, 08H, 2CH, 00H, 00H, 09H, 0B8H, 00H db 00H, 08H, 0CH, 00H, 00H, 08H, 8CH, 00H db 00H, 08H, 4CH, 00H, 00H, 09H, 0F8H, 00H db 10H, 07H, 03H, 00H, 00H, 08H, 52H, 00H db 00H, 08H, 12H, 00H, 15H, 08H, 0A3H, 00H db 13H, 07H, 23H, 00H, 00H, 08H, 72H, 00H db 00H, 08H, 32H, 00H, 00H, 09H, 0C4H, 00H db 11H, 07H, 0BH, 00H, 00H, 08H, 62H, 00H db 00H, 08H, 22H, 00H, 00H, 09H, 0A4H, 00H db 00H, 08H, 02H, 00H, 00H, 08H, 82H, 00H db 00H, 08H, 42H, 00H, 00H, 09H, 0E4H, 00H db 10H, 07H, 07H, 00H, 00H, 08H, 5AH, 00H db 00H, 08H, 1AH, 00H, 00H, 09H, 94H, 00H db 14H, 07H, 43H, 00H, 00H, 08H, 7AH, 00H db 00H, 08H, 3AH, 00H, 00H, 09H, 0D4H, 00H db 12H, 07H, 13H, 00H, 00H, 08H, 6AH, 00H db 00H, 08H, 2AH, 00H, 00H, 09H, 0B4H, 00H db 00H, 08H, 0AH, 00H, 00H, 08H, 8AH, 00H db 00H, 08H, 4AH, 00H, 00H, 09H, 0F4H, 00H db 10H, 07H, 05H, 00H, 00H, 08H, 56H, 00H db 00H, 08H, 16H, 00H, 40H, 08H, 00H, 00H db 13H, 07H, 33H, 00H, 00H, 08H, 76H, 00H db 00H, 08H, 36H, 00H, 00H, 09H, 0CCH, 00H db 11H, 07H, 0FH, 00H, 00H, 08H, 66H, 00H db 00H, 08H, 26H, 00H, 00H, 09H, 0ACH, 00H db 00H, 08H, 06H, 00H, 00H, 08H, 86H, 00H db 00H, 08H, 46H, 00H, 00H, 09H, 0ECH, 00H db 10H, 07H, 09H, 00H, 00H, 08H, 5EH, 00H db 00H, 08H, 1EH, 00H, 00H, 09H, 9CH, 00H db 14H, 07H, 63H, 00H, 00H, 08H, 7EH, 00H db 00H, 08H, 3EH, 00H, 00H, 09H, 0DCH, 00H db 12H, 07H, 1BH, 00H, 00H, 08H, 6EH, 00H db 00H, 08H, 2EH, 00H, 00H, 09H, 0BCH, 00H db 00H, 08H, 0EH, 00H, 00H, 08H, 8EH, 00H db 00H, 08H, 4EH, 00H, 00H, 09H, 0FCH, 00H db 60H, 07H, 00H, 00H, 00H, 08H, 51H, 00H db 00H, 08H, 11H, 00H, 15H, 08H, 83H, 00H db 12H, 07H, 1FH, 00H, 00H, 08H, 71H, 00H db 00H, 08H, 31H, 00H, 00H, 09H, 0C2H, 00H db 10H, 07H, 0AH, 00H, 00H, 08H, 61H, 00H db 00H, 08H, 21H, 00H, 00H, 09H, 0A2H, 00H db 00H, 08H, 01H, 00H, 00H, 08H, 81H, 00H db 00H, 08H, 41H, 00H, 00H, 09H, 0E2H, 00H db 10H, 07H, 06H, 00H, 00H, 08H, 59H, 00H db 00H, 08H, 19H, 00H, 00H, 09H, 92H, 00H db 13H, 07H, 3BH, 00H, 00H, 08H, 79H, 00H db 00H, 08H, 39H, 00H, 00H, 09H, 0D2H, 00H db 11H, 07H, 11H, 00H, 00H, 08H, 69H, 00H db 00H, 08H, 29H, 00H, 00H, 09H, 0B2H, 00H db 00H, 08H, 09H, 00H, 00H, 08H, 89H, 00H db 00H, 08H, 49H, 00H, 00H, 09H, 0F2H, 00H db 10H, 07H, 04H, 00H, 00H, 08H, 55H, 00H db 00H, 08H, 15H, 00H, 10H, 08H, 02H, 01H db 13H, 07H, 2BH, 00H, 00H, 08H, 75H, 00H db 00H, 08H, 35H, 00H, 00H, 09H, 0CAH, 00H db 11H, 07H, 0DH, 00H, 00H, 08H, 65H, 00H db 00H, 08H, 25H, 00H, 00H, 09H, 0AAH, 00H db 00H, 08H, 05H, 00H, 00H, 08H, 85H, 00H db 00H, 08H, 45H, 00H, 00H, 09H, 0EAH, 00H db 10H, 07H, 08H, 00H, 00H, 08H, 5DH, 00H db 00H, 08H, 1DH, 00H, 00H, 09H, 9AH, 00H db 14H, 07H, 53H, 00H, 00H, 08H, 7DH, 00H db 00H, 08H, 3DH, 00H, 00H, 09H, 0DAH, 00H db 12H, 07H, 17H, 00H, 00H, 08H, 6DH, 00H db 00H, 08H, 2DH, 00H, 00H, 09H, 0BAH, 00H db 00H, 08H, 0DH, 00H, 00H, 08H, 8DH, 00H db 00H, 08H, 4DH, 00H, 00H, 09H, 0FAH, 00H db 10H, 07H, 03H, 00H, 00H, 08H, 53H, 00H db 00H, 08H, 13H, 00H, 15H, 08H, 0C3H, 00H db 13H, 07H, 23H, 00H, 00H, 08H, 73H, 00H db 00H, 08H, 33H, 00H, 00H, 09H, 0C6H, 00H db 11H, 07H, 0BH, 00H, 00H, 08H, 63H, 00H db 00H, 08H, 23H, 00H, 00H, 09H, 0A6H, 00H db 00H, 08H, 03H, 00H, 00H, 08H, 83H, 00H db 00H, 08H, 43H, 00H, 00H, 09H, 0E6H, 00H db 10H, 07H, 07H, 00H, 00H, 08H, 5BH, 00H db 00H, 08H, 1BH, 00H, 00H, 09H, 96H, 00H db 14H, 07H, 43H, 00H, 00H, 08H, 7BH, 00H db 00H, 08H, 3BH, 00H, 00H, 09H, 0D6H, 00H db 12H, 07H, 13H, 00H, 00H, 08H, 6BH, 00H db 00H, 08H, 2BH, 00H, 00H, 09H, 0B6H, 00H db 00H, 08H, 0BH, 00H, 00H, 08H, 8BH, 00H db 00H, 08H, 4BH, 00H, 00H, 09H, 0F6H, 00H db 10H, 07H, 05H, 00H, 00H, 08H, 57H, 00H db 00H, 08H, 17H, 00H, 40H, 08H, 00H, 00H db 13H, 07H, 33H, 00H, 00H, 08H, 77H, 00H db 00H, 08H, 37H, 00H, 00H, 09H, 0CEH, 00H db 11H, 07H, 0FH, 00H, 00H, 08H, 67H, 00H db 00H, 08H, 27H, 00H, 00H, 09H, 0AEH, 00H db 00H, 08H, 07H, 00H, 00H, 08H, 87H, 00H db 00H, 08H, 47H, 00H, 00H, 09H, 0EEH, 00H db 10H, 07H, 09H, 00H, 00H, 08H, 5FH, 00H db 00H, 08H, 1FH, 00H, 00H, 09H, 9EH, 00H db 14H, 07H, 63H, 00H, 00H, 08H, 7FH, 00H db 00H, 08H, 3FH, 00H, 00H, 09H, 0DEH, 00H db 12H, 07H, 1BH, 00H, 00H, 08H, 6FH, 00H db 00H, 08H, 2FH, 00H, 00H, 09H, 0BEH, 00H db 00H, 08H, 0FH, 00H, 00H, 08H, 8FH, 00H db 00H, 08H, 4FH, 00H, 00H, 09H, 0FEH, 00H db 60H, 07H, 00H, 00H, 00H, 08H, 50H, 00H db 00H, 08H, 10H, 00H, 14H, 08H, 73H, 00H db 12H, 07H, 1FH, 00H, 00H, 08H, 70H, 00H db 00H, 08H, 30H, 00H, 00H, 09H, 0C1H, 00H db 10H, 07H, 0AH, 00H, 00H, 08H, 60H, 00H db 00H, 08H, 20H, 00H, 00H, 09H, 0A1H, 00H db 00H, 08H, 00H, 00H, 00H, 08H, 80H, 00H db 00H, 08H, 40H, 00H, 00H, 09H, 0E1H, 00H db 10H, 07H, 06H, 00H, 00H, 08H, 58H, 00H db 00H, 08H, 18H, 00H, 00H, 09H, 91H, 00H db 13H, 07H, 3BH, 00H, 00H, 08H, 78H, 00H db 00H, 08H, 38H, 00H, 00H, 09H, 0D1H, 00H db 11H, 07H, 11H, 00H, 00H, 08H, 68H, 00H db 00H, 08H, 28H, 00H, 00H, 09H, 0B1H, 00H db 00H, 08H, 08H, 00H, 00H, 08H, 88H, 00H db 00H, 08H, 48H, 00H, 00H, 09H, 0F1H, 00H db 10H, 07H, 04H, 00H, 00H, 08H, 54H, 00H db 00H, 08H, 14H, 00H, 15H, 08H, 0E3H, 00H db 13H, 07H, 2BH, 00H, 00H, 08H, 74H, 00H db 00H, 08H, 34H, 00H, 00H, 09H, 0C9H, 00H db 11H, 07H, 0DH, 00H, 00H, 08H, 64H, 00H db 00H, 08H, 24H, 00H, 00H, 09H, 0A9H, 00H db 00H, 08H, 04H, 00H, 00H, 08H, 84H, 00H db 00H, 08H, 44H, 00H, 00H, 09H, 0E9H, 00H db 10H, 07H, 08H, 00H, 00H, 08H, 5CH, 00H db 00H, 08H, 1CH, 00H, 00H, 09H, 99H, 00H db 14H, 07H, 53H, 00H, 00H, 08H, 7CH, 00H db 00H, 08H, 3CH, 00H, 00H, 09H, 0D9H, 00H db 12H, 07H, 17H, 00H, 00H, 08H, 6CH, 00H db 00H, 08H, 2CH, 00H, 00H, 09H, 0B9H, 00H db 00H, 08H, 0CH, 00H, 00H, 08H, 8CH, 00H db 00H, 08H, 4CH, 00H, 00H, 09H, 0F9H, 00H db 10H, 07H, 03H, 00H, 00H, 08H, 52H, 00H db 00H, 08H, 12H, 00H, 15H, 08H, 0A3H, 00H db 13H, 07H, 23H, 00H, 00H, 08H, 72H, 00H db 00H, 08H, 32H, 00H, 00H, 09H, 0C5H, 00H db 11H, 07H, 0BH, 00H, 00H, 08H, 62H, 00H db 00H, 08H, 22H, 00H, 00H, 09H, 0A5H, 00H db 00H, 08H, 02H, 00H, 00H, 08H, 82H, 00H db 00H, 08H, 42H, 00H, 00H, 09H, 0E5H, 00H db 10H, 07H, 07H, 00H, 00H, 08H, 5AH, 00H db 00H, 08H, 1AH, 00H, 00H, 09H, 95H, 00H db 14H, 07H, 43H, 00H, 00H, 08H, 7AH, 00H db 00H, 08H, 3AH, 00H, 00H, 09H, 0D5H, 00H db 12H, 07H, 13H, 00H, 00H, 08H, 6AH, 00H db 00H, 08H, 2AH, 00H, 00H, 09H, 0B5H, 00H db 00H, 08H, 0AH, 00H, 00H, 08H, 8AH, 00H db 00H, 08H, 4AH, 00H, 00H, 09H, 0F5H, 00H db 10H, 07H, 05H, 00H, 00H, 08H, 56H, 00H db 00H, 08H, 16H, 00H, 40H, 08H, 00H, 00H db 13H, 07H, 33H, 00H, 00H, 08H, 76H, 00H db 00H, 08H, 36H, 00H, 00H, 09H, 0CDH, 00H db 11H, 07H, 0FH, 00H, 00H, 08H, 66H, 00H db 00H, 08H, 26H, 00H, 00H, 09H, 0ADH, 00H db 00H, 08H, 06H, 00H, 00H, 08H, 86H, 00H db 00H, 08H, 46H, 00H, 00H, 09H, 0EDH, 00H db 10H, 07H, 09H, 00H, 00H, 08H, 5EH, 00H db 00H, 08H, 1EH, 00H, 00H, 09H, 9DH, 00H db 14H, 07H, 63H, 00H, 00H, 08H, 7EH, 00H db 00H, 08H, 3EH, 00H, 00H, 09H, 0DDH, 00H db 12H, 07H, 1BH, 00H, 00H, 08H, 6EH, 00H db 00H, 08H, 2EH, 00H, 00H, 09H, 0BDH, 00H db 00H, 08H, 0EH, 00H, 00H, 08H, 8EH, 00H db 00H, 08H, 4EH, 00H, 00H, 09H, 0FDH, 00H db 60H, 07H, 00H, 00H, 00H, 08H, 51H, 00H db 00H, 08H, 11H, 00H, 15H, 08H, 83H, 00H db 12H, 07H, 1FH, 00H, 00H, 08H, 71H, 00H db 00H, 08H, 31H, 00H, 00H, 09H, 0C3H, 00H db 10H, 07H, 0AH, 00H, 00H, 08H, 61H, 00H db 00H, 08H, 21H, 00H, 00H, 09H, 0A3H, 00H db 00H, 08H, 01H, 00H, 00H, 08H, 81H, 00H db 00H, 08H, 41H, 00H, 00H, 09H, 0E3H, 00H db 10H, 07H, 06H, 00H, 00H, 08H, 59H, 00H db 00H, 08H, 19H, 00H, 00H, 09H, 93H, 00H db 13H, 07H, 3BH, 00H, 00H, 08H, 79H, 00H db 00H, 08H, 39H, 00H, 00H, 09H, 0D3H, 00H db 11H, 07H, 11H, 00H, 00H, 08H, 69H, 00H db 00H, 08H, 29H, 00H, 00H, 09H, 0B3H, 00H db 00H, 08H, 09H, 00H, 00H, 08H, 89H, 00H db 00H, 08H, 49H, 00H, 00H, 09H, 0F3H, 00H db 10H, 07H, 04H, 00H, 00H, 08H, 55H, 00H db 00H, 08H, 15H, 00H, 10H, 08H, 02H, 01H db 13H, 07H, 2BH, 00H, 00H, 08H, 75H, 00H db 00H, 08H, 35H, 00H, 00H, 09H, 0CBH, 00H db 11H, 07H, 0DH, 00H, 00H, 08H, 65H, 00H db 00H, 08H, 25H, 00H, 00H, 09H, 0ABH, 00H db 00H, 08H, 05H, 00H, 00H, 08H, 85H, 00H db 00H, 08H, 45H, 00H, 00H, 09H, 0EBH, 00H db 10H, 07H, 08H, 00H, 00H, 08H, 5DH, 00H db 00H, 08H, 1DH, 00H, 00H, 09H, 9BH, 00H db 14H, 07H, 53H, 00H, 00H, 08H, 7DH, 00H db 00H, 08H, 3DH, 00H, 00H, 09H, 0DBH, 00H db 12H, 07H, 17H, 00H, 00H, 08H, 6DH, 00H db 00H, 08H, 2DH, 00H, 00H, 09H, 0BBH, 00H db 00H, 08H, 0DH, 00H, 00H, 08H, 8DH, 00H db 00H, 08H, 4DH, 00H, 00H, 09H, 0FBH, 00H db 10H, 07H, 03H, 00H, 00H, 08H, 53H, 00H db 00H, 08H, 13H, 00H, 15H, 08H, 0C3H, 00H db 13H, 07H, 23H, 00H, 00H, 08H, 73H, 00H db 00H, 08H, 33H, 00H, 00H, 09H, 0C7H, 00H db 11H, 07H, 0BH, 00H, 00H, 08H, 63H, 00H db 00H, 08H, 23H, 00H, 00H, 09H, 0A7H, 00H db 00H, 08H, 03H, 00H, 00H, 08H, 83H, 00H db 00H, 08H, 43H, 00H, 00H, 09H, 0E7H, 00H db 10H, 07H, 07H, 00H, 00H, 08H, 5BH, 00H db 00H, 08H, 1BH, 00H, 00H, 09H, 97H, 00H db 14H, 07H, 43H, 00H, 00H, 08H, 7BH, 00H db 00H, 08H, 3BH, 00H, 00H, 09H, 0D7H, 00H db 12H, 07H, 13H, 00H, 00H, 08H, 6BH, 00H db 00H, 08H, 2BH, 00H, 00H, 09H, 0B7H, 00H db 00H, 08H, 0BH, 00H, 00H, 08H, 8BH, 00H db 00H, 08H, 4BH, 00H, 00H, 09H, 0F7H, 00H db 10H, 07H, 05H, 00H, 00H, 08H, 57H, 00H db 00H, 08H, 17H, 00H, 40H, 08H, 00H, 00H db 13H, 07H, 33H, 00H, 00H, 08H, 77H, 00H db 00H, 08H, 37H, 00H, 00H, 09H, 0CFH, 00H db 11H, 07H, 0FH, 00H, 00H, 08H, 67H, 00H db 00H, 08H, 27H, 00H, 00H, 09H, 0AFH, 00H db 00H, 08H, 07H, 00H, 00H, 08H, 87H, 00H db 00H, 08H, 47H, 00H, 00H, 09H, 0EFH, 00H db 10H, 07H, 09H, 00H, 00H, 08H, 5FH, 00H db 00H, 08H, 1FH, 00H, 00H, 09H, 9FH, 00H db 14H, 07H, 63H, 00H, 00H, 08H, 7FH, 00H db 00H, 08H, 3FH, 00H, 00H, 09H, 0DFH, 00H db 12H, 07H, 1BH, 00H, 00H, 08H, 6FH, 00H db 00H, 08H, 2FH, 00H, 00H, 09H, 0BFH, 00H db 00H, 08H, 0FH, 00H, 00H, 08H, 8FH, 00H db 00H, 08H, 4FH, 00H, 00H, 09H, 0FFH, 00H @@250: db 10H, 05H, 01H, 00H, 17H, 05H, 01H, 01H db 13H, 05H, 11H, 00H, 1BH, 05H, 01H, 10H db 11H, 05H, 05H, 00H, 19H, 05H, 01H, 04H db 15H, 05H, 41H, 00H, 1DH, 05H, 01H, 40H db 10H, 05H, 03H, 00H, 18H, 05H, 01H, 02H db 14H, 05H, 21H, 00H, 1CH, 05H, 01H, 20H db 12H, 05H, 09H, 00H, 1AH, 05H, 01H, 08H db 16H, 05H, 81H, 00H, 40H, 05H, 00H, 00H db 10H, 05H, 02H, 00H, 17H, 05H, 81H, 01H db 13H, 05H, 19H, 00H, 1BH, 05H, 01H, 18H db 11H, 05H, 07H, 00H, 19H, 05H, 01H, 06H db 15H, 05H, 61H, 00H, 1DH, 05H, 01H, 60H db 10H, 05H, 04H, 00H, 18H, 05H, 01H, 03H db 14H, 05H, 31H, 00H, 1CH, 05H, 01H, 30H db 12H, 05H, 0DH, 00H, 1AH, 05H, 01H, 0CH db 16H, 05H, 0C1H, 00H, 40H, 05H, 00H, 00H @@263: db 03H, 00H, 04H, 00H, 05H, 00H, 06H, 00H db 07H, 00H, 08H, 00H, 09H, 00H, 0AH, 00H db 0BH, 00H, 0DH, 00H, 0FH, 00H, 11H, 00H db 13H, 00H, 17H, 00H, 1BH, 00H, 1FH, 00H db 23H, 00H, 2BH, 00H, 33H, 00H, 3BH, 00H db 43H, 00H, 53H, 00H, 63H, 00H, 73H, 00H db 83H, 00H, 0A3H, 00H, 0C3H, 00H, 0E3H, 00H db 02H, 01H, 00H, 00H, 00H, 00H, 00H, 00H @@264: db 10H, 00H, 10H, 00H, 10H, 00H, 10H, 00H db 10H, 00H, 10H, 00H, 10H, 00H, 10H, 00H db 11H, 00H, 11H, 00H, 11H, 00H, 11H, 00H db 12H, 00H, 12H, 00H, 12H, 00H, 12H, 00H db 13H, 00H, 13H, 00H, 13H, 00H, 13H, 00H db 14H, 00H, 14H, 00H, 14H, 00H, 14H, 00H db 15H, 00H, 15H, 00H, 15H, 00H, 15H, 00H db 10H, 00H, 0C9H, 00H, 0C4H, 00H, 00H, 00H @@265: db 01H, 00H, 02H, 00H, 03H, 00H, 04H, 00H db 05H, 00H, 07H, 00H, 09H, 00H, 0DH, 00H db 11H, 00H, 19H, 00H, 21H, 00H, 31H, 00H db 41H, 00H, 61H, 00H, 81H, 00H, 0C1H, 00H db 01H, 01H, 81H, 01H, 01H, 02H, 01H, 03H db 01H, 04H, 01H, 06H, 01H, 08H, 01H, 0CH db 01H, 10H, 01H, 18H, 01H, 20H, 01H, 30H db 01H, 40H, 01H, 60H, 00H, 00H, 00H, 00H @@266: db 10H, 00H, 10H, 00H, 10H, 00H, 10H, 00H db 11H, 00H, 11H, 00H, 12H, 00H, 12H, 00H db 13H, 00H, 13H, 00H, 14H, 00H, 14H, 00H db 15H, 00H, 15H, 00H, 16H, 00H, 16H, 00H db 17H, 00H, 17H, 00H, 18H, 00H, 18H, 00H db 19H, 00H, 19H, 00H, 1AH, 00H, 1AH, 00H db 1BH, 00H, 1BH, 00H, 1CH, 00H, 1CH, 00H db 1DH, 00H, 1DH, 00H, 40H, 00H, 40H, 00H end; function inflateEnd; asm pop ebp // auto-generated push ebp; mov ebp,esp push esi mov esi, dword ptr [esp + 08H] test esi, esi jz @@195 mov eax, dword ptr [esi + 1CH] test eax, eax jz @@195 mov ecx, dword ptr [esi + 24H] test ecx, ecx jz @@195 mov eax, dword ptr [eax + 34H] test eax, eax jz @@194 push eax mov eax, dword ptr [esi + 28H] push eax call ecx @@194: mov ecx, dword ptr [esi + 1CH] mov edx, dword ptr [esi + 28H] push ecx push edx call dword ptr [esi + 24H] mov dword ptr [esi + 1CH], 0 xor eax, eax pop esi ret 4 @@195: mov eax, -2 pop esi ret 4 end; function adler32; // our optimized asm version, faster than the original zlib C implementation asm push ebx push esi push edi mov edi,eax shr edi,16 movzx ebx,ax push ebp mov esi,edx test esi,esi mov ebp,ecx jne @31 mov eax,1 jmp @32 @31: test ebp,ebp jbe @34 @33: cmp ebp,5552 jae @35 mov eax,ebp jmp @36 nop; nop @35: mov eax,5552 @36: sub ebp,eax cmp eax,16 jl @38 xor edx,edx xor ecx,ecx @39: sub eax,16 mov dl,[esi] mov cl,[esi+1] add ebx,edx add edi,ebx add ebx,ecx mov dl,[esi+2] add edi,ebx add ebx,edx mov cl,[esi+3] add edi,ebx add ebx,ecx mov dl,[esi+4] add edi,ebx add ebx,edx mov cl,[esi+5] add edi,ebx add ebx,ecx mov dl,[esi+6] add edi,ebx add ebx,edx mov cl,[esi+7] add edi,ebx add ebx,ecx mov dl,[esi+8] add edi,ebx add ebx,edx mov cl,[esi+9] add edi,ebx add ebx,ecx mov dl,[esi+10] add edi,ebx add ebx,edx mov cl,[esi+11] add edi,ebx add ebx,ecx mov dl,[esi+12] add edi,ebx add ebx,edx mov cl,[esi+13] add edi,ebx add ebx,ecx mov dl,[esi+14] add edi,ebx add ebx,edx mov cl,[esi+15] add edi,ebx add ebx,ecx cmp eax,16 lea esi,[esi+16] lea edi,[edi+ebx] jge @39 @38: test eax,eax je @42 @43: xor edx,edx mov dl,[esi] add ebx,edx dec eax lea esi,[esi+1] lea edi,[edi+ebx] jg @43 @42: mov ecx,65521 mov eax,ebx xor edx,edx div ecx mov ebx,edx mov ecx,65521 mov eax,edi xor edx,edx div ecx test ebp,ebp mov edi,edx ja @33 @34: mov eax,edi shl eax,16 or eax,ebx @45: @32: pop ebp pop edi pop esi pop ebx end; {$define BYFOUR} // if defined, the crc32 hashing is performed using 8 tables, for better // CPU pipelining and faster execution var // tables content is created from code in initialization section below // (save 8 KB of code size from standard crc32.obj, with no speed penalty) crc32tab: array[0..{$ifdef BYFOUR}7{$else}0{$endif},byte] of cardinal; function crc32(crc: cardinal; buf: PAnsiChar; len: cardinal): cardinal; // adapted from fast Aleksandr Sharahov version asm test edx, edx jz @ret neg ecx jz @ret not eax push ebx {$ifdef BYFOUR} @head: test dl, 3 jz @bodyinit movzx ebx, byte [edx] inc edx xor bl, al shr eax, 8 xor eax,dword ptr [ebx*4 + crc32tab] inc ecx jnz @head pop ebx not eax ret @ret: rep ret @bodyinit: sub edx, ecx add ecx, 8 jg @bodydone push esi push edi mov edi, edx mov edx, eax @bodyloop: mov ebx, [edi + ecx - 4] xor edx, [edi + ecx - 8] movzx esi, bl mov eax,dword ptr [esi*4 + crc32tab + 1024*3] movzx esi, bh xor eax,dword ptr [esi*4 + crc32tab + 1024*2] shr ebx, 16 movzx esi, bl xor eax,dword ptr [esi*4 + crc32tab + 1024*1] movzx esi, bh xor eax,dword ptr [esi*4 + crc32tab + 1024*0] movzx esi, dl xor eax,dword ptr [esi*4 + crc32tab + 1024*7] movzx esi, dh xor eax,dword ptr [esi*4 + crc32tab + 1024*6] shr edx, 16 movzx esi, dl xor eax,dword ptr [esi*4 + crc32tab + 1024*5] movzx esi, dh xor eax,dword ptr [esi*4 + crc32tab + 1024*4] add ecx, 8 jg @done mov ebx, [edi + ecx - 4] xor eax, [edi + ecx - 8] movzx esi, bl mov edx,dword ptr [esi*4 + crc32tab + 1024*3] movzx esi, bh xor edx,dword ptr [esi*4 + crc32tab + 1024*2] shr ebx, 16 movzx esi, bl xor edx,dword ptr [esi*4 + crc32tab + 1024*1] movzx esi, bh xor edx,dword ptr [esi*4 + crc32tab + 1024*0] movzx esi, al xor edx,dword ptr [esi*4 + crc32tab + 1024*7] movzx esi, ah xor edx,dword ptr [esi*4 + crc32tab + 1024*6] shr eax, 16 movzx esi, al xor edx,dword ptr [esi*4 + crc32tab + 1024*5] movzx esi, ah xor edx,dword ptr [esi*4 + crc32tab + 1024*4] add ecx, 8 jle @bodyloop mov eax, edx @done: mov edx, edi pop edi pop esi @bodydone: sub ecx, 8 jl @tail pop ebx not eax ret @tail: movzx ebx,byte ptr [edx + ecx] xor bl,al shr eax,8 xor eax,dword ptr [ebx*4 + crc32tab] inc ecx jnz @tail pop ebx not eax {$else} sub edx,ecx @next: movzx ebx,byte ptr [edx + ecx] xor bl, al shr eax, 8 xor eax, [ebx*4 + crc32tab] add ecx, 1 jnz @next pop ebx not eax ret @ret: db $f3 // rep ret {$endif BYFOUR} end; function get_crc_table: pointer; begin result := @crc32tab; end; function zcalloc(AppData: Pointer; Items, Size: cardinal): Pointer; begin // direct use of the (FastMM4) delphi heap for all zip memory allocation Getmem(result,Items * Size); end; procedure zcfree(AppData, Block: Pointer); begin // direct use of the (FastMM4) delphi heap for all zip memory allocation FreeMem(Block); end; procedure _memcpy(dest, src: Pointer; count: integer); cdecl; begin // will use fastcode if compiled within Move(src^, dest^, count); end; procedure _memset(dest: Pointer; val: Integer; count: integer); cdecl; begin // will use fastcode if compiled within FillChar(dest^, count, val); end; {$else} {$ifdef USEDELPHIZLIB} // Delphi linker is really bugged -> use slow ZLib.dcu function deflate(var strm: TZStream; flush: integer): integer; cdecl; begin result := ZLib.deflate(z_stream(strm),flush); end; function deflateEnd(var strm: TZStream): integer; cdecl; begin result := ZLib.deflateEnd(z_stream(strm)); end; function inflate(var strm: TZStream; flush: integer): integer; cdecl; begin result := ZLib.inflate(z_stream(strm),flush); end; function inflateEnd(var strm: TZStream): integer; cdecl; begin result := ZLib.inflateEnd(z_stream(strm)); end; function adler32(adler: TZCRC; buf: PAnsiChar; len: cardinal): TZCRC; cdecl; begin result := ZLib.adler32(adler,pointer(buf),len); end; function crc32(crc: TZCRC; buf: PAnsiChar; len: cardinal): TZCRC; cdecl; begin result := ZLib.crc32(crc,pointer(buf),len); end; function deflateInit_(var strm: TZStream; level: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; begin result := ZLib.deflateInit_(z_stream(strm),level,version,stream_size); end; function inflateInit_(var strm: TZStream; version: PAnsiChar; stream_size: integer): integer; cdecl; begin result := ZLib.inflateInit_(z_stream(strm),version,stream_size); end; function deflateInit2_(var strm: TZStream; level, method, windowBits, memLevel, strategy: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; begin result := ZLib.deflateInit2_(z_stream(strm),level,method,windowBits,memLevel, strategy,version,stream_size); end; function inflateInit2_(var strm: TZStream; windowBits: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; begin result := ZLib.inflateInit2_(z_stream(strm),windowBits,version,stream_size); end; function get_crc_table: pointer; cdecl; begin result := ZLib.get_crc_table; end; {$endif USEDELPHIZLIB} {$ifdef FPC} // we supply our own static zlib files in coff format for Windows {$ifdef WIN32} {$LINK static\i386-win32\deflate.o} {$LINK static\i386-win32\trees.o} {$LINK static\i386-win32\zutil.o} {$LINK static\i386-win32\inffast.o} {$LINK static\i386-win32\inflate.o} {$LINK static\i386-win32\inftrees.o} {$LINK static\i386-win32\adler32.o} {$LINK static\i386-win32\crc32.o} {$linklib static\i386-win32\libmsvcrt.a} {$endif} {$ifdef WIN64} {$ifdef USEZLIBSSE} {$L static\x86_64-win64\sse\inffast.o} {$L static\x86_64-win64\sse\inftrees.o} {$L static\x86_64-win64\sse\inflate.o} {$L static\x86_64-win64\sse\deflate.o} {$L static\x86_64-win64\sse\trees.o} {$L static\x86_64-win64\sse\adler32.o} {$L static\x86_64-win64\sse\crc32.o} {$L static\x86_64-win64\sse\zutil.o} {$else USEZLIBSSE} {$L static\x86_64-win64\inffast.o} {$L static\x86_64-win64\inftrees.o} {$L static\x86_64-win64\inflate.o} {$L static\x86_64-win64\deflate.o} {$L static\x86_64-win64\trees.o} {$L static\x86_64-win64\adler32.o} {$L static\x86_64-win64\crc32.o} {$L static\x86_64-win64\zutil.o} {$endif USEZLIBSSE} {$linklib static\x86_64-win64\libmsvcrt.a} {$endif} function deflate(var strm: TZStream; flush: integer): integer; cdecl; external; function deflateEnd(var strm: TZStream): integer; cdecl; external; function inflate(var strm: TZStream; flush: integer): integer; cdecl; external; function inflateEnd(var strm: TZStream): integer; cdecl; external; function adler32(adler: TZCRC; buf: PAnsiChar; len: cardinal): TZCRC; cdecl; external; function crc32(crc: TZCRC; buf: PAnsiChar; len: cardinal): TZCRC; cdecl; external; function deflateInit_(var strm: TZStream; level: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; external; function inflateInit_(var strm: TZStream; version: PAnsiChar; stream_size: integer): integer; cdecl; external; function deflateInit2_(var strm: TZStream; level, method, windowBits, memLevel, strategy: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; external; function inflateInit2_(var strm: TZStream; windowBits: integer; version: PAnsiChar; stream_size: integer): integer; cdecl; external; {$endif FPC} {$endif USEINLINEASM} {$endif USEPASZLIB} {$endif USEEXTZLIB} function compressBound(sourceLen: cardinal): cardinal; begin result := sourceLen + (sourceLen shr 12) + (sourceLen shr 14) + 11; end; function zlibAllocMem(AppData: Pointer; Items, Size: cardinal): Pointer; cdecl; begin Getmem(result,Items * Size); end; procedure zlibFreeMem(AppData, Block: Pointer); cdecl; begin FreeMem(Block); end; procedure StreamInit(var Stream: TZStream); begin fillchar(Stream,sizeof(Stream),0); {$ifndef USEINLINEASM} {$ifndef USEPASZLIB} Stream.zalloc := @zlibAllocMem; // even under Linux, use program heap Stream.zfree := @zlibFreeMem; {$endif} {$endif} end; function DeflateInit(var Stream: TZStream; CompressionLevel: integer; ZlibFormat: Boolean): Boolean; var Bits: integer; begin if ZlibFormat then Bits := MAX_WBITS else Bits := -MAX_WBITS; result := deflateInit2_(Stream, CompressionLevel, Z_DEFLATED, Bits, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, ZLIB_VERSION, sizeof(Stream))>=0 end; function ZLibError(Code: integer): shortstring; begin case Code of Z_ERRNO: result := 'Z_ERRNO'; Z_STREAM_ERROR: result := 'Z_STREAM_ERROR'; Z_DATA_ERROR: result := 'Z_DATA_ERROR'; Z_MEM_ERROR: result := 'Z_MEM_ERROR'; Z_BUF_ERROR: result := 'Z_BUF_ERROR'; Z_VERSION_ERROR: result := 'Z_VERSION_ERROR'; else str(Code,result); end; end; function Check(const Code: Integer; const ValidCodes: array of Integer; const Context: string): integer; var i: Integer; begin if Code=Z_MEM_ERROR then OutOfMemoryError; result := code; for i := Low(ValidCodes) to High(ValidCodes) do if ValidCodes[i]=Code then Exit; raise ESynZipException.CreateFmt('Error %s during %s process',[ZLibError(Code),Context]); end; function CompressString(const data: ZipString; failIfGrow: boolean = false; CompressionLevel: integer=6) : ZipString; var i1 : integer; begin result := ''; SetLength(result, 12 + (Int64(length(data)) * 11) div 10 + 12); pInt64(result)^ := length(data); PCardinalArray(result)^[2] := adler32(0, pointer(data), length(data)); i1 := CompressMem(pointer(data), @PByteArray(result)[12], length(data), length(result) - 12, CompressionLevel); if (i1 > 0) and ( (12 + i1 < length(data)) or not failIfGrow ) then SetLength(result, 12 + i1) else result := ''; end; function UncompressString(const data: ZipString) : ZipString; begin result := ''; if Length(data) > 12 then begin SetLength(result, PCardinal(data)^); SetLength(result, UncompressMem(@PByteArray(data)[12], pointer(result), length(data) - 12, length(result))); if (result <> '') and ((Adler32(0, pointer(result), length(result))) <> PCardinalArray(data)^[2]) then result := ''; end; end; function CompressMem(src, dst: pointer; srcLen, dstLen: integer; CompressionLevel: integer=6; ZlibFormat: Boolean=false) : integer; var strm: TZStream; begin StreamInit(strm); strm.next_in := src; strm.avail_in := srcLen; strm.next_out := dst; strm.avail_out := dstLen; if DeflateInit(strm,CompressionLevel,ZlibFormat) then try Check(deflate(strm,Z_FINISH),[Z_STREAM_END,Z_OK],'CompressMem'); finally deflateEnd(strm); end; result := strm.total_out; end; type TTempBuf = record buf: pointer; temp: AnsiString; buf128k: array[0..32767] of cardinal; // IIS allows 256KB of stack size -> 128KB end; procedure InitTempBuf(var tempbuf: TTempBuf; var TempBufSize: integer); begin if TempBufSize<=sizeof(tempbuf.buf128k) then begin TempBufSize := sizeof(tempbuf.buf128k); tempbuf.buf := @tempbuf.buf128k; end else begin SetLength(tempbuf.temp,TempBufSize); tempbuf.buf := pointer(tempbuf.temp); end; end; function CompressStream(src: pointer; srcLen: integer; tmp: TStream; CompressionLevel: integer; ZlibFormat: Boolean; TempBufSize: integer): cardinal; var strm: TZStream; code: integer; temp: TTempBuf; procedure FlushBuf; var Count: integer; begin Count := TempBufSize - integer(strm.avail_out); if Count=0 then exit; tmp.WriteBuffer(temp.buf^,Count); strm.next_out := temp.buf; strm.avail_out := TempBufSize; end; begin InitTempBuf(temp,TempBufSize); StreamInit(strm); strm.next_in := src; strm.avail_in := srcLen; strm.next_out := temp.buf; strm.avail_out := TempBufSize; if DeflateInit(strm,CompressionLevel,ZlibFormat) then try repeat code := Check(deflate(strm, Z_FINISH),[Z_OK,Z_STREAM_END,Z_BUF_ERROR],'CompressStream'); FlushBuf; until code=Z_STREAM_END; FlushBuf; finally deflateEnd(strm); end; result := strm.total_out; end; function UnCompressMem(src, dst: pointer; srcLen, dstLen: integer; ZlibFormat: Boolean) : integer; var strm: TZStream; Bits: integer; begin StreamInit(strm); strm.next_in := src; strm.avail_in := srcLen; strm.next_out := dst; strm.avail_out := dstLen; if ZlibFormat then Bits := MAX_WBITS else Bits := -MAX_WBITS; // -MAX_WBITS -> no zLib header => .zip compatible ! if inflateInit2_(strm, Bits, ZLIB_VERSION, sizeof(strm))>=0 then try Check(inflate(strm, Z_FINISH),[Z_OK,Z_STREAM_END],'UnCompressMem'); finally inflateEnd(strm); end; result := strm.total_out; end; function UnCompressStream(src: pointer; srcLen: integer; tmp: TStream; checkCRC: PCardinal; ZlibFormat: Boolean; TempBufSize: integer): cardinal; var strm: TZStream; code, Bits: integer; temp: TTempBuf; procedure FlushBuf; var Count: integer; begin Count := TempBufSize - integer(strm.avail_out); if Count=0 then exit; if CheckCRC<>nil then CheckCRC^ := SynZip.crc32(CheckCRC^,temp.buf,Count); if tmp<>nil then tmp.WriteBuffer(temp.buf^,Count); strm.next_out := temp.buf; strm.avail_out := TempBufSize; end; begin InitTempBuf(temp,TempBufSize); StreamInit(strm); strm.next_in := src; strm.avail_in := srcLen; strm.next_out := temp.buf; strm.avail_out := TempBufSize; if checkCRC<>nil then CheckCRC^ := 0; if ZlibFormat then Bits := MAX_WBITS else Bits := -MAX_WBITS; // -MAX_WBITS -> no zLib header => .zip compatible ! if inflateInit2_(strm, Bits, ZLIB_VERSION, sizeof(strm))>=0 then try repeat code := Check(inflate(strm, Z_FINISH),[Z_OK,Z_STREAM_END,Z_BUF_ERROR],'UnCompressStream'); if (code=Z_BUF_ERROR) and (TempBufSize=integer(strm.avail_out)) then Check(code,[],'UnCompressStream'); // occur on invalid input FlushBuf; until code=Z_STREAM_END; FlushBuf; finally inflateEnd(strm); end; result := strm.total_out; end; function UnCompressZipString(src: pointer; srcLen: integer; out data: ZipString; checkCRC: PCardinal; ZlibFormat: Boolean; TempBufSize: integer): cardinal; // result:=dstLen checkCRC(<>nil)^:=crc32 (if aStream=nil -> fast crc calc) var strm: TZStream; len, code, Bits: integer; temp: TTempBuf; procedure FlushBuf; var Count: integer; begin Count := TempBufSize - integer(strm.avail_out); if Count=0 then exit; if CheckCRC<>nil then CheckCRC^ := SynZip.crc32(CheckCRC^,temp.buf,Count); SetLength(data,len+Count); Move(temp.buf^,PByteArray(data)[len],Count); inc(len,Count); strm.next_out := temp.buf; strm.avail_out := TempBufSize; end; begin InitTempBuf(temp,TempBufSize); len := 0; StreamInit(strm); strm.next_in := src; strm.avail_in := srcLen; strm.next_out := temp.buf; strm.avail_out := TempBufSize; if checkCRC<>nil then CheckCRC^ := 0; if ZlibFormat then Bits := MAX_WBITS else Bits := -MAX_WBITS; // -MAX_WBITS -> no zLib header => .zip compatible ! if inflateInit2_(strm, Bits, ZLIB_VERSION, sizeof(strm))>=0 then try repeat code := Check(inflate(strm, Z_FINISH),[Z_OK,Z_STREAM_END,Z_BUF_ERROR],'UnCompressZipString'); FlushBuf; until code=Z_STREAM_END; FlushBuf; finally inflateEnd(strm); end; result := strm.total_out; end; const HTTP_LEVEL = 1; // 6 is standard, but 1 is enough and faster function CompressGZip(var DataRawByteString; Compress: boolean): AnsiString; var L: integer; P: PAnsiChar; Data: ZipString absolute DataRawByteString; begin L := length(Data); if Compress then begin SetString(result,nil,L+128+L shr 3); // maximum possible memory required P := pointer(result); move(GZHEAD,P^,GZHEAD_SIZE); inc(P,GZHEAD_SIZE); inc(P,CompressMem(pointer(Data),P,L,length(result)-(GZHEAD_SIZE+8),HTTP_LEVEL)); PCardinal(P)^ := SynZip.crc32(0,pointer(Data),L); inc(P,4); PCardinal(P)^ := L; inc(P,4); SetString(Data,PAnsiChar(pointer(result)),P-pointer(result)); end else Data := gzread(pointer(Data),length(Data)); result := 'gzip'; end; procedure CompressInternal(var Data: ZipString; Compress, ZLib: boolean); var tmp: ZipString; DataLen: integer; begin tmp := Data; DataLen := length(Data); if Compress then begin SetString(Data,nil,DataLen+256+DataLen shr 3); // max mem required DataLen := CompressMem(pointer(tmp),pointer(Data),DataLen,length(Data), HTTP_LEVEL,ZLib); if DataLen<=0 then Data := '' else SetLength(Data,DataLen); end else UnCompressZipString(pointer(tmp),DataLen,Data,nil,ZLib,0); end; function CompressDeflate(var DataRawByteString; Compress: boolean): AnsiString; var Data: ZipString absolute DataRawByteString; begin CompressInternal(Data,Compress,false); result := 'deflate'; end; function CompressZLib(var DataRawByteString; Compress: boolean): AnsiString; var Data: ZipString absolute DataRawByteString; begin CompressInternal(Data,Compress,true); result := 'zlib'; end; { TLocalFileHeader } function TLocalFileHeader.LocalData: PAnsiChar; begin result := @Self; inc(result,sizeof(TLocalFileHeader)+fileInfo.extraLen+fileInfo.nameLen); end; { TFileHeader } function TFileHeader.IsFolder: boolean; begin result := extFileAttr and $00000010<>0; end; procedure TFileHeader.Init; begin fillchar(self,sizeof(TFileHeader),0); signature := ENTRY_SIGNATURE_INC; // +1 to avoid finding it in the exe dec(signature); madeBy := $14; extFileAttr := $A0; // archive, normal fileInfo.neededVersion := $14; end; { TFileInfo } function TFileInfo.AlgoID: integer; // 1..15 (1=SynLZ e.g.) from flags bits 7..10 begin // in PKware appnote, bits 7..10 of general purpose bit flag are not used result := (flags shr 7) and 15; // proprietary flag for SynZipFiles.pas end; function TFileInfo.SameAs(aInfo: PFileInfo): boolean; begin // tolerate a time change through a network: zcrc32 is accurate enough if (zzipSize=0) or (aInfo.zzipSize=0) then raise ESynZipException.Create('SameAs() with crc+sizes in "data descriptor"'); result := (zzipMethod=aInfo.zzipMethod) and (flags=aInfo.flags) and (zzipSize=aInfo.zzipSize) and (zfullSize=aInfo.zfullSize) and (zcrc32=aInfo.zcrc32); end; procedure TFileInfo.SetAlgoID(Algorithm: integer); begin zzipMethod := Z_STORED; // file is stored, accorging to .ZIP standard // in PKware appnote, bits 7..10 of general purpose bit flag are not used flags := (flags and $F87F) or (Algorithm and 15) shl 7; // proprietary flag for SynZipFiles.pas end; function TFileInfo.GetUTF8FileName: boolean; begin // from PKware appnote, Bit 11: Language encoding flag (EFS) result := (flags and (1 shl 11))<>0; end; procedure TFileInfo.SetUTF8FileName; begin flags := flags or (1 shl 11); end; procedure TFileInfo.UnSetUTF8FileName; begin flags := flags and not(1 shl 11); end; function CRC32string(const aString: ZipString): cardinal; // crc32 is better than adler32 for short strings, and fast enough in zlib 1.2.5 begin result := length(aString); if result<>0 then result := SynZip.crc32(0,pointer(aString),result); end; { TSynZipCompressor } constructor TSynZipCompressor.Create(outStream: TStream; CompressionLevel: Integer; Format: TSynZipCompressorFormat = szcfRaw); begin fDestStream := outStream; fGZFormat := (Format=szcfGZ); if fGZFormat then fDestStream.WriteBuffer(GZHEAD,GZHEAD_SIZE); StreamInit(FStrm); FStrm.next_out := @FBufferOut; FStrm.avail_out := SizeOf(FBufferOut); fInitialized := DeflateInit(FStrm,CompressionLevel,Format=szcfZip); end; procedure TSynZipCompressor.Flush; begin if FInitialized then begin while (Check(deflate(FStrm, Z_FINISH),[Z_OK, Z_STREAM_END],'Flush')<>Z_STREAM_END) and (FStrm.avail_out=0) do FlushBufferOut; FlushBufferOut; end; end; destructor TSynZipCompressor.Destroy; begin if FInitialized then begin Flush; FStrm.next_out := nil; FStrm.avail_out := 0; deflateEnd(FStrm); end; if fGZFormat then begin fDestStream.WriteBuffer(fCRC,4); fDestStream.WriteBuffer(FStrm.total_in,4); end; inherited; end; function TSynZipCompressor.SizeIn: cardinal; begin // FStrm.total_in may be integer, cardinal or ulong -> use function result := FStrm.total_in; end; function TSynZipCompressor.SizeOut: cardinal; begin // FStrm.total_out may be integer, cardinal or ulong -> use function result := FStrm.total_out; end; function TSynZipCompressor.FlushBufferOut: integer; begin result := 0; if not FInitialized then exit; if FStrm.avail_out < SizeOf(FBufferOut) then begin result := SizeOf(FBufferOut) - FStrm.avail_out; FDestStream.WriteBuffer(FBufferOut, result); FStrm.next_out := @FBufferOut; FStrm.avail_out := SizeOf(FBufferOut); end; end; function TSynZipCompressor.Read(var Buffer; Count: Integer): Longint; begin assert(false); result := 0; end; function TSynZipCompressor.Seek(Offset: Integer; Origin: Word): Longint; begin if not FInitialized then result := 0 else if (Offset = 0) and (Origin = soFromCurrent) then // for TStream.Position result := FStrm.total_in else begin result := 0; assert((Offset = 0) and (Origin = soFromBeginning) and (FStrm.total_in = 0)); end; end; function TSynZipCompressor.Write(const Buffer; Count: Integer): Longint; begin if (self=nil) or not FInitialized or (Count<=0) then begin result := 0; exit; end; result := Count; fCRC := SynZip.crc32(fCRC,@Buffer,Count); FStrm.next_in := pointer(@Buffer); FStrm.avail_in := Count; while FStrm.avail_in > 0 do begin // compress pending data if Check(deflate(FStrm, Z_NO_FLUSH), [Z_OK], 'Write')<>Z_OK then raise ESynZipException.Create('ZCompress'); if FStrm.avail_out = 0 then FlushBufferOut; end; FStrm.next_in := nil; FStrm.avail_in := 0; end; {$ifdef USEINLINEASM} { Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x (which is shifting right by one and adding x^32 mod p if the bit shifted out is a one). We start with the highest power (least significant bit) of q and repeat for all eight bits of q. The table is simply the CRC of all possible eight bit values. This is all the information needed to generate CRC's on data a byte at a time for all combinations of CRC register values and incoming bytes. } procedure InitCrc32Tab; var i,n: integer; crc: cardinal; begin // this code size is only 105 bytes, generating 8 KB table content for i := 0 to 255 do begin crc := i; for n := 1 to 8 do if (crc and 1)<>0 then // $edb88320 from polynomial p=(0,1,2,4,5,7,8,10,11,12,16,22,23,26) crc := (crc shr 1) xor $edb88320 else crc := crc shr 1; crc32tab[0,i] := crc; end; {$ifdef BYFOUR} for i := 0 to 255 do begin crc := crc32tab[0,i]; for n := 1 to 7 do begin crc := (crc shr 8) xor crc32tab[0,byte(crc)]; crc32tab[n,i] := crc; end; end; {$endif} end; initialization // crc32 tables content is created from code in initialization section below // (save 8 KB of code size from standard crc32.obj, with no speed penalty) InitCrc32Tab; {$endif USEINLINEASM} end.