Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
5632 lines (5265 sloc) 181 KB
/// 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) 2019 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) 2019
the Initial Developer. All Rights Reserved.
Contributor(s):
- Alf
- 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)
Version 1.3
- Delphi 2009/2010 compatibility (Unicode)
Version 1.3.1 - January 23, 2010
- issue corrected in CompressStream()
- compilation of TSynZipCompressor under Delphi 2009/2010, without any
Internal Error DT5830 (triggered with my Delphi 2009 Update 3)
Version 1.3.2 - February 5, 2010
- added .zip direct reading class
Version 1.4 - February 8, 2010
- whole Synopse SQLite3 database framework released under the GNU Lesser
General Public License version 3, instead of generic "Public Domain"
Version 1.5 - February 11, 2010
- added .zip direct writing class
Version 1.9
- crc32 is now coded in inlined fast asm (crc32.obj is no longer necessary)
- crc32 hashing is performed using 8 tables, for better CPU pipelining and
faster execution
- crc32 tables are created on the fly during unit initialization, therefore
save 8 KB of code size from standard crc32.obj, with no speed penalty
Version 1.9.2
- both obj files (i.e. deflate.obj and trees.obj) updated to version 1.2.5
Version 1.13
- code modifications to compile with Delphi 5 compiler
- new CompressGZip and CompressDeflate functions, for THttpSocket.RegisterCompress
- now handle Unicode file names UTF-8 encoded inside .Zip archive
- new TZipWrite.CreateFrom constructor, to add some new content to an
existing .Zip archive
- EventArchiveZip function can be used as a TSynLogArchiveEvent handler to
compress old .log files into a .zip standard archive
Version 1.15
- unit now tested with Delphi XE2 (32 Bit)
Version 1.16
- unit now compiles with Delphi XE2 (64 Bit)
- TZipWrite.AddDeflated(const aFileName) method will use streaming instead
of in-memory compression (will handle huge files much efficiently, e.g.
log files as for EventArchiveZip)
Version 1.18
- defined ZipString dedicated type, to store data in a Unicode-neutral manner
- introducing new TZipWriteToStream class, able to create a zip without file
- added TFileHeader.IsFolder and TLocalFileHeader.LocalData methods
- added TZipRead.UnZip() overloaded methods using a file name parameter
- added DestDirIsFileName optional parameter to TZipRead.UnZip() methods
- added TZipRead.UnZipAll() method
- fixed CompressDeflate() function, which was in fact creating zlib content
- fixed TZipWrite.AddDeflated() to handle data > 200 MB - thanks jpdk!
- fixed unexpected error when adding files e.g. via TZipWrite.CreateForm()
to an empty archive - thanks Gigo for the feedback!
- addded CompressZLib() function, as expected by web browsers
- any zip-related error will now raise a ESynZipException
- fixed ticket [2e22dd25aa] about TZipRead.UnMap
- fixed ticket [431b8b3dd9d] about gzread() overoptimistic assertion
- fixed UnZip() when crc and sizes are stored not within the file header,
but in a separate data descriptor block, after the compressed data (this
may occur e.g. if the .zip is created with latest Java JRE) - also added
corresponding TZipRead.RetrieveFileInfo() method and renamed TZipEntry
info field into infoLocal, and introduced infoDirectory new field
- renamed ZipFormat parameter to ZlibFormat, and introduce it also for
uncompression, so that both deflate and zlib layout are handled
- allow reading files of size 0 in TZipRead
- fixed TZipWrite.Destroy issue as reported by [aa468640c59]
- unit fixed and tested with Delphi XE2 (and up) 64-bit compiler
}
{$I Synopse.inc} // define HASINLINE USETYPEINFO 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 UNICODE}
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 UNICODE}record{$else}object{$endif}
signature : dword; // $02014b50 PK#1#2
madeBy : word; // $14
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
TLocalFileHeader = {$ifdef UNICODE}record{$else}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;
function get_crc_table: pointer; cdecl;
{$endif USEINLINEASM}
{$endif USEPASZLIB}
type
/// simple wrapper class to decompress a .gz file into memory or stream/file
{$ifdef UNICODE}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
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);
/// 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
// - update can be done manualy by using a TZipRead instance and the
// AddFromZip() method
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);
/// add a file from an already compressed zip entry
procedure AddFromZip(const ZipEntry: TZipEntry);
/// 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'
{$ifdef MSWINDOWS}
function EventArchiveZip(const aOldLogFileName, aDestinationPath: TFileName): boolean;
{$endif}
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;
{$ifdef MSWINDOWS}
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;
{$endif MSWINDOWS}
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 := $14;
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);
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 stored data
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);
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);
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;
procedure TZipWrite.AddFromZip(const ZipEntry: TZipEntry);
begin
if (self=nil) or (Handle<=0) then
exit;
if Count>=length(Entry) then
SetLength(Entry,length(Entry)+20);
with Entry[Count] do begin
fhr.fileInfo := ZipEntry.infoLocal^;
InternalAdd(ZipEntry.zipName,ZipEntry.data,fhr.fileInfo.zzipSize);
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');
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 doesn't have UTF8Decode/UTF8Encode functions -> make 7 bit version
if infoLocal^.GetUTF8FileName then
// decode UTF-8 file name into native string/TFileName type
zipName := UTF8Decode(tmp) else
{$endif}
begin
{$ifdef MSWINDOWS} // decode OEM/DOS file name into native encoding
SetLength(zipName,infoLocal^.nameLen);
OemToChar(Pointer(tmp),Pointer(zipName)); // OemToCharW/OemToCharA
{$else}
zipName := UTF8Decode(tmp); // let's assume it is UTF-8 under Linux
{$endif}
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<Count-2 then
P := Pointer(Entry[Index+1].infoLocal) else
P := Pointer(FirstFileHeader);
dec(P);
PDataStart := ZipPtrUint(Entry[Index].data);
repeat
// same pattern as ReadLocalItemDescriptor() in 7-Zip's ZipIn.cpp
// but here, search is done backwards (much faster than 7-Zip algorithm)
if P^.signature<>$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<gzlen) and (gz[offset]<>#0) do
inc(offset);
inc(offset);
end;
if gzfComment in flags then begin
fcomment := gz+offset;
while (offset<gzlen) and (gz[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 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