📄 ztvinflate.pas
字号:
// decompress
(**********************************************************************
Copyright 1998-2003, Microchip Data Systems / Carl Bunton
Under license agreement, this source module may be used only on a
single computer.
No portion of this module may be reproduced, copied, revised, edited,
distributed or transmitted via electronic means except in compiled
application format.
Web-site: http://www.ziptv.com
Email: custsupt@ziptv.com
Notes:
v6.5.1:
Proc: inflate_blocks_reset
rem'd "Or (s.mode = dtree)", see note above this line. Unable
to locate a memory allocation for this attempt at freeing mem.
**********************************************************************)
Unit ztvInflate;
Interface
Uses
Classes,
SysUtils,
ztvRegister,
ztvBase,
ztvStreams,
ztvGbls,
ztvConsts;
{$I ZipTV.inc}
{.$Define Patch112}
{$Define USE_PTR}
{.$define SLOW}
{.$define LocalDef64}
{$J+} { Writeable Typed Constants } // v4.0 added
{$Q-} { Overflow Checking } // v4.5.3 added
Function inflateInit_(z: ztv_streamp; DEF_WBITS: smallint; stream_size: _int): _int;
Function inflateEnd(Var z: ztv_stream): _int;
Function inflateReset(Var z: ztv_stream): _int;
Function _inflate(Var z: ztv_stream; f: _int): _int;
//Function inflateSetDictionary(Var z: ztv_stream; dictionary: _pBytef;
// dictLength: uInt): _int;
Function ztvDecompress_String_Method1(s: String): String;
Function ztvDecompress_String_Method2(s: String; StrLength: Integer): String;
Function ztvDecompress_BufToBuf(Const inbuf: Pointer; InBytes: _int;
Var outbuf: Pointer; Var outBytes: _int; OutEstimate: _int): u_long;
Function ztvDecompress_StreamToFile(Stream: TStream32; FileName: String): u_long;
Function ztvDecompress_StreamFromClipboard(Stream: TStream32): u_long;
Function ztvDecompress_StreamToStream(InStream, OutStream: TStream32;
InBytes: _int): u_long;
Implementation
Uses
ztvCrypt;
Const
PRESET_DICT = $20; { preset dictionary flag in header }
MANY = 1440;
BMAX = {15} 16; { maximum bit length of any code }
Const
inflate_mask: Array[0..16] Of _uInt = ($0000,
$0001, $0003, $0007, $000F, $001F, $003F, $007F, $00FF,
$01FF, $03FF, $07FF, $0FFF, $1FFF, $3FFF, $7FFF, $FFFF);
invalid_code = {112; //} 99; // v6.1 v4.8.5 revised
border: Array[0..18] Of Word { Order of the bit length code lengths }
= (16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15);
// Tables for deflate from PKZIP's appnote.txt.
cplens64: Array[0..30] Of {u_long = //}_uInt = //v6.1
(3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 3, 0, 0);
{ the code 285 is defined differently }
cplens32: Array[0..30] Of {u_long = //}_uInt = //v6.1 { Copy lengths for literal codes 257..285 }
(3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0);
{ actually lengths - 2; also see note #13 above about 258 }
// Extra bits for literal codes 257..285
cplext64: Array[0..30] Of {u_long = //}_uInt = //v6.1
(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16, invalid_code, invalid_code);
cplext32: Array[0..30] Of {u_long = //}_uInt = //v6.1
(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 , invalid_code, invalid_code);
cpdist64: Array[0..31] Of {u_long = //}_uInt = //v6.1 { Copy offsets for distance codes 0..31 }
(1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577, 32769, 49153);
{$IFDEF PKZIP_BUG_WORKAROUND}
cpdist32: Array[0..31] Of {u_long = //}_uInt = //v6.1 { Copy offsets for distance codes 0..31 }
(1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577, 32769, 49153);
{$ELSE}
cpdist32: Array[0..29] Of {u_long = //}_uInt = //v6.1 { Copy offsets for distance codes 0..29 }
(1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577);
{$ENDIF PKZIP_BUG_WORKAROUND}
cpdext64: Array[0..31] Of {u_long = //}_uInt = //v6.1 { Extra bits for distance codes }
(0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
14, 14);
{$IFDEF PKZIP_BUG_WORKAROUND}
cpdext32: Array[0..31] Of {u_long = //}_uInt = //v6.1 { Extra bits for distance codes }
(0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
INVALID_CODE, INVALID_CODE);
{$ELSE}
cpdext32: Array[0..29] Of {u_long = //}_uInt = //v6.1 { Extra bits for distance codes }
(0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13);
{$ENDIF PKZIP_BUG_WORKAROUND}
Const
FIXEDH = 544; { number of hufts used by fixed tables }
fixed_built: Boolean = False; //v4.0 rem'd... changed to a global var
Var
MaxDists: Byte;
fixed_mem: Array[0..FIXEDH - 1] Of huft;
fixed_bl: {u_long; //}_uInt; //v6.1
fixed_bd: {u_long; //}_uInt; //v6.1
fixed_tl: phuft;
fixed_td: phuft;
//-------------------------------------------------------------
Function ZALLOC(Var strm: ztv_stream; Items: _uInt; size: _uInt): voidpf;
Begin
ZALLOC := strm.ZALLOC(strm.opaque, Items, size);
End;
//-------------------------------------------------------------
Procedure ZFREE(Var strm: ztv_stream; ptr: voidpf);
Begin
strm.ZFREE(strm.opaque, ptr);
End;
//-------------------------------------------------------------
Procedure inflate_codes_free(C: pInflate_codes_state; Var z: ztv_stream);
Begin
ZFREE(z, C);
End;
//-------------------------------------------------------------
Procedure inflate_blocks_reset(Var s: inflate_blocks_state;
Var z: ztv_stream;
C: puLong); { check value on output }
Begin
If (C <> Z_NULL) Then
C^ := s.Check;
// v6.5.1 rem'd "Or (s.mode = dtree)". Using TZipKey with \3\zip\Encrypt_Xxxxx.zip,
// password of "MhWEa" causes an unknown exception. Attempts to release
// memory that wasn't (at least in this review, couldn't find the allocation)
// first allocated.
If (s.mode = BTREE) {Or (s.mode = dtree)} Then
ZFREE(z, s.sub.trees.blens);
If (s.mode = CODES) Then
inflate_codes_free(s.sub.decode.CODES, z);
s.mode := ZTYPE;
s.bitk := 0;
s.bitb := 0;
s.Write := s.window;
s.Read := s.window;
If Assigned(s.CheckFn) Then
Begin
s.Check := s.CheckFn(u_long(0), _pBytef(Nil), 0);
z.adler := s.Check;
End;
End;
//-------------------------------------------------------------
Function inflateReset(Var z: ztv_stream): _int;
Begin
If (z.state = Z_NULL) Then
Begin
Result := Z_STREAM_ERROR;
Exit;
End;
z.total_out := 0;
z.total_in := 0;
If z.state^.nowrap Then
z.state^.mode := BLOCKS
Else
z.state^.mode := method;
inflate_blocks_reset(z.state^.BLOCKS^, z, Z_NULL);
Result := Z_OK;
End;
//-------------------------------------------------------------
Function inflate_blocks_free(s: pInflate_blocks_state; Var z: ztv_stream): _int;
Begin
inflate_blocks_reset(s^, z, Z_NULL);
ZFREE(z, s^.window);
ZFREE(z, s^.hufts);
ZFREE(z, s);
Result := Z_OK;
End;
//-------------------------------------------------------------
Function inflateEnd(Var z: ztv_stream): _int;
Begin
If (z.state = Z_NULL) Or Not Assigned(z.ZFREE) Then
Begin
Result := Z_STREAM_ERROR;
Exit;
End;
If (z.state^.BLOCKS <> Z_NULL) Then
inflate_blocks_free(z.state^.BLOCKS, z);
ZFREE(z, z.state);
z.state := Z_NULL;
Result := Z_OK;
End;
//-------------------------------------------------------------
Function inflate_blocks_new(Var z: ztv_stream;
C: _check_func; { check function }
w: _uInt { window size }
): pInflate_blocks_state;
Var
s: pInflate_blocks_state;
Begin
s := pInflate_blocks_state(ZALLOC(z, 1, SizeOf(inflate_blocks_state)));
If (s = Z_NULL) Then
Begin
Result := s;
Exit;
End;
s^.hufts := huft_ptr(ZALLOC(z, SizeOf(huft), MANY));
If (s^.hufts = Z_NULL) Then
Begin
ZFREE(z, s);
Result := Z_NULL;
Exit;
End;
s^.window := _pBytef(ZALLOC(z, 1, w));
If (s^.window = Z_NULL) Then
Begin
ZFREE(z, s^.hufts);
ZFREE(z, s);
Result := Z_NULL;
Exit;
End;
s^.zend := s^.window;
inc(s^.zend, w);
s^.CheckFn := C;
s^.mode := ZTYPE;
inflate_blocks_reset(s^, z, Z_NULL);
Result := s;
End;
//-------------------------------------------------------------
Function inflateInit2_(Var z: ztv_stream;
w: _int;
stream_size: _int): _int;
Var
BitMask: Byte;
Begin
If is64Bit Then
MAXDISTS := 32
Else
{$IFDEF PKZIP_BUG_WORKAROUND}
MAXDISTS := 32;
{$ELSE}
MAXDISTS := 30;
{$ENDIF PKZIP_BUG_WORKAROUND}
If (stream_size <> SizeOf(ztv_stream)) Then
Begin
Result := Z_VERSION_ERROR;
Exit;
End;
{ SetLength(strm.msg, 255); }
If Not Assigned(z.ZALLOC) Then
Begin
z.ZALLOC := @ztvAllocMem;
z.opaque := voidpf(0);
End;
If Not Assigned(z.ZFREE) Then
z.ZFREE := @ztvFreeMem;
z.state := pInternal_state(ZALLOC(z, 1, SizeOf(internal_state)));
If (z.state = Z_NULL) Then
Begin
Result := Z_MEM_ERROR;
Exit;
End;
z.state^.BLOCKS := Z_NULL;
{ handle undocumented nowrap option (no zlib header or check) }
z.state^.nowrap := False;
If (w < 0) Then
Begin
w := -w;
z.state^.nowrap := True;
End;
BitMask := -MAX_WBITS;
If is64Bit Then
Begin
Inc(w);
Inc(BitMask);
End;
{ set window size }
If (w < 8) Or (w > BitMask) Then
Begin
inflateEnd(z);
Result := Z_STREAM_ERROR;
Exit;
End;
z.state^.wbits := _uInt(w);
{ create inflate_blocks state }
If z.state^.nowrap Then
z.state^.BLOCKS := inflate_blocks_new(z, Nil, _uInt(1) Shl w)
Else
z.state^.BLOCKS := inflate_blocks_new(z, @_adler, _uInt(1) Shl w);
If (z.state^.BLOCKS = Z_NULL) Then
Begin
inflateEnd(z);
Result := Z_MEM_ERROR;
Exit;
End;
inflateReset(z);
Result := Z_OK;
End;
//-------------------------------------------------------------
{Function inflateInit2( Var z: ztv_stream; windowBits: SmallInt ): _int;
Begin
Result := inflateInit2_( z, windowBits, SizeOf( ztv_stream ) );
End;}
//-------------------------------------------------------------
{Function inflateInit( Var z: ztv_stream; DEF_WBITS: SmallInt ): _int;
Begin
Result := inflateInit2_( z, DEF_WBITS, SizeOf( ztv_stream ) );
End;}
//-------------------------------------------------------------
Function inflateInit_(z: ztv_streamp; DEF_WBITS: smallint; stream_size: _int): _int;
Begin
If (z = Z_NULL) Then
Result := Z_STREAM_ERROR
Else
Result := inflateInit2_(z^, DEF_WBITS, stream_size);
End;
//-------------------------------------------------------------
Function inflate_flush(Var s: inflate_blocks_state; Var z: ztv_stream;
R: _int): _int;
Var
n: _uInt;
p, q: _pBytef;
Begin
p := z.next_out;
q := s.Read;
{ compute number of bytes to copy as far as end of window }
If ptr2int(q) <= ptr2int(s.Write) Then
n := _uInt(ptr2int(s.Write) - ptr2int(q))
Else
n := _uInt(ptr2int(s.zend) - ptr2int(q));
If (n > z.avail_out) Then
n := z.avail_out;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -