mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Update Compress library from RVWorld latest
This commit is contained in:
613
SabreTools.FileTypes/Compress/ZipFile/Explode/Original.c
Normal file
613
SabreTools.FileTypes/Compress/ZipFile/Explode/Original.c
Normal file
@@ -0,0 +1,613 @@
|
||||
/*
|
||||
Copyright (c) 1990-2007 Info-ZIP. All rights reserved.
|
||||
See the accompanying file LICENSE, version 2007-Mar-04 or later
|
||||
(the contents of which are also included in unzip.h) for terms of use.
|
||||
If, for some reason, all these files are missing, the Info-ZIP license
|
||||
also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
|
||||
*/
|
||||
/* explode.c -- by Mark Adler
|
||||
version c17d, 01 December 2007 */
|
||||
|
||||
|
||||
/* Copyright history:
|
||||
- Starting with UnZip 5.41 of 16-April-2000, this source file
|
||||
is covered by the Info-Zip LICENSE cited above.
|
||||
- Prior versions of this source file, found in UnZip source packages
|
||||
up to UnZip 5.40, were put in the public domain.
|
||||
The original copyright note by Mark Adler was:
|
||||
"You can do whatever you like with this source file,
|
||||
though I would prefer that if you modify it and
|
||||
redistribute it that you include comments to that effect
|
||||
with your name and the date. Thank you."
|
||||
History:
|
||||
vers date who what
|
||||
---- --------- -------------- ------------------------------------
|
||||
c1 30 Mar 92 M. Adler explode that uses huft_build from inflate
|
||||
(this gives over a 70% speed improvement
|
||||
over the original unimplode.c, which
|
||||
decoded a bit at a time)
|
||||
c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k.
|
||||
c3 10 Apr 92 M. Adler added a little memory tracking if DEBUG
|
||||
c4 11 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy()
|
||||
c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing
|
||||
the 32K window size for specialized
|
||||
applications.
|
||||
c6 31 May 92 M. Adler added typecasts to eliminate some warnings
|
||||
c7 27 Jun 92 G. Roelofs added more typecasts.
|
||||
c8 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch.
|
||||
c9 19 Jul 93 J. Bush added more typecasts (to return values);
|
||||
made l[256] array static for Amiga.
|
||||
c10 8 Oct 93 G. Roelofs added used_csize for diagnostics; added
|
||||
buf and unshrink arguments to flush();
|
||||
undef'd various macros at end for Turbo C;
|
||||
removed NEXTBYTE macro (now in unzip.h)
|
||||
and bytebuf variable (not used); changed
|
||||
memset() to memzero().
|
||||
c11 9 Jan 94 M. Adler fixed incorrect used_csize calculation.
|
||||
c12 9 Apr 94 G. Roelofs fixed split comments on preprocessor lines
|
||||
to avoid bug in Encore compiler.
|
||||
c13 25 Aug 94 M. Adler fixed distance-length comment (orig c9 fix)
|
||||
c14 22 Nov 95 S. Maxwell removed unnecessary "static" on auto array
|
||||
c15 6 Jul 96 W. Haidinger added ulg typecasts to flush() calls.
|
||||
c16 8 Feb 98 C. Spieler added ZCONST modifiers to const tables
|
||||
and #ifdef DEBUG around debugging code.
|
||||
c16b 25 Mar 98 C. Spieler modified DLL code for slide redirection.
|
||||
c16d 05 Jul 99 C. Spieler take care of flush() return values and
|
||||
stop processing in case of errors
|
||||
c17 04 Feb 01 C. Spieler reorganized code to reduce repetitions
|
||||
of large code parts; adapted huft decoding
|
||||
to the changes in inflate's huft_build()
|
||||
due to support of deflate64; fixed memory
|
||||
leaks (huft tables were not free'd when
|
||||
get_tree() failed).
|
||||
c17b 16 Feb 02 C. Spieler changed type of the "extra lengths" array
|
||||
"extra" from ush into uch (to save space)
|
||||
c17c 10 Aug 04 NN file sizes use zoff_t.
|
||||
c17d 01 Dec 07 C. Spieler type for file sizes changed from zoff_t
|
||||
into zusz_t.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Explode imploded (PKZIP method 6 compressed) data. This compression
|
||||
method searches for as much of the current string of bytes (up to a length
|
||||
of ~320) in the previous 4K or 8K bytes. If it doesn't find any matches
|
||||
(of at least length 2 or 3), it codes the next byte. Otherwise, it codes
|
||||
the length of the matched string and its distance backwards from the
|
||||
current position. Single bytes ("literals") are preceded by a one (a
|
||||
single bit) and are either uncoded (the eight bits go directly into the
|
||||
compressed stream for a total of nine bits) or Huffman coded with a
|
||||
supplied literal code tree. If literals are coded, then the minimum match
|
||||
length is three, otherwise it is two.
|
||||
There are therefore four kinds of imploded streams: 8K search with coded
|
||||
literals (min match = 3), 4K search with coded literals (min match = 3),
|
||||
8K with uncoded literals (min match = 2), and 4K with uncoded literals
|
||||
(min match = 2). The kind of stream is identified in two bits of a
|
||||
general purpose bit flag that is outside of the compressed stream.
|
||||
Distance-length pairs for matched strings are preceded by a zero bit (to
|
||||
distinguish them from literals) and are always coded. The distance comes
|
||||
first and is either the low six (4K) or low seven (8K) bits of the
|
||||
distance (uncoded), followed by the high six bits of the distance coded.
|
||||
Then the length is six bits coded (0..63 + min match length), and if the
|
||||
maximum such length is coded, then it's followed by another eight bits
|
||||
(uncoded) to be added to the coded length. This gives a match length
|
||||
range of 2..320 or 3..321 bytes.
|
||||
The literal, length, and distance codes are all represented in a slightly
|
||||
compressed form themselves. What is sent are the lengths of the codes for
|
||||
each value, which is sufficient to construct the codes. Each byte of the
|
||||
code representation is the code length (the low four bits representing
|
||||
1..16), and the number of values sequentially with that length (the high
|
||||
four bits also representing 1..16). There are 256 literal code values (if
|
||||
literals are coded), 64 length code values, and 64 distance code values,
|
||||
in that order at the beginning of the compressed stream. Each set of code
|
||||
values is preceded (redundantly) with a byte indicating how many bytes are
|
||||
in the code description that follows, in the range 1..256.
|
||||
The codes themselves are decoded using tables made by huft_build() from
|
||||
the bit lengths. That routine and its comments are in the inflate.c
|
||||
module.
|
||||
*/
|
||||
|
||||
#define __EXPLODE_C /* identifies this source module */
|
||||
#define UNZIP_INTERNAL
|
||||
#include "unzip.h" /* must supply slide[] (uch) array and NEXTBYTE macro */
|
||||
|
||||
#ifndef WSIZE
|
||||
# define WSIZE 0x8000 /* window size--must be a power of two, and */
|
||||
#endif /* at least 8K for zip's implode method */
|
||||
|
||||
#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
|
||||
# define wszimpl (unsigned)(G._wsize)
|
||||
#else
|
||||
# if defined(USE_DEFLATE64) && defined(INT_16BIT)
|
||||
# define wszimpl (unsigned)(WSIZE>>1)
|
||||
# else /* !(USE_DEFLATE64 && INT_16BIT) */
|
||||
# define wszimpl WSIZE
|
||||
# endif /* !(USE_DEFLATE64 && INT_16BIT) */
|
||||
#endif
|
||||
|
||||
/* routines here */
|
||||
static int get_tree OF((__GPRO__ unsigned* l, unsigned n));
|
||||
static int explode_lit OF((__GPRO__ struct huft* tb, struct huft* tl,
|
||||
struct huft* td, unsigned bb, unsigned bl,
|
||||
unsigned bd, unsigned bdl));
|
||||
static int explode_nolit OF((__GPRO__ struct huft* tl, struct huft* td,
|
||||
unsigned bl, unsigned bd, unsigned bdl));
|
||||
int explode OF((__GPRO));
|
||||
|
||||
|
||||
/* The implode algorithm uses a sliding 4K or 8K byte window on the
|
||||
uncompressed stream to find repeated byte strings. This is implemented
|
||||
here as a circular buffer. The index is updated simply by incrementing
|
||||
and then and'ing with 0x0fff (4K-1) or 0x1fff (8K-1). Here, the 32K
|
||||
buffer of inflate is used, and it works just as well to always have
|
||||
a 32K circular buffer, so the index is anded with 0x7fff. This is
|
||||
done to allow the window to also be used as the output buffer. */
|
||||
/* This must be supplied in an external module useable like "uch slide[8192];"
|
||||
or "uch *slide;", where the latter would be malloc'ed. In unzip, slide[]
|
||||
is actually a 32K area for use by inflate, which uses a 32K sliding window.
|
||||
*/
|
||||
|
||||
|
||||
#define INVALID_CODE 99
|
||||
#define IS_INVALID_CODE(c) ((c) == INVALID_CODE)
|
||||
|
||||
/* Tables for length and distance */
|
||||
static ZCONST ush cplen2[] =
|
||||
{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
|
||||
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65 };
|
||||
static ZCONST ush cplen3[] =
|
||||
{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
||||
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
||||
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
|
||||
53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66 };
|
||||
static ZCONST uch extra[] =
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8 };
|
||||
static ZCONST ush cpdist4[] =
|
||||
{ 1, 65, 129, 193, 257, 321, 385, 449, 513, 577, 641, 705,
|
||||
769, 833, 897, 961, 1025, 1089, 1153, 1217, 1281, 1345, 1409, 1473,
|
||||
1537, 1601, 1665, 1729, 1793, 1857, 1921, 1985, 2049, 2113, 2177,
|
||||
2241, 2305, 2369, 2433, 2497, 2561, 2625, 2689, 2753, 2817, 2881,
|
||||
2945, 3009, 3073, 3137, 3201, 3265, 3329, 3393, 3457, 3521, 3585,
|
||||
3649, 3713, 3777, 3841, 3905, 3969, 4033 };
|
||||
static ZCONST ush cpdist8[] =
|
||||
{ 1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153, 1281,
|
||||
1409, 1537, 1665, 1793, 1921, 2049, 2177, 2305, 2433, 2561, 2689,
|
||||
2817, 2945, 3073, 3201, 3329, 3457, 3585, 3713, 3841, 3969, 4097,
|
||||
4225, 4353, 4481, 4609, 4737, 4865, 4993, 5121, 5249, 5377, 5505,
|
||||
5633, 5761, 5889, 6017, 6145, 6273, 6401, 6529, 6657, 6785, 6913,
|
||||
7041, 7169, 7297, 7425, 7553, 7681, 7809, 7937, 8065 };
|
||||
|
||||
|
||||
/* Macros for inflate() bit peeking and grabbing.
|
||||
The usage is:
|
||||
NEEDBITS(j)
|
||||
x = b & mask_bits[j];
|
||||
DUMPBITS(j)
|
||||
where NEEDBITS makes sure that b has at least j bits in it, and
|
||||
DUMPBITS removes the bits from b. The macros use the variable k
|
||||
for the number of bits in b. Normally, b and k are register
|
||||
variables for speed.
|
||||
*/
|
||||
|
||||
#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
|
||||
#define DUMPBITS(n) {b>>=(n);k-=(n);}
|
||||
|
||||
#define DECODEHUFT(htab, bits, mask) {\
|
||||
NEEDBITS((unsigned)(bits))\
|
||||
t = (htab) + ((~(unsigned)b)&(mask));\
|
||||
while (1) {\
|
||||
DUMPBITS(t->b)\
|
||||
if ((e=t->e) <= 32) break;\
|
||||
if (IS_INVALID_CODE(e)) return 1;\
|
||||
e &= 31;\
|
||||
NEEDBITS(e)\
|
||||
t = t->v.t + ((~(unsigned)b)&mask_bits[e]);\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
static int get_tree(__G__ l, n)
|
||||
__GDEF
|
||||
unsigned* l; /* bit lengths */
|
||||
unsigned n; /* number expected */
|
||||
/* Get the bit lengths for a code representation from the compressed
|
||||
stream. If get_tree() returns 4, then there is an error in the data.
|
||||
Otherwise zero is returned. */
|
||||
{
|
||||
unsigned i; /* bytes remaining in list */
|
||||
unsigned k; /* lengths entered */
|
||||
unsigned j; /* number of codes */
|
||||
unsigned b; /* bit length for those codes */
|
||||
|
||||
|
||||
/* get bit lengths */
|
||||
i = NEXTBYTE + 1; /* length/count pairs to read */
|
||||
k = 0; /* next code */
|
||||
do {
|
||||
b = ((j = NEXTBYTE) & 0xf) + 1; /* bits in code (1..16) */
|
||||
j = ((j & 0xf0) >> 4) + 1; /* codes with those bits (1..16) */
|
||||
if (k + j > n)
|
||||
return 4; /* don't overflow l[] */
|
||||
do {
|
||||
l[k++] = b;
|
||||
} while (--j);
|
||||
} while (--i);
|
||||
return k != n ? 4 : 0; /* should have read n of them */
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int explode_lit(__G__ tb, tl, td, bb, bl, bd, bdl)
|
||||
__GDEF
|
||||
struct huft* tb, * tl, * td; /* literal, length, and distance tables */
|
||||
unsigned bb, bl, bd; /* number of bits decoded by those */
|
||||
unsigned bdl; /* number of distance low bits */
|
||||
/* Decompress the imploded data using coded literals and a sliding
|
||||
window (of size 2^(6+bdl) bytes). */
|
||||
{
|
||||
zusz_t s; /* bytes to decompress */
|
||||
register unsigned e; /* table entry flag/number of extra bits */
|
||||
unsigned n, d; /* length and index for copy */
|
||||
unsigned w; /* current window position */
|
||||
struct huft* t; /* pointer to table entry */
|
||||
unsigned mb, ml, md; /* masks for bb, bl, and bd bits */
|
||||
unsigned mdl; /* mask for bdl (distance lower) bits */
|
||||
register ulg b; /* bit buffer */
|
||||
register unsigned k; /* number of bits in bit buffer */
|
||||
unsigned u; /* true if unflushed */
|
||||
int retval = 0; /* error code returned: initialized to "no error" */
|
||||
|
||||
|
||||
/* explode the coded data */
|
||||
b = k = w = 0; /* initialize bit buffer, window */
|
||||
u = 1; /* buffer unflushed */
|
||||
mb = mask_bits[bb]; /* precompute masks for speed */
|
||||
ml = mask_bits[bl];
|
||||
md = mask_bits[bd];
|
||||
mdl = mask_bits[bdl];
|
||||
s = G.lrec.ucsize;
|
||||
while (s > 0) /* do until ucsize bytes uncompressed */
|
||||
{
|
||||
NEEDBITS(1)
|
||||
if (b & 1) /* then literal--decode it */
|
||||
{
|
||||
DUMPBITS(1)
|
||||
s--;
|
||||
DECODEHUFT(tb, bb, mb) /* get coded literal */
|
||||
redirSlide[w++] = (uch)t->v.n;
|
||||
if (w == wszimpl)
|
||||
{
|
||||
if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)
|
||||
return retval;
|
||||
w = u = 0;
|
||||
}
|
||||
}
|
||||
else /* else distance/length */
|
||||
{
|
||||
DUMPBITS(1)
|
||||
NEEDBITS(bdl) /* get distance low bits */
|
||||
d = (unsigned)b & mdl;
|
||||
DUMPBITS(bdl)
|
||||
DECODEHUFT(td, bd, md) /* get coded distance high bits */
|
||||
d = w - d - t->v.n; /* construct offset */
|
||||
DECODEHUFT(tl, bl, ml) /* get coded length */
|
||||
n = t->v.n;
|
||||
if (e) /* get length extra bits */
|
||||
{
|
||||
NEEDBITS(8)
|
||||
n += (unsigned)b & 0xff;
|
||||
DUMPBITS(8)
|
||||
}
|
||||
|
||||
/* do the copy */
|
||||
s = (s > (zusz_t)n ? s - (zusz_t)n : 0);
|
||||
do {
|
||||
#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
|
||||
if (G.redirect_slide) {
|
||||
/* &= w/ wszimpl not needed and wrong if redirect */
|
||||
if (d >= wszimpl)
|
||||
return 1;
|
||||
e = wszimpl - (d > w ? d : w);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
e = wszimpl - ((d &= wszimpl - 1) > w ? d : w);
|
||||
if (e > n) e = n;
|
||||
n -= e;
|
||||
if (u && w <= d)
|
||||
{
|
||||
memzero(redirSlide + w, e);
|
||||
w += e;
|
||||
d += e;
|
||||
}
|
||||
else
|
||||
#ifndef NOMEMCPY
|
||||
if (w - d >= e) /* (this test assumes unsigned comparison) */
|
||||
{
|
||||
memcpy(redirSlide + w, redirSlide + d, e);
|
||||
w += e;
|
||||
d += e;
|
||||
}
|
||||
else /* do it slow to avoid memcpy() overlap */
|
||||
#endif /* !NOMEMCPY */
|
||||
do {
|
||||
redirSlide[w++] = redirSlide[d++];
|
||||
} while (--e);
|
||||
if (w == wszimpl)
|
||||
{
|
||||
if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)
|
||||
return retval;
|
||||
w = u = 0;
|
||||
}
|
||||
} while (n);
|
||||
}
|
||||
}
|
||||
|
||||
/* flush out redirSlide */
|
||||
if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)
|
||||
return retval;
|
||||
if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */
|
||||
{ /* sometimes read one too many: k>>3 compensates */
|
||||
G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
|
||||
return 5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int explode_nolit(__G__ tl, td, bl, bd, bdl)
|
||||
__GDEF
|
||||
struct huft* tl, * td; /* length and distance decoder tables */
|
||||
unsigned bl, bd; /* number of bits decoded by tl[] and td[] */
|
||||
unsigned bdl; /* number of distance low bits */
|
||||
/* Decompress the imploded data using uncoded literals and a sliding
|
||||
window (of size 2^(6+bdl) bytes). */
|
||||
{
|
||||
zusz_t s; /* bytes to decompress */
|
||||
register unsigned e; /* table entry flag/number of extra bits */
|
||||
unsigned n, d; /* length and index for copy */
|
||||
unsigned w; /* current window position */
|
||||
struct huft* t; /* pointer to table entry */
|
||||
unsigned ml, md; /* masks for bl and bd bits */
|
||||
unsigned mdl; /* mask for bdl (distance lower) bits */
|
||||
register ulg b; /* bit buffer */
|
||||
register unsigned k; /* number of bits in bit buffer */
|
||||
unsigned u; /* true if unflushed */
|
||||
int retval = 0; /* error code returned: initialized to "no error" */
|
||||
|
||||
|
||||
/* explode the coded data */
|
||||
b = k = w = 0; /* initialize bit buffer, window */
|
||||
u = 1; /* buffer unflushed */
|
||||
ml = mask_bits[bl]; /* precompute masks for speed */
|
||||
md = mask_bits[bd];
|
||||
mdl = mask_bits[bdl];
|
||||
s = G.lrec.ucsize;
|
||||
while (s > 0) /* do until ucsize bytes uncompressed */
|
||||
{
|
||||
NEEDBITS(1)
|
||||
if (b & 1) /* then literal--get eight bits */
|
||||
{
|
||||
DUMPBITS(1)
|
||||
s--;
|
||||
NEEDBITS(8)
|
||||
redirSlide[w++] = (uch)b;
|
||||
if (w == wszimpl)
|
||||
{
|
||||
if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)
|
||||
return retval;
|
||||
w = u = 0;
|
||||
}
|
||||
DUMPBITS(8)
|
||||
}
|
||||
else /* else distance/length */
|
||||
{
|
||||
DUMPBITS(1)
|
||||
NEEDBITS(bdl) /* get distance low bits */
|
||||
d = (unsigned)b & mdl;
|
||||
DUMPBITS(bdl)
|
||||
DECODEHUFT(td, bd, md) /* get coded distance high bits */
|
||||
d = w - d - t->v.n; /* construct offset */
|
||||
DECODEHUFT(tl, bl, ml) /* get coded length */
|
||||
n = t->v.n;
|
||||
if (e) /* get length extra bits */
|
||||
{
|
||||
NEEDBITS(8)
|
||||
n += (unsigned)b & 0xff;
|
||||
DUMPBITS(8)
|
||||
}
|
||||
|
||||
/* do the copy */
|
||||
s = (s > (zusz_t)n ? s - (zusz_t)n : 0);
|
||||
do {
|
||||
#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
|
||||
if (G.redirect_slide) {
|
||||
/* &= w/ wszimpl not needed and wrong if redirect */
|
||||
if (d >= wszimpl)
|
||||
return 1;
|
||||
e = wszimpl - (d > w ? d : w);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
e = wszimpl - ((d &= wszimpl - 1) > w ? d : w);
|
||||
if (e > n) e = n;
|
||||
n -= e;
|
||||
if (u && w <= d)
|
||||
{
|
||||
memzero(redirSlide + w, e);
|
||||
w += e;
|
||||
d += e;
|
||||
}
|
||||
else
|
||||
#ifndef NOMEMCPY
|
||||
if (w - d >= e) /* (this test assumes unsigned comparison) */
|
||||
{
|
||||
memcpy(redirSlide + w, redirSlide + d, e);
|
||||
w += e;
|
||||
d += e;
|
||||
}
|
||||
else /* do it slow to avoid memcpy() overlap */
|
||||
#endif /* !NOMEMCPY */
|
||||
do {
|
||||
redirSlide[w++] = redirSlide[d++];
|
||||
} while (--e);
|
||||
if (w == wszimpl)
|
||||
{
|
||||
if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)
|
||||
return retval;
|
||||
w = u = 0;
|
||||
}
|
||||
} while (n);
|
||||
}
|
||||
}
|
||||
|
||||
/* flush out redirSlide */
|
||||
if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)
|
||||
return retval;
|
||||
if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */
|
||||
{ /* sometimes read one too many: k>>3 compensates */
|
||||
G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
|
||||
return 5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int explode(__G)
|
||||
__GDEF
|
||||
/* Explode an imploded compressed stream. Based on the general purpose
|
||||
bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding
|
||||
window. Construct the literal (if any), length, and distance codes and
|
||||
the tables needed to decode them (using huft_build() from inflate.c),
|
||||
and call the appropriate routine for the type of data in the remainder
|
||||
of the stream. The four routines are nearly identical, differing only
|
||||
in whether the literal is decoded or simply read in, and in how many
|
||||
bits are read in, uncoded, for the low distance bits. */
|
||||
{
|
||||
unsigned r; /* return codes */
|
||||
struct huft* tb; /* literal code table */
|
||||
struct huft* tl; /* length code table */
|
||||
struct huft* td; /* distance code table */
|
||||
unsigned bb; /* bits for tb */
|
||||
unsigned bl; /* bits for tl */
|
||||
unsigned bd; /* bits for td */
|
||||
unsigned bdl; /* number of uncoded lower distance bits */
|
||||
unsigned l[256]; /* bit lengths for codes */
|
||||
|
||||
#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
|
||||
if (G.redirect_slide)
|
||||
/* For 16-bit systems, it has already been checked at DLL entrance that
|
||||
* the buffer size in G.redirect_size does not exceed unsigned range.
|
||||
*/
|
||||
G._wsize = G.redirect_size, redirSlide = G.redirect_buffer;
|
||||
else
|
||||
#if defined(USE_DEFLATE64) && defined(INT_16BIT)
|
||||
/* For systems using 16-bit ints, reduce the used buffer size below
|
||||
* the limit of "unsigned int" numbers range.
|
||||
*/
|
||||
G._wsize = WSIZE >> 1, redirSlide = slide;
|
||||
#else /* !(USE_DEFLATE64 && INT_16BIT) */
|
||||
G._wsize = WSIZE, redirSlide = slide;
|
||||
#endif /* !(USE_DEFLATE64 && INT_16BIT) */
|
||||
#endif /* DLL && !NO_SLIDE_REDIR */
|
||||
|
||||
/* Tune base table sizes. Note: I thought that to truly optimize speed,
|
||||
I would have to select different bl, bd, and bb values for different
|
||||
compressed file sizes. I was surprised to find out that the values of
|
||||
7, 7, and 9 worked best over a very wide range of sizes, except that
|
||||
bd = 8 worked marginally better for large compressed sizes. */
|
||||
bl = 7;
|
||||
bd = (G.csize + G.incnt) > 200000L ? 8 : 7;
|
||||
|
||||
#ifdef DEBUG
|
||||
G.hufts = 0; /* initialize huft's malloc'ed */
|
||||
#endif
|
||||
|
||||
if (G.lrec.general_purpose_bit_flag & 4)
|
||||
/* With literal tree--minimum match length is 3 */
|
||||
{
|
||||
bb = 9; /* base table size for literals */
|
||||
if ((r = get_tree(__G__ l, 256)) != 0)
|
||||
return (int)r;
|
||||
if ((r = huft_build(__G__ l, 256, 256, NULL, NULL, &tb, &bb)) != 0)
|
||||
{
|
||||
if (r == 1)
|
||||
huft_free(tb);
|
||||
return (int)r;
|
||||
}
|
||||
if ((r = get_tree(__G__ l, 64)) != 0) {
|
||||
huft_free(tb);
|
||||
return (int)r;
|
||||
}
|
||||
if ((r = huft_build(__G__ l, 64, 0, cplen3, extra, &tl, &bl)) != 0)
|
||||
{
|
||||
if (r == 1)
|
||||
huft_free(tl);
|
||||
huft_free(tb);
|
||||
return (int)r;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* No literal tree--minimum match length is 2 */
|
||||
{
|
||||
tb = (struct huft*)NULL;
|
||||
if ((r = get_tree(__G__ l, 64)) != 0)
|
||||
return (int)r;
|
||||
if ((r = huft_build(__G__ l, 64, 0, cplen2, extra, &tl, &bl)) != 0)
|
||||
{
|
||||
if (r == 1)
|
||||
huft_free(tl);
|
||||
return (int)r;
|
||||
}
|
||||
}
|
||||
|
||||
if ((r = get_tree(__G__ l, 64)) != 0) {
|
||||
huft_free(tl);
|
||||
if (tb != (struct huft*)NULL) huft_free(tb);
|
||||
return (int)r;
|
||||
}
|
||||
if (G.lrec.general_purpose_bit_flag & 2) /* true if 8K */
|
||||
{
|
||||
bdl = 7;
|
||||
r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd);
|
||||
}
|
||||
else /* else 4K */
|
||||
{
|
||||
bdl = 6;
|
||||
r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd);
|
||||
}
|
||||
if (r != 0)
|
||||
{
|
||||
if (r == 1)
|
||||
huft_free(td);
|
||||
huft_free(tl);
|
||||
if (tb != (struct huft*)NULL) huft_free(tb);
|
||||
return (int)r;
|
||||
}
|
||||
|
||||
if (tb != NULL) {
|
||||
r = explode_lit(__G__ tb, tl, td, bb, bl, bd, bdl);
|
||||
huft_free(tb);
|
||||
}
|
||||
else {
|
||||
r = explode_nolit(__G__ tl, td, bl, bd, bdl);
|
||||
}
|
||||
|
||||
huft_free(td);
|
||||
huft_free(tl);
|
||||
Trace((stderr, "<%u > ", G.hufts));
|
||||
return (int)r;
|
||||
}
|
||||
|
||||
/* so explode.c and inflate.c can be compiled together into one object: */
|
||||
#undef DECODEHUFT
|
||||
#undef NEEDBITS
|
||||
#undef DUMPBITS
|
||||
#undef wszimpl
|
||||
@@ -157,14 +157,14 @@ namespace Compress.ZipFile.ZLib
|
||||
{
|
||||
"need dictionary",
|
||||
"stream end",
|
||||
string.Empty,
|
||||
"",
|
||||
"file error",
|
||||
"stream error",
|
||||
"data error",
|
||||
"insufficient memory",
|
||||
"buffer error",
|
||||
"incompatible version",
|
||||
string.Empty
|
||||
""
|
||||
};
|
||||
|
||||
// preset dictionary flag in zlib header
|
||||
@@ -545,10 +545,10 @@ namespace Compress.ZipFile.ZLib
|
||||
internal void send_tree(short[] tree, int max_code)
|
||||
{
|
||||
int n; // iterates over all tree elements
|
||||
int prevlen = -1; // last emitted length
|
||||
int prevlen = -1; // last emitted length
|
||||
int curlen; // length of current code
|
||||
int nextlen = tree[0 * 2 + 1]; // length of next code
|
||||
int count = 0; // repeat count of the current code
|
||||
int nextlen = tree[0 * 2 + 1]; // length of next code
|
||||
int count = 0; // repeat count of the current code
|
||||
int max_count = 7; // max repeat count
|
||||
int min_count = 4; // min repeat count
|
||||
|
||||
@@ -729,7 +729,7 @@ namespace Compress.ZipFile.ZLib
|
||||
* *
|
||||
* this code is not turned on by default in ZLIB Trrntzip code *
|
||||
* *
|
||||
* *************************************************************
|
||||
* *************************************************************
|
||||
*/
|
||||
if (false) //CompSettings
|
||||
{
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
// Inftree.cs
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
|
||||
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code module is part of DotNetZip, a zipfile class library.
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// This code is licensed under the Microsoft Public License.
|
||||
// This code is licensed under the Microsoft Public License.
|
||||
// See the file License.txt for the license details.
|
||||
// More info on: http://dotnetzip.codeplex.com
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// last saved (in emacs):
|
||||
// last saved (in emacs):
|
||||
// Time-stamp: <2009-October-28 12:43:54>
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// This module defines classes used in decompression. This code is derived
|
||||
// from the jzlib implementation of zlib. In keeping with the license for jzlib,
|
||||
// from the jzlib implementation of zlib. In keeping with the license for jzlib,
|
||||
// the copyright to that code is below.
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in
|
||||
// the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
//
|
||||
// 3. The names of the authors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
@@ -50,7 +50,7 @@
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
// This program is based on zlib-1.1.3; credit to authors
|
||||
@@ -64,373 +64,373 @@ using System;
|
||||
|
||||
namespace Compress.ZipFile.ZLib
|
||||
{
|
||||
|
||||
sealed class InfTree
|
||||
{
|
||||
|
||||
private const int MANY = 1440;
|
||||
|
||||
private const int Z_OK = 0;
|
||||
private const int Z_STREAM_END = 1;
|
||||
private const int Z_NEED_DICT = 2;
|
||||
private const int Z_ERRNO = -1;
|
||||
private const int Z_STREAM_ERROR = -2;
|
||||
private const int Z_DATA_ERROR = -3;
|
||||
private const int Z_MEM_ERROR = -4;
|
||||
private const int Z_BUF_ERROR = -5;
|
||||
private const int Z_VERSION_ERROR = -6;
|
||||
|
||||
internal const int fixed_bl = 9;
|
||||
internal const int fixed_bd = 5;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'fixed_tl'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] fixed_tl = new int[]{96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 192, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 160, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 224, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 144, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 208, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 176, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 240, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 200, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 168, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 232, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 152, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 216, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 184, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 248, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 196, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 164, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 228, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 148, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 212, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 180, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 244, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 204, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 172, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 236, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 156, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 220, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 188, 0, 8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 252, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 194, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 162, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 226, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 146, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 210, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 178, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 242, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 202, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 170, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 234, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 154, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 218, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 186,
|
||||
0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 250, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 198, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 166, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 230, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 150, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 214, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 182, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 246, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 206, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 174, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 238, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 158, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 222, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 190, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 254, 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 193, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 161, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 225, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 145, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 209, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 177, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 241, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 201, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 169, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 233, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 153, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 217, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 185, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 249, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 197, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 165, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 229, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 149, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 213, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 181, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 245, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 205, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 173, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 237, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 157, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 221, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 189, 0, 8,
|
||||
14, 0, 8, 142, 0, 8, 78, 0, 9, 253, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 195, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 163, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 227, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 147, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 211, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 179, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 243, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 203, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 171, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 235, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 155, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 219, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 187, 0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 251, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 199, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 167, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 231, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 151, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 215, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 183, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 247, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 207, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 175, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 239, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 159, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 223, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 191, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 255};
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'fixed_td'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] fixed_td = new int[] { 80, 5, 1, 87, 5, 257, 83, 5, 17, 91, 5, 4097, 81, 5, 5, 89, 5, 1025, 85, 5, 65, 93, 5, 16385, 80, 5, 3, 88, 5, 513, 84, 5, 33, 92, 5, 8193, 82, 5, 9, 90, 5, 2049, 86, 5, 129, 192, 5, 24577, 80, 5, 2, 87, 5, 385, 83, 5, 25, 91, 5, 6145, 81, 5, 7, 89, 5, 1537, 85, 5, 97, 93, 5, 24577, 80, 5, 4, 88, 5, 769, 84, 5, 49, 92, 5, 12289, 82, 5, 13, 90, 5, 3073, 86, 5, 193, 192, 5, 24577 };
|
||||
|
||||
// Tables for deflate from PKZIP's appnote.txt.
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'cplens'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] cplens = new int[] { 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 };
|
||||
|
||||
// see note #13 above about 258
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'cplext'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] cplext = new int[] { 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, 112, 112 };
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'cpdist'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] cpdist = new int[] { 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 };
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'cpdext'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] cpdext = new int[] { 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 };
|
||||
|
||||
// If BMAX needs to be larger than 16, then h and x[] should be uLong.
|
||||
internal const int BMAX = 15; // maximum bit length of any code
|
||||
|
||||
internal int[] hn = null; // hufts used in space
|
||||
internal int[] v = null; // work area for huft_build
|
||||
internal int[] c = null; // bit length count table
|
||||
internal int[] r = null; // table entry for structure assignment
|
||||
internal int[] u = null; // table stack
|
||||
internal int[] x = null; // bit offsets, then code stack
|
||||
|
||||
private int huft_build(int[] b, int bindex, int n, int s, int[] d, int[] e, int[] t, int[] m, int[] hp, int[] hn, int[] v)
|
||||
|
||||
sealed class InfTree
|
||||
{
|
||||
// Given a list of code lengths and a maximum table size, make a set of
|
||||
// tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
|
||||
// if the given code set is incomplete (the tables are still built in this
|
||||
// case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
|
||||
// lengths), or Z_MEM_ERROR if not enough memory.
|
||||
|
||||
int a; // counter for codes of length k
|
||||
int f; // i repeats in table every f entries
|
||||
int g; // maximum code length
|
||||
int h; // table level
|
||||
int i; // counter, current code
|
||||
int j; // counter
|
||||
int k; // number of bits in current code
|
||||
int l; // bits per table (returned in m)
|
||||
int mask; // (1 << w) - 1, to avoid cc -O bug on HP
|
||||
int p; // pointer into c[], b[], or v[]
|
||||
int q; // points to current table
|
||||
int w; // bits before this table == (l * h)
|
||||
int xp; // pointer into x
|
||||
int y; // number of dummy codes added
|
||||
int z; // number of entries in current table
|
||||
|
||||
// Generate counts for each bit length
|
||||
|
||||
p = 0; i = n;
|
||||
do
|
||||
{
|
||||
c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
|
||||
}
|
||||
while (i != 0);
|
||||
|
||||
if (c[0] == n)
|
||||
{
|
||||
// null input--all zero length codes
|
||||
t[0] = -1;
|
||||
m[0] = 0;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
// Find minimum and maximum length, bound *m by those
|
||||
l = m[0];
|
||||
for (j = 1; j <= BMAX; j++)
|
||||
if (c[j] != 0)
|
||||
break;
|
||||
k = j; // minimum code length
|
||||
if (l < j)
|
||||
{
|
||||
l = j;
|
||||
}
|
||||
for (i = BMAX; i != 0; i--)
|
||||
{
|
||||
if (c[i] != 0)
|
||||
break;
|
||||
}
|
||||
g = i; // maximum code length
|
||||
if (l > i)
|
||||
{
|
||||
l = i;
|
||||
}
|
||||
m[0] = l;
|
||||
|
||||
// Adjust last length count to fill out codes, if needed
|
||||
for (y = 1 << j; j < i; j++, y <<= 1)
|
||||
{
|
||||
if ((y -= c[j]) < 0)
|
||||
|
||||
private const int MANY = 1440;
|
||||
|
||||
private const int Z_OK = 0;
|
||||
private const int Z_STREAM_END = 1;
|
||||
private const int Z_NEED_DICT = 2;
|
||||
private const int Z_ERRNO = - 1;
|
||||
private const int Z_STREAM_ERROR = - 2;
|
||||
private const int Z_DATA_ERROR = - 3;
|
||||
private const int Z_MEM_ERROR = - 4;
|
||||
private const int Z_BUF_ERROR = - 5;
|
||||
private const int Z_VERSION_ERROR = - 6;
|
||||
|
||||
internal const int fixed_bl = 9;
|
||||
internal const int fixed_bd = 5;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'fixed_tl'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] fixed_tl = new int[]{96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 192, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 160, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 224, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 144, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 208, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 176, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 240, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 200, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 168, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 232, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 152, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 216, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 184, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 248, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 196, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 164, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 228, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 148, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 212, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 180, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 244, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 204, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 172, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 236, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 156, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 220, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 188, 0, 8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 252, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 194, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 162, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 226, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 146, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 210, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 178, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 242, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 202, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 170, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 234, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 154, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 218, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 186,
|
||||
0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 250, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 198, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 166, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 230, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 150, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 214, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 182, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 246, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 206, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 174, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 238, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 158, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 222, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 190, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 254, 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 193, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 161, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 225, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 145, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 209, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 177, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 241, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 201, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 169, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 233, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 153, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 217, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 185, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 249, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 197, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 165, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 229, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 149, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 213, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 181, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 245, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 205, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 173, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 237, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 157, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 221, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 189, 0, 8,
|
||||
14, 0, 8, 142, 0, 8, 78, 0, 9, 253, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 195, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 163, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 227, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 147, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 211, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 179, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 243, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 203, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 171, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 235, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 155, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 219, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 187, 0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 251, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 199, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 167, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 231, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 151, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 215, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 183, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 247, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 207, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 175, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 239, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 159, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 223, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 191, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 255};
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'fixed_td'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] fixed_td = new int[]{80, 5, 1, 87, 5, 257, 83, 5, 17, 91, 5, 4097, 81, 5, 5, 89, 5, 1025, 85, 5, 65, 93, 5, 16385, 80, 5, 3, 88, 5, 513, 84, 5, 33, 92, 5, 8193, 82, 5, 9, 90, 5, 2049, 86, 5, 129, 192, 5, 24577, 80, 5, 2, 87, 5, 385, 83, 5, 25, 91, 5, 6145, 81, 5, 7, 89, 5, 1537, 85, 5, 97, 93, 5, 24577, 80, 5, 4, 88, 5, 769, 84, 5, 49, 92, 5, 12289, 82, 5, 13, 90, 5, 3073, 86, 5, 193, 192, 5, 24577};
|
||||
|
||||
// Tables for deflate from PKZIP's appnote.txt.
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'cplens'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] cplens = new int[]{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};
|
||||
|
||||
// see note #13 above about 258
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'cplext'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] cplext = new int[]{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, 112, 112};
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'cpdist'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] cpdist = new int[]{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};
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'cpdext'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] cpdext = new int[]{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};
|
||||
|
||||
// If BMAX needs to be larger than 16, then h and x[] should be uLong.
|
||||
internal const int BMAX = 15; // maximum bit length of any code
|
||||
|
||||
internal int[] hn = null; // hufts used in space
|
||||
internal int[] v = null; // work area for huft_build
|
||||
internal int[] c = null; // bit length count table
|
||||
internal int[] r = null; // table entry for structure assignment
|
||||
internal int[] u = null; // table stack
|
||||
internal int[] x = null; // bit offsets, then code stack
|
||||
|
||||
private int huft_build(int[] b, int bindex, int n, int s, int[] d, int[] e, int[] t, int[] m, int[] hp, int[] hn, int[] v)
|
||||
{
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
}
|
||||
if ((y -= c[i]) < 0)
|
||||
{
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
c[i] += y;
|
||||
|
||||
// Generate starting offsets into the value table for each length
|
||||
x[1] = j = 0;
|
||||
p = 1; xp = 2;
|
||||
while (--i != 0)
|
||||
{
|
||||
// note that i == g from above
|
||||
x[xp] = (j += c[p]);
|
||||
xp++;
|
||||
p++;
|
||||
}
|
||||
|
||||
// Make a table of values in order of bit lengths
|
||||
i = 0; p = 0;
|
||||
do
|
||||
{
|
||||
if ((j = b[bindex + p]) != 0)
|
||||
{
|
||||
v[x[j]++] = i;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
while (++i < n);
|
||||
n = x[g]; // set n to length of v
|
||||
|
||||
// Generate the Huffman codes and for each, make the table entries
|
||||
x[0] = i = 0; // first Huffman code is zero
|
||||
p = 0; // grab values in bit order
|
||||
h = -1; // no tables yet--level -1
|
||||
w = -l; // bits decoded == (l * h)
|
||||
u[0] = 0; // just to keep compilers happy
|
||||
q = 0; // ditto
|
||||
z = 0; // ditto
|
||||
|
||||
// go through the bit lengths (k already is bits in shortest code)
|
||||
for (; k <= g; k++)
|
||||
{
|
||||
a = c[k];
|
||||
while (a-- != 0)
|
||||
{
|
||||
// here i is the Huffman code of length k bits for value *p
|
||||
// make tables up to required level
|
||||
while (k > w + l)
|
||||
{
|
||||
h++;
|
||||
w += l; // previous table always l bits
|
||||
// compute minimum size table less than or equal to l bits
|
||||
z = g - w;
|
||||
z = (z > l) ? l : z; // table size upper limit
|
||||
if ((f = 1 << (j = k - w)) > a + 1)
|
||||
// Given a list of code lengths and a maximum table size, make a set of
|
||||
// tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
|
||||
// if the given code set is incomplete (the tables are still built in this
|
||||
// case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
|
||||
// lengths), or Z_MEM_ERROR if not enough memory.
|
||||
|
||||
int a; // counter for codes of length k
|
||||
int f; // i repeats in table every f entries
|
||||
int g; // maximum code length
|
||||
int h; // table level
|
||||
int i; // counter, current code
|
||||
int j; // counter
|
||||
int k; // number of bits in current code
|
||||
int l; // bits per table (returned in m)
|
||||
int mask; // (1 << w) - 1, to avoid cc -O bug on HP
|
||||
int p; // pointer into c[], b[], or v[]
|
||||
int q; // points to current table
|
||||
int w; // bits before this table == (l * h)
|
||||
int xp; // pointer into x
|
||||
int y; // number of dummy codes added
|
||||
int z; // number of entries in current table
|
||||
|
||||
// Generate counts for each bit length
|
||||
|
||||
p = 0; i = n;
|
||||
do
|
||||
{
|
||||
// try a k-w bit table
|
||||
// too few codes for k-w bit table
|
||||
f -= (a + 1); // deduct codes from patterns left
|
||||
xp = k;
|
||||
if (j < z)
|
||||
{
|
||||
while (++j < z)
|
||||
c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
|
||||
}
|
||||
while (i != 0);
|
||||
|
||||
if (c[0] == n)
|
||||
{
|
||||
// null input--all zero length codes
|
||||
t[0] = - 1;
|
||||
m[0] = 0;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
// Find minimum and maximum length, bound *m by those
|
||||
l = m[0];
|
||||
for (j = 1; j <= BMAX; j++)
|
||||
if (c[j] != 0)
|
||||
break;
|
||||
k = j; // minimum code length
|
||||
if (l < j)
|
||||
{
|
||||
l = j;
|
||||
}
|
||||
for (i = BMAX; i != 0; i--)
|
||||
{
|
||||
if (c[i] != 0)
|
||||
break;
|
||||
}
|
||||
g = i; // maximum code length
|
||||
if (l > i)
|
||||
{
|
||||
l = i;
|
||||
}
|
||||
m[0] = l;
|
||||
|
||||
// Adjust last length count to fill out codes, if needed
|
||||
for (y = 1 << j; j < i; j++, y <<= 1)
|
||||
{
|
||||
if ((y -= c[j]) < 0)
|
||||
{
|
||||
// try smaller tables up to z bits
|
||||
if ((f <<= 1) <= c[++xp])
|
||||
break; // enough codes to use up j bits
|
||||
f -= c[xp]; // else deduct codes from patterns
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
z = 1 << j; // table entries for j-bit table
|
||||
|
||||
// allocate new table
|
||||
if (hn[0] + z > MANY)
|
||||
if ((y -= c[i]) < 0)
|
||||
{
|
||||
// (note: doesn't matter for fixed)
|
||||
return Z_DATA_ERROR; // overflow of MANY
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
u[h] = q = hn[0]; // DEBUG
|
||||
hn[0] += z;
|
||||
|
||||
// connect to last table, if there is one
|
||||
if (h != 0)
|
||||
c[i] += y;
|
||||
|
||||
// Generate starting offsets into the value table for each length
|
||||
x[1] = j = 0;
|
||||
p = 1; xp = 2;
|
||||
while (--i != 0)
|
||||
{
|
||||
x[h] = i; // save pattern for backing up
|
||||
r[0] = (sbyte)j; // bits in this table
|
||||
r[1] = (sbyte)l; // bits to dump before this table
|
||||
j = SharedUtils.URShift(i, (w - l));
|
||||
r[2] = (int)(q - u[h - 1] - j); // offset to this table
|
||||
Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
|
||||
// note that i == g from above
|
||||
x[xp] = (j += c[p]);
|
||||
xp++;
|
||||
p++;
|
||||
}
|
||||
|
||||
// Make a table of values in order of bit lengths
|
||||
i = 0; p = 0;
|
||||
do
|
||||
{
|
||||
if ((j = b[bindex + p]) != 0)
|
||||
{
|
||||
v[x[j]++] = i;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
while (++i < n);
|
||||
n = x[g]; // set n to length of v
|
||||
|
||||
// Generate the Huffman codes and for each, make the table entries
|
||||
x[0] = i = 0; // first Huffman code is zero
|
||||
p = 0; // grab values in bit order
|
||||
h = - 1; // no tables yet--level -1
|
||||
w = - l; // bits decoded == (l * h)
|
||||
u[0] = 0; // just to keep compilers happy
|
||||
q = 0; // ditto
|
||||
z = 0; // ditto
|
||||
|
||||
// go through the bit lengths (k already is bits in shortest code)
|
||||
for (; k <= g; k++)
|
||||
{
|
||||
a = c[k];
|
||||
while (a-- != 0)
|
||||
{
|
||||
// here i is the Huffman code of length k bits for value *p
|
||||
// make tables up to required level
|
||||
while (k > w + l)
|
||||
{
|
||||
h++;
|
||||
w += l; // previous table always l bits
|
||||
// compute minimum size table less than or equal to l bits
|
||||
z = g - w;
|
||||
z = (z > l)?l:z; // table size upper limit
|
||||
if ((f = 1 << (j = k - w)) > a + 1)
|
||||
{
|
||||
// try a k-w bit table
|
||||
// too few codes for k-w bit table
|
||||
f -= (a + 1); // deduct codes from patterns left
|
||||
xp = k;
|
||||
if (j < z)
|
||||
{
|
||||
while (++j < z)
|
||||
{
|
||||
// try smaller tables up to z bits
|
||||
if ((f <<= 1) <= c[++xp])
|
||||
break; // enough codes to use up j bits
|
||||
f -= c[xp]; // else deduct codes from patterns
|
||||
}
|
||||
}
|
||||
}
|
||||
z = 1 << j; // table entries for j-bit table
|
||||
|
||||
// allocate new table
|
||||
if (hn[0] + z > MANY)
|
||||
{
|
||||
// (note: doesn't matter for fixed)
|
||||
return Z_DATA_ERROR; // overflow of MANY
|
||||
}
|
||||
u[h] = q = hn[0]; // DEBUG
|
||||
hn[0] += z;
|
||||
|
||||
// connect to last table, if there is one
|
||||
if (h != 0)
|
||||
{
|
||||
x[h] = i; // save pattern for backing up
|
||||
r[0] = (sbyte) j; // bits in this table
|
||||
r[1] = (sbyte) l; // bits to dump before this table
|
||||
j = SharedUtils.URShift(i, (w - l));
|
||||
r[2] = (int) (q - u[h - 1] - j); // offset to this table
|
||||
Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
|
||||
}
|
||||
else
|
||||
{
|
||||
t[0] = q; // first table is returned result
|
||||
}
|
||||
}
|
||||
|
||||
// set up table entry in r
|
||||
r[1] = (sbyte) (k - w);
|
||||
if (p >= n)
|
||||
{
|
||||
r[0] = 128 + 64; // out of values--invalid code
|
||||
}
|
||||
else if (v[p] < s)
|
||||
{
|
||||
r[0] = (sbyte) (v[p] < 256?0:32 + 64); // 256 is end-of-block
|
||||
r[2] = v[p++]; // simple code is just the value
|
||||
}
|
||||
else
|
||||
{
|
||||
r[0] = (sbyte) (e[v[p] - s] + 16 + 64); // non-simple--look up in lists
|
||||
r[2] = d[v[p++] - s];
|
||||
}
|
||||
|
||||
// fill code-like entries with r
|
||||
f = 1 << (k - w);
|
||||
for (j = SharedUtils.URShift(i, w); j < z; j += f)
|
||||
{
|
||||
Array.Copy(r, 0, hp, (q + j) * 3, 3);
|
||||
}
|
||||
|
||||
// backwards increment the k-bit code i
|
||||
for (j = 1 << (k - 1); (i & j) != 0; j = SharedUtils.URShift(j, 1))
|
||||
{
|
||||
i ^= j;
|
||||
}
|
||||
i ^= j;
|
||||
|
||||
// backup over finished tables
|
||||
mask = (1 << w) - 1; // needed on HP, cc -O bug
|
||||
while ((i & mask) != x[h])
|
||||
{
|
||||
h--; // don't need to update q
|
||||
w -= l;
|
||||
mask = (1 << w) - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return Z_BUF_ERROR if we were given an incomplete table
|
||||
return y != 0 && g != 1?Z_BUF_ERROR:Z_OK;
|
||||
}
|
||||
|
||||
internal int inflate_trees_bits(int[] c, int[] bb, int[] tb, int[] hp, ZlibCodec z)
|
||||
{
|
||||
int result;
|
||||
initWorkArea(19);
|
||||
hn[0] = 0;
|
||||
result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
|
||||
|
||||
if (result == Z_DATA_ERROR)
|
||||
{
|
||||
z.Message = "oversubscribed dynamic bit lengths tree";
|
||||
}
|
||||
else if (result == Z_BUF_ERROR || bb[0] == 0)
|
||||
{
|
||||
z.Message = "incomplete dynamic bit lengths tree";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int inflate_trees_dynamic(int nl, int nd, int[] c, int[] bl, int[] bd, int[] tl, int[] td, int[] hp, ZlibCodec z)
|
||||
{
|
||||
int result;
|
||||
|
||||
// build literal/length tree
|
||||
initWorkArea(288);
|
||||
hn[0] = 0;
|
||||
result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
|
||||
if (result != Z_OK || bl[0] == 0)
|
||||
{
|
||||
if (result == Z_DATA_ERROR)
|
||||
{
|
||||
z.Message = "oversubscribed literal/length tree";
|
||||
}
|
||||
else if (result != Z_MEM_ERROR)
|
||||
{
|
||||
z.Message = "incomplete literal/length tree";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// build distance tree
|
||||
initWorkArea(288);
|
||||
result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
|
||||
|
||||
if (result != Z_OK || (bd[0] == 0 && nl > 257))
|
||||
{
|
||||
if (result == Z_DATA_ERROR)
|
||||
{
|
||||
z.Message = "oversubscribed distance tree";
|
||||
}
|
||||
else if (result == Z_BUF_ERROR)
|
||||
{
|
||||
z.Message = "incomplete distance tree";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
else if (result != Z_MEM_ERROR)
|
||||
{
|
||||
z.Message = "empty distance tree with lengths";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
internal static int inflate_trees_fixed(int[] bl, int[] bd, int[][] tl, int[][] td, ZlibCodec z)
|
||||
{
|
||||
bl[0] = fixed_bl;
|
||||
bd[0] = fixed_bd;
|
||||
tl[0] = fixed_tl;
|
||||
td[0] = fixed_td;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
private void initWorkArea(int vsize)
|
||||
{
|
||||
if (hn == null)
|
||||
{
|
||||
hn = new int[1];
|
||||
v = new int[vsize];
|
||||
c = new int[BMAX + 1];
|
||||
r = new int[3];
|
||||
u = new int[BMAX];
|
||||
x = new int[BMAX + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
t[0] = q; // first table is returned result
|
||||
if (v.Length < vsize)
|
||||
{
|
||||
v = new int[vsize];
|
||||
}
|
||||
Array.Clear(v,0,vsize);
|
||||
Array.Clear(c,0,BMAX+1);
|
||||
r[0]=0; r[1]=0; r[2]=0;
|
||||
// for(int i=0; i<BMAX; i++){u[i]=0;}
|
||||
//Array.Copy(c, 0, u, 0, BMAX);
|
||||
Array.Clear(u,0,BMAX);
|
||||
// for(int i=0; i<BMAX+1; i++){x[i]=0;}
|
||||
//Array.Copy(c, 0, x, 0, BMAX + 1);
|
||||
Array.Clear(x,0,BMAX+1);
|
||||
}
|
||||
}
|
||||
|
||||
// set up table entry in r
|
||||
r[1] = (sbyte)(k - w);
|
||||
if (p >= n)
|
||||
{
|
||||
r[0] = 128 + 64; // out of values--invalid code
|
||||
}
|
||||
else if (v[p] < s)
|
||||
{
|
||||
r[0] = (sbyte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
|
||||
r[2] = v[p++]; // simple code is just the value
|
||||
}
|
||||
else
|
||||
{
|
||||
r[0] = (sbyte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
|
||||
r[2] = d[v[p++] - s];
|
||||
}
|
||||
|
||||
// fill code-like entries with r
|
||||
f = 1 << (k - w);
|
||||
for (j = SharedUtils.URShift(i, w); j < z; j += f)
|
||||
{
|
||||
Array.Copy(r, 0, hp, (q + j) * 3, 3);
|
||||
}
|
||||
|
||||
// backwards increment the k-bit code i
|
||||
for (j = 1 << (k - 1); (i & j) != 0; j = SharedUtils.URShift(j, 1))
|
||||
{
|
||||
i ^= j;
|
||||
}
|
||||
i ^= j;
|
||||
|
||||
// backup over finished tables
|
||||
mask = (1 << w) - 1; // needed on HP, cc -O bug
|
||||
while ((i & mask) != x[h])
|
||||
{
|
||||
h--; // don't need to update q
|
||||
w -= l;
|
||||
mask = (1 << w) - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return Z_BUF_ERROR if we were given an incomplete table
|
||||
return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
|
||||
}
|
||||
|
||||
internal int inflate_trees_bits(int[] c, int[] bb, int[] tb, int[] hp, ZlibCodec z)
|
||||
{
|
||||
int result;
|
||||
initWorkArea(19);
|
||||
hn[0] = 0;
|
||||
result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
|
||||
|
||||
if (result == Z_DATA_ERROR)
|
||||
{
|
||||
z.Message = "oversubscribed dynamic bit lengths tree";
|
||||
}
|
||||
else if (result == Z_BUF_ERROR || bb[0] == 0)
|
||||
{
|
||||
z.Message = "incomplete dynamic bit lengths tree";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int inflate_trees_dynamic(int nl, int nd, int[] c, int[] bl, int[] bd, int[] tl, int[] td, int[] hp, ZlibCodec z)
|
||||
{
|
||||
int result;
|
||||
|
||||
// build literal/length tree
|
||||
initWorkArea(288);
|
||||
hn[0] = 0;
|
||||
result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
|
||||
if (result != Z_OK || bl[0] == 0)
|
||||
{
|
||||
if (result == Z_DATA_ERROR)
|
||||
{
|
||||
z.Message = "oversubscribed literal/length tree";
|
||||
}
|
||||
else if (result != Z_MEM_ERROR)
|
||||
{
|
||||
z.Message = "incomplete literal/length tree";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// build distance tree
|
||||
initWorkArea(288);
|
||||
result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
|
||||
|
||||
if (result != Z_OK || (bd[0] == 0 && nl > 257))
|
||||
{
|
||||
if (result == Z_DATA_ERROR)
|
||||
{
|
||||
z.Message = "oversubscribed distance tree";
|
||||
}
|
||||
else if (result == Z_BUF_ERROR)
|
||||
{
|
||||
z.Message = "incomplete distance tree";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
else if (result != Z_MEM_ERROR)
|
||||
{
|
||||
z.Message = "empty distance tree with lengths";
|
||||
result = Z_DATA_ERROR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
internal static int inflate_trees_fixed(int[] bl, int[] bd, int[][] tl, int[][] td, ZlibCodec z)
|
||||
{
|
||||
bl[0] = fixed_bl;
|
||||
bd[0] = fixed_bd;
|
||||
tl[0] = fixed_tl;
|
||||
td[0] = fixed_td;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
private void initWorkArea(int vsize)
|
||||
{
|
||||
if (hn == null)
|
||||
{
|
||||
hn = new int[1];
|
||||
v = new int[vsize];
|
||||
c = new int[BMAX + 1];
|
||||
r = new int[3];
|
||||
u = new int[BMAX];
|
||||
x = new int[BMAX + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (v.Length < vsize)
|
||||
{
|
||||
v = new int[vsize];
|
||||
}
|
||||
Array.Clear(v, 0, vsize);
|
||||
Array.Clear(c, 0, BMAX + 1);
|
||||
r[0] = 0; r[1] = 0; r[2] = 0;
|
||||
// for(int i=0; i<BMAX; i++){u[i]=0;}
|
||||
//Array.Copy(c, 0, u, 0, BMAX);
|
||||
Array.Clear(u, 0, BMAX);
|
||||
// for(int i=0; i<BMAX+1; i++){x[i]=0;}
|
||||
//Array.Copy(c, 0, x, 0, BMAX + 1);
|
||||
Array.Clear(x, 0, BMAX + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,16 +76,16 @@ namespace Compress.ZipFile.ZLib
|
||||
|
||||
private enum InflateBlockMode
|
||||
{
|
||||
TYPE = 0, // get type bits (3, including end bit)
|
||||
LENS = 1, // get lengths for stored
|
||||
TYPE = 0, // get type bits (3, including end bit)
|
||||
LENS = 1, // get lengths for stored
|
||||
STORED = 2, // processing stored block
|
||||
TABLE = 3, // get table lengths
|
||||
BTREE = 4, // get bit lengths tree for a dynamic block
|
||||
DTREE = 5, // get length, distance trees for a dynamic block
|
||||
CODES = 6, // processing fixed or dynamic block
|
||||
DRY = 7, // output remaining window bytes
|
||||
DONE = 8, // finished last block, done
|
||||
BAD = 9, // ot a data error--stuck here
|
||||
TABLE = 3, // get table lengths
|
||||
BTREE = 4, // get bit lengths tree for a dynamic block
|
||||
DTREE = 5, // get length, distance trees for a dynamic block
|
||||
CODES = 6, // processing fixed or dynamic block
|
||||
DRY = 7, // output remaining window bytes
|
||||
DONE = 8, // finished last block, done
|
||||
BAD = 9, // ot a data error--stuck here
|
||||
}
|
||||
|
||||
private InflateBlockMode mode; // current inflate_block mode
|
||||
@@ -104,7 +104,7 @@ namespace Compress.ZipFile.ZLib
|
||||
|
||||
internal ZlibCodec _codec; // pointer back to this zlib stream
|
||||
|
||||
// mode independent information
|
||||
// mode independent information
|
||||
internal int bitk; // bits in bit buffer
|
||||
internal int bitb; // bit buffer
|
||||
internal int[] hufts; // single malloc for tree space
|
||||
@@ -255,7 +255,7 @@ namespace Compress.ZipFile.ZLib
|
||||
k += 8;
|
||||
}
|
||||
|
||||
if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
|
||||
if ( ( ((~b)>>16) & 0xffff) != (b & 0xffff))
|
||||
{
|
||||
mode = InflateBlockMode.BAD;
|
||||
_codec.Message = "invalid stored block lengths";
|
||||
@@ -533,7 +533,7 @@ namespace Compress.ZipFile.ZLib
|
||||
return Flush(r);
|
||||
}
|
||||
|
||||
c = (c == 16) ? blens[i - 1] : 0;
|
||||
c = (c == 16) ? blens[i-1] : 0;
|
||||
do
|
||||
{
|
||||
blens[i++] = c;
|
||||
@@ -679,9 +679,9 @@ namespace Compress.ZipFile.ZLib
|
||||
{
|
||||
int nBytes;
|
||||
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
for (int pass=0; pass < 2; pass++)
|
||||
{
|
||||
if (pass == 0)
|
||||
if (pass==0)
|
||||
{
|
||||
// compute number of bytes to copy as far as end of window
|
||||
nBytes = (int)((readAt <= writeAt ? writeAt : end) - readAt);
|
||||
@@ -752,15 +752,15 @@ namespace Compress.ZipFile.ZLib
|
||||
// waiting for "i:"=input,
|
||||
// "o:"=output,
|
||||
// "x:"=nothing
|
||||
private const int START = 0; // x: set up for LEN
|
||||
private const int LEN = 1; // i: get length/literal/eob next
|
||||
private const int LENEXT = 2; // i: getting length extra (have base)
|
||||
private const int DIST = 3; // i: get distance next
|
||||
private const int START = 0; // x: set up for LEN
|
||||
private const int LEN = 1; // i: get length/literal/eob next
|
||||
private const int LENEXT = 2; // i: getting length extra (have base)
|
||||
private const int DIST = 3; // i: get distance next
|
||||
private const int DISTEXT = 4; // i: getting distance extra
|
||||
private const int COPY = 5; // o: copying bytes in window, waiting for space
|
||||
private const int LIT = 6; // o: got literal, waiting for output space
|
||||
private const int WASH = 7; // o: got eob, possibly still output waiting
|
||||
private const int END = 8; // x: got eob and all data flushed
|
||||
private const int COPY = 5; // o: copying bytes in window, waiting for space
|
||||
private const int LIT = 6; // o: got literal, waiting for output space
|
||||
private const int WASH = 7; // o: got eob, possibly still output waiting
|
||||
private const int END = 8; // x: got eob and all data flushed
|
||||
private const int BADCODE = 9; // x: got error
|
||||
|
||||
internal int mode; // current inflate_codes mode
|
||||
@@ -1413,19 +1413,19 @@ namespace Compress.ZipFile.ZLib
|
||||
private enum InflateManagerMode
|
||||
{
|
||||
METHOD = 0, // waiting for method byte
|
||||
FLAG = 1, // waiting for flag byte
|
||||
DICT4 = 2, // four dictionary check bytes to go
|
||||
DICT3 = 3, // three dictionary check bytes to go
|
||||
DICT2 = 4, // two dictionary check bytes to go
|
||||
DICT1 = 5, // one dictionary check byte to go
|
||||
DICT0 = 6, // waiting for inflateSetDictionary
|
||||
FLAG = 1, // waiting for flag byte
|
||||
DICT4 = 2, // four dictionary check bytes to go
|
||||
DICT3 = 3, // three dictionary check bytes to go
|
||||
DICT2 = 4, // two dictionary check bytes to go
|
||||
DICT1 = 5, // one dictionary check byte to go
|
||||
DICT0 = 6, // waiting for inflateSetDictionary
|
||||
BLOCKS = 7, // decompressing blocks
|
||||
CHECK4 = 8, // four check bytes to go
|
||||
CHECK3 = 9, // three check bytes to go
|
||||
CHECK2 = 10, // two check bytes to go
|
||||
CHECK1 = 11, // one check byte to go
|
||||
DONE = 12, // finished check, done
|
||||
BAD = 13, // got an error--stay here
|
||||
DONE = 12, // finished check, done
|
||||
BAD = 13, // got an error--stay here
|
||||
}
|
||||
|
||||
private InflateManagerMode mode; // current inflate mode
|
||||
@@ -1518,9 +1518,9 @@ namespace Compress.ZipFile.ZLib
|
||||
if (_codec.InputBuffer == null)
|
||||
throw new ZlibException("InputBuffer is null. ");
|
||||
|
||||
// int f = (flush == FlushType.Finish)
|
||||
// ? ZlibConstants.Z_BUF_ERROR
|
||||
// : ZlibConstants.Z_OK;
|
||||
// int f = (flush == FlushType.Finish)
|
||||
// ? ZlibConstants.Z_BUF_ERROR
|
||||
// : ZlibConstants.Z_OK;
|
||||
|
||||
// workitem 8870
|
||||
int f = ZlibConstants.Z_OK;
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
// Tree.cs
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
|
||||
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code module is part of DotNetZip, a zipfile class library.
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// This code is licensed under the Microsoft Public License.
|
||||
// This code is licensed under the Microsoft Public License.
|
||||
// See the file License.txt for the license details.
|
||||
// More info on: http://dotnetzip.codeplex.com
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// last saved (in emacs):
|
||||
// last saved (in emacs):
|
||||
// Time-stamp: <2009-October-28 13:29:50>
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
@@ -25,22 +25,22 @@
|
||||
// code is below.
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in
|
||||
// the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
//
|
||||
// 3. The names of the authors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
@@ -51,7 +51,7 @@
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
// This program is based on zlib-1.1.3; credit to authors
|
||||
@@ -66,72 +66,72 @@ namespace Compress.ZipFile.ZLib
|
||||
sealed class Tree
|
||||
{
|
||||
private static readonly int HEAP_SIZE = (2 * InternalConstants.L_CODES + 1);
|
||||
|
||||
|
||||
// extra bits for each length code
|
||||
internal static readonly int[] ExtraLengthBits = new int[]
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
// extra bits for each distance code
|
||||
internal static readonly int[] ExtraDistanceBits = new int[]
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
// extra bits for each bit length code
|
||||
internal static readonly int[] extra_blbits = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };
|
||||
|
||||
internal static readonly sbyte[] bl_order = new sbyte[] { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
|
||||
|
||||
|
||||
internal static readonly int[] extra_blbits = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7};
|
||||
|
||||
internal static readonly sbyte[] bl_order = new sbyte[]{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
|
||||
|
||||
// The lengths of the bit length codes are sent in order of decreasing
|
||||
// probability, to avoid transmitting the lengths for unused bit
|
||||
// length codes.
|
||||
|
||||
|
||||
internal const int Buf_size = 8 * 2;
|
||||
|
||||
|
||||
// see definition of array dist_code below
|
||||
//internal const int DIST_CODE_LEN = 512;
|
||||
|
||||
|
||||
private static readonly sbyte[] _dist_code = new sbyte[]
|
||||
{
|
||||
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
|
||||
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
|
||||
};
|
||||
|
||||
|
||||
internal static readonly sbyte[] LengthCode = new sbyte[]
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11,
|
||||
@@ -151,14 +151,14 @@ namespace Compress.ZipFile.ZLib
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
|
||||
};
|
||||
|
||||
|
||||
|
||||
internal static readonly int[] LengthBase = new int[]
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28,
|
||||
32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0
|
||||
};
|
||||
|
||||
|
||||
|
||||
internal static readonly int[] DistanceBase = new int[]
|
||||
{
|
||||
@@ -166,11 +166,11 @@ namespace Compress.ZipFile.ZLib
|
||||
256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Map from a distance to a distance code.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <remarks>
|
||||
/// No side effects. _dist_code[256] and _dist_code[257] are never used.
|
||||
/// </remarks>
|
||||
internal static int DistanceCode(int dist)
|
||||
@@ -183,7 +183,7 @@ namespace Compress.ZipFile.ZLib
|
||||
internal short[] dyn_tree; // the dynamic tree
|
||||
internal int max_code; // largest code with non zero frequency
|
||||
internal StaticTree staticTree; // the corresponding static tree
|
||||
|
||||
|
||||
// Compute the optimal bit lengths for a tree and update the total bit length
|
||||
// for the current block.
|
||||
// IN assertion: the fields freq and dad are set, heap[heap_max] and
|
||||
@@ -192,7 +192,7 @@ namespace Compress.ZipFile.ZLib
|
||||
// array bl_count contains the frequencies for each bit length.
|
||||
// The length opt_len is updated; static_len is also updated if stree is
|
||||
// not null.
|
||||
internal void gen_bitlen(DeflateManager s)
|
||||
internal void gen_bitlen(DeflateManager s)
|
||||
{
|
||||
short[] tree = dyn_tree;
|
||||
short[] stree = staticTree.treeCodes;
|
||||
@@ -205,14 +205,14 @@ namespace Compress.ZipFile.ZLib
|
||||
int xbits; // extra bits
|
||||
short f; // frequency
|
||||
int overflow = 0; // number of elements with bit length too large
|
||||
|
||||
|
||||
for (bits = 0; bits <= InternalConstants.MAX_BITS; bits++)
|
||||
s.bl_count[bits] = 0;
|
||||
|
||||
|
||||
// In a first pass, compute the optimal bit lengths (which may
|
||||
// overflow in the case of the bit length tree).
|
||||
tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
|
||||
|
||||
|
||||
for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
|
||||
{
|
||||
n = s.heap[h];
|
||||
@@ -221,12 +221,12 @@ namespace Compress.ZipFile.ZLib
|
||||
{
|
||||
bits = max_length; overflow++;
|
||||
}
|
||||
tree[n * 2 + 1] = (short)bits;
|
||||
tree[n * 2 + 1] = (short) bits;
|
||||
// We overwrite tree[n*2+1] which is no longer needed
|
||||
|
||||
|
||||
if (n > max_code)
|
||||
continue; // not a leaf node
|
||||
|
||||
|
||||
s.bl_count[bits]++;
|
||||
xbits = 0;
|
||||
if (n >= base_Renamed)
|
||||
@@ -237,24 +237,24 @@ namespace Compress.ZipFile.ZLib
|
||||
s.static_len += f * (stree[n * 2 + 1] + xbits);
|
||||
}
|
||||
if (overflow == 0)
|
||||
return;
|
||||
|
||||
return ;
|
||||
|
||||
// This happens for example on obj2 and pic of the Calgary corpus
|
||||
// Find the first bit length which could increase:
|
||||
do
|
||||
do
|
||||
{
|
||||
bits = max_length - 1;
|
||||
while (s.bl_count[bits] == 0)
|
||||
bits--;
|
||||
s.bl_count[bits]--; // move one leaf down the tree
|
||||
s.bl_count[bits + 1] = (short)(s.bl_count[bits + 1] + 2); // move one overflow item as its brother
|
||||
s.bl_count[bits + 1] = (short) (s.bl_count[bits + 1] + 2); // move one overflow item as its brother
|
||||
s.bl_count[max_length]--;
|
||||
// The brother of the overflow item also moves one step up,
|
||||
// but this does not affect bl_count[max_length]
|
||||
overflow -= 2;
|
||||
}
|
||||
while (overflow > 0);
|
||||
|
||||
|
||||
for (bits = max_length; bits != 0; bits--)
|
||||
{
|
||||
n = s.bl_count[bits];
|
||||
@@ -265,35 +265,35 @@ namespace Compress.ZipFile.ZLib
|
||||
continue;
|
||||
if (tree[m * 2 + 1] != bits)
|
||||
{
|
||||
s.opt_len = (int)(s.opt_len + ((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
|
||||
tree[m * 2 + 1] = (short)bits;
|
||||
s.opt_len = (int) (s.opt_len + ((long) bits - (long) tree[m * 2 + 1]) * (long) tree[m * 2]);
|
||||
tree[m * 2 + 1] = (short) bits;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Construct one Huffman tree and assigns the code bit strings and lengths.
|
||||
// Update the total bit length for the current block.
|
||||
// IN assertion: the field freq is set for all tree elements.
|
||||
// OUT assertions: the fields len and code are set to the optimal bit length
|
||||
// and corresponding code. The length opt_len is updated; static_len is
|
||||
// also updated if stree is not null. The field max_code is set.
|
||||
internal void build_tree(DeflateManager s)
|
||||
internal void build_tree(DeflateManager s)
|
||||
{
|
||||
short[] tree = dyn_tree;
|
||||
short[] tree = dyn_tree;
|
||||
short[] stree = staticTree.treeCodes;
|
||||
int elems = staticTree.elems;
|
||||
int elems = staticTree.elems;
|
||||
int n, m; // iterate over heap elements
|
||||
int max_code = -1; // largest code with non zero frequency
|
||||
int max_code = -1; // largest code with non zero frequency
|
||||
int node; // new node being created
|
||||
|
||||
|
||||
// Construct the initial heap, with least frequent element in
|
||||
// heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
|
||||
// heap[0] is not used.
|
||||
s.heap_len = 0;
|
||||
s.heap_max = HEAP_SIZE;
|
||||
|
||||
|
||||
for (n = 0; n < elems; n++)
|
||||
{
|
||||
if (tree[n * 2] != 0)
|
||||
@@ -306,14 +306,14 @@ namespace Compress.ZipFile.ZLib
|
||||
tree[n * 2 + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The pkzip format requires that at least one distance code exists,
|
||||
// and that at least one bit should be sent even if there is only one
|
||||
// possible code. So to avoid special checks later on we force at least
|
||||
// two codes of non zero frequency.
|
||||
while (s.heap_len < 2)
|
||||
{
|
||||
node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
|
||||
node = s.heap[++s.heap_len] = (max_code < 2?++max_code:0);
|
||||
tree[node * 2] = 1;
|
||||
s.depth[node] = 0;
|
||||
s.opt_len--;
|
||||
@@ -322,94 +322,93 @@ namespace Compress.ZipFile.ZLib
|
||||
// node is 0 or 1 so it does not have extra bits
|
||||
}
|
||||
this.max_code = max_code;
|
||||
|
||||
|
||||
// The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
|
||||
// establish sub-heaps of increasing lengths:
|
||||
|
||||
|
||||
for (n = s.heap_len / 2; n >= 1; n--)
|
||||
s.pqdownheap(tree, n);
|
||||
|
||||
|
||||
// Construct the Huffman tree by repeatedly combining the least two
|
||||
// frequent nodes.
|
||||
|
||||
|
||||
node = elems; // next internal node of the tree
|
||||
do
|
||||
do
|
||||
{
|
||||
// n = node of least frequency
|
||||
n = s.heap[1];
|
||||
s.heap[1] = s.heap[s.heap_len--];
|
||||
s.pqdownheap(tree, 1);
|
||||
m = s.heap[1]; // m = node of next least frequency
|
||||
|
||||
|
||||
s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
|
||||
s.heap[--s.heap_max] = m;
|
||||
|
||||
|
||||
// Create a new node father of n and m
|
||||
tree[node * 2] = unchecked((short)(tree[n * 2] + tree[m * 2]));
|
||||
s.depth[node] = (sbyte)(System.Math.Max((byte)s.depth[n], (byte)s.depth[m]) + 1);
|
||||
tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
|
||||
|
||||
tree[node * 2] = unchecked((short) (tree[n * 2] + tree[m * 2]));
|
||||
s.depth[node] = (sbyte) (System.Math.Max((byte) s.depth[n], (byte) s.depth[m]) + 1);
|
||||
tree[n * 2 + 1] = tree[m * 2 + 1] = (short) node;
|
||||
|
||||
// and insert the new node in the heap
|
||||
s.heap[1] = node++;
|
||||
s.pqdownheap(tree, 1);
|
||||
}
|
||||
while (s.heap_len >= 2);
|
||||
|
||||
|
||||
s.heap[--s.heap_max] = s.heap[1];
|
||||
|
||||
|
||||
// At this point, the fields freq and dad are set. We can now
|
||||
// generate the bit lengths.
|
||||
|
||||
|
||||
gen_bitlen(s);
|
||||
|
||||
|
||||
// The field len is now set, we can generate the bit codes
|
||||
gen_codes(tree, max_code, s.bl_count);
|
||||
}
|
||||
|
||||
|
||||
// Generate the codes for a given tree and bit counts (which need not be
|
||||
// optimal).
|
||||
// IN assertion: the array bl_count contains the bit length statistics for
|
||||
// the given tree and the field len is set for all tree elements.
|
||||
// OUT assertion: the field code is set for all tree elements of non
|
||||
// zero code length.
|
||||
internal static void gen_codes(short[] tree, int max_code, short[] bl_count)
|
||||
internal static void gen_codes(short[] tree, int max_code, short[] bl_count)
|
||||
{
|
||||
short[] next_code = new short[InternalConstants.MAX_BITS + 1]; // next code value for each bit length
|
||||
short code = 0; // running code value
|
||||
int bits; // bit index
|
||||
int n; // code index
|
||||
|
||||
|
||||
// The distribution counts are first used to generate the code values
|
||||
// without bit reversal.
|
||||
for (bits = 1; bits <= InternalConstants.MAX_BITS; bits++)
|
||||
unchecked
|
||||
{
|
||||
next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
|
||||
unchecked {
|
||||
next_code[bits] = code = (short) ((code + bl_count[bits - 1]) << 1);
|
||||
}
|
||||
|
||||
|
||||
// Check that the bit counts in bl_count are consistent. The last code
|
||||
// must be all ones.
|
||||
//Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
|
||||
// "inconsistent bit counts");
|
||||
//Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
|
||||
|
||||
|
||||
for (n = 0; n <= max_code; n++)
|
||||
{
|
||||
int len = tree[n * 2 + 1];
|
||||
if (len == 0)
|
||||
continue;
|
||||
// Now reverse the bits
|
||||
tree[n * 2] = unchecked((short)(bi_reverse(next_code[len]++, len)));
|
||||
tree[n * 2] = unchecked((short) (bi_reverse(next_code[len]++, len)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reverse the first len bits of a code, using straightforward code (a faster
|
||||
// method would use a table)
|
||||
// IN assertion: 1 <= len <= 15
|
||||
internal static int bi_reverse(int code, int len)
|
||||
{
|
||||
int res = 0;
|
||||
do
|
||||
do
|
||||
{
|
||||
res |= code & 1;
|
||||
code >>= 1; //SharedUtils.URShift(code, 1);
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace Compress.ZipFile.ZLib
|
||||
/// If you are producing ZIPs for use on Mac OSX, be aware that archives produced with CompressionLevel.None
|
||||
/// cannot be opened with the default zip reader. Use a different CompressionLevel.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
None= 0,
|
||||
/// <summary>
|
||||
/// Same as None.
|
||||
/// </summary>
|
||||
@@ -249,7 +249,7 @@ namespace Compress.ZipFile.ZLib
|
||||
/// <summary>
|
||||
/// Used to specify that the stream should compress the data.
|
||||
/// </summary>
|
||||
Compress = 0,
|
||||
Compress= 0,
|
||||
/// <summary>
|
||||
/// Used to specify that the stream should decompress the data.
|
||||
/// </summary>
|
||||
@@ -299,24 +299,24 @@ namespace Compress.ZipFile.ZLib
|
||||
|
||||
internal static class InternalConstants
|
||||
{
|
||||
internal static readonly int MAX_BITS = 15;
|
||||
internal static readonly int BL_CODES = 19;
|
||||
internal static readonly int D_CODES = 30;
|
||||
internal static readonly int LITERALS = 256;
|
||||
internal static readonly int MAX_BITS = 15;
|
||||
internal static readonly int BL_CODES = 19;
|
||||
internal static readonly int D_CODES = 30;
|
||||
internal static readonly int LITERALS = 256;
|
||||
internal static readonly int LENGTH_CODES = 29;
|
||||
internal static readonly int L_CODES = (LITERALS + 1 + LENGTH_CODES);
|
||||
internal static readonly int L_CODES = (LITERALS + 1 + LENGTH_CODES);
|
||||
|
||||
// Bit length codes must not exceed MAX_BL_BITS bits
|
||||
internal static readonly int MAX_BL_BITS = 7;
|
||||
internal static readonly int MAX_BL_BITS = 7;
|
||||
|
||||
// repeat previous bit length 3-6 times (2 bits of repeat count)
|
||||
internal static readonly int REP_3_6 = 16;
|
||||
internal static readonly int REP_3_6 = 16;
|
||||
|
||||
// repeat a zero length 3-10 times (3 bits of repeat count)
|
||||
internal static readonly int REPZ_3_10 = 17;
|
||||
internal static readonly int REPZ_3_10 = 17;
|
||||
|
||||
// repeat a zero length 11-138 times (7 bits of repeat count)
|
||||
internal static readonly int REPZ_11_138 = 18;
|
||||
internal static readonly int REPZ_11_138 = 18;
|
||||
|
||||
}
|
||||
|
||||
@@ -433,8 +433,8 @@ namespace Compress.ZipFile.ZLib
|
||||
if (buf == null)
|
||||
return 1;
|
||||
|
||||
uint s1 = (uint)(adler & 0xffff);
|
||||
uint s2 = (uint)((adler >> 16) & 0xffff);
|
||||
uint s1 = (uint) (adler & 0xffff);
|
||||
uint s2 = (uint) ((adler >> 16) & 0xffff);
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
|
||||
@@ -321,7 +321,8 @@ namespace Compress.ZipFile.ZLib
|
||||
|
||||
public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin)
|
||||
{
|
||||
return _stream.Seek(offset, origin);
|
||||
throw new NotImplementedException();
|
||||
//_outStream.Seek(offset, origin);
|
||||
}
|
||||
public override void SetLength(System.Int64 value)
|
||||
{
|
||||
@@ -553,4 +554,4 @@ namespace Compress.ZipFile.ZLib
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
// ZlibCodec.cs
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
|
||||
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code module is part of DotNetZip, a zipfile class library.
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// This code is licensed under the Microsoft Public License.
|
||||
// This code is licensed under the Microsoft Public License.
|
||||
// See the file License.txt for the license details.
|
||||
// More info on: http://dotnetzip.codeplex.com
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// last saved (in emacs):
|
||||
// last saved (in emacs):
|
||||
// Time-stamp: <2009-November-03 15:40:51>
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
@@ -28,22 +28,22 @@
|
||||
// is included below.
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in
|
||||
// the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
//
|
||||
// 3. The names of the authors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
@@ -54,7 +54,7 @@
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
// This program is based on zlib-1.1.3; credit to authors
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Interop = System.Runtime.InteropServices;
|
||||
using Interop=System.Runtime.InteropServices;
|
||||
|
||||
namespace Compress.ZipFile.ZLib
|
||||
{
|
||||
@@ -82,7 +82,7 @@ namespace Compress.ZipFile.ZLib
|
||||
/// </remarks>
|
||||
[Guid("ebc25cf6-9120-4283-b972-0e5520d0000D")]
|
||||
[Interop.ComVisible(true)]
|
||||
#if !NETCF
|
||||
#if !NETCF
|
||||
[Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)]
|
||||
#endif
|
||||
sealed public class ZlibCodec
|
||||
@@ -93,15 +93,15 @@ namespace Compress.ZipFile.ZLib
|
||||
public byte[] InputBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// An index into the InputBuffer array, indicating where to start reading.
|
||||
/// An index into the InputBuffer array, indicating where to start reading.
|
||||
/// </summary>
|
||||
public int NextIn;
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes available in the InputBuffer, starting at NextIn.
|
||||
/// The number of bytes available in the InputBuffer, starting at NextIn.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Generally you should set this to InputBuffer.Length before the first Inflate() or Deflate() call.
|
||||
/// Generally you should set this to InputBuffer.Length before the first Inflate() or Deflate() call.
|
||||
/// The class will update this number as calls to Inflate/Deflate are made.
|
||||
/// </remarks>
|
||||
public int AvailableBytesIn;
|
||||
@@ -117,15 +117,15 @@ namespace Compress.ZipFile.ZLib
|
||||
public byte[] OutputBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// An index into the OutputBuffer array, indicating where to start writing.
|
||||
/// An index into the OutputBuffer array, indicating where to start writing.
|
||||
/// </summary>
|
||||
public int NextOut;
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes available in the OutputBuffer, starting at NextOut.
|
||||
/// The number of bytes available in the OutputBuffer, starting at NextOut.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Generally you should set this to OutputBuffer.Length before the first Inflate() or Deflate() call.
|
||||
/// Generally you should set this to OutputBuffer.Length before the first Inflate() or Deflate() call.
|
||||
/// The class will update this number as calls to Inflate/Deflate are made.
|
||||
/// </remarks>
|
||||
public int AvailableBytesOut;
|
||||
@@ -151,13 +151,13 @@ namespace Compress.ZipFile.ZLib
|
||||
public CompressionLevel CompressLevel = CompressionLevel.Default;
|
||||
|
||||
/// <summary>
|
||||
/// The number of Window Bits to use.
|
||||
/// The number of Window Bits to use.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gauges the size of the sliding window, and hence the
|
||||
/// compression effectiveness as well as memory consumption. It's best to just leave this
|
||||
/// This gauges the size of the sliding window, and hence the
|
||||
/// compression effectiveness as well as memory consumption. It's best to just leave this
|
||||
/// setting alone if you don't know what it is. The maximum value is 15 bits, which implies
|
||||
/// a 32k window.
|
||||
/// a 32k window.
|
||||
/// </remarks>
|
||||
public int WindowBits = ZlibConstants.WindowBitsDefault;
|
||||
|
||||
@@ -187,9 +187,9 @@ namespace Compress.ZipFile.ZLib
|
||||
/// Create a ZlibCodec.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you use this default constructor, you will later have to explicitly call
|
||||
/// InitializeInflate() or InitializeDeflate() before using the ZlibCodec to compress
|
||||
/// or decompress.
|
||||
/// If you use this default constructor, you will later have to explicitly call
|
||||
/// InitializeInflate() or InitializeDeflate() before using the ZlibCodec to compress
|
||||
/// or decompress.
|
||||
/// </remarks>
|
||||
public ZlibCodec() { }
|
||||
|
||||
@@ -215,10 +215,10 @@ namespace Compress.ZipFile.ZLib
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the inflation state.
|
||||
/// Initialize the inflation state.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It is not necessary to call this before using the ZlibCodec to inflate data;
|
||||
/// It is not necessary to call this before using the ZlibCodec to inflate data;
|
||||
/// It is implicitly called when you call the constructor.
|
||||
/// </remarks>
|
||||
/// <returns>Z_OK if everything goes well.</returns>
|
||||
@@ -251,20 +251,20 @@ namespace Compress.ZipFile.ZLib
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the ZlibCodec for inflation, with the specified number of window bits.
|
||||
/// Initialize the ZlibCodec for inflation, with the specified number of window bits.
|
||||
/// </summary>
|
||||
/// <param name="windowBits">The number of window bits to use. If you need to ask what that is,
|
||||
/// <param name="windowBits">The number of window bits to use. If you need to ask what that is,
|
||||
/// then you shouldn't be calling this initializer.</param>
|
||||
/// <returns>Z_OK if all goes well.</returns>
|
||||
public int InitializeInflate(int windowBits)
|
||||
{
|
||||
this.WindowBits = windowBits;
|
||||
this.WindowBits = windowBits;
|
||||
return InitializeInflate(windowBits, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the inflation state with an explicit flag to govern the handling of
|
||||
/// RFC1950 header bytes.
|
||||
/// RFC1950 header bytes.
|
||||
/// </summary>
|
||||
///
|
||||
/// <remarks>
|
||||
@@ -276,9 +276,9 @@ namespace Compress.ZipFile.ZLib
|
||||
/// false.
|
||||
/// </remarks>
|
||||
///
|
||||
/// <param name="expectRfc1950Header">whether to expect an RFC1950 header byte pair when reading
|
||||
/// <param name="expectRfc1950Header">whether to expect an RFC1950 header byte pair when reading
|
||||
/// the stream of data to be inflated.</param>
|
||||
/// <param name="windowBits">The number of window bits to use. If you need to ask what that is,
|
||||
/// <param name="windowBits">The number of window bits to use. If you need to ask what that is,
|
||||
/// then you shouldn't be calling this initializer.</param>
|
||||
/// <returns>Z_OK if everything goes well.</returns>
|
||||
public int InitializeInflate(int windowBits, bool expectRfc1950Header)
|
||||
@@ -293,7 +293,7 @@ namespace Compress.ZipFile.ZLib
|
||||
/// Inflate the data in the InputBuffer, placing the result in the OutputBuffer.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You must have set InputBuffer and OutputBuffer, NextIn and NextOut, and AvailableBytesIn and
|
||||
/// You must have set InputBuffer and OutputBuffer, NextIn and NextOut, and AvailableBytesIn and
|
||||
/// AvailableBytesOut before calling this method.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
@@ -303,48 +303,48 @@ namespace Compress.ZipFile.ZLib
|
||||
/// int bufferSize = 1024;
|
||||
/// byte[] buffer = new byte[bufferSize];
|
||||
/// ZlibCodec decompressor = new ZlibCodec();
|
||||
///
|
||||
///
|
||||
/// Console.WriteLine("\n============================================");
|
||||
/// Console.WriteLine("Size of Buffer to Inflate: {0} bytes.", CompressedBytes.Length);
|
||||
/// MemoryStream ms = new MemoryStream(DecompressedBytes);
|
||||
///
|
||||
///
|
||||
/// int rc = decompressor.InitializeInflate();
|
||||
///
|
||||
///
|
||||
/// decompressor.InputBuffer = CompressedBytes;
|
||||
/// decompressor.NextIn = 0;
|
||||
/// decompressor.AvailableBytesIn = CompressedBytes.Length;
|
||||
///
|
||||
///
|
||||
/// decompressor.OutputBuffer = buffer;
|
||||
///
|
||||
/// // pass 1: inflate
|
||||
///
|
||||
/// // pass 1: inflate
|
||||
/// do
|
||||
/// {
|
||||
/// decompressor.NextOut = 0;
|
||||
/// decompressor.AvailableBytesOut = buffer.Length;
|
||||
/// rc = decompressor.Inflate(FlushType.None);
|
||||
///
|
||||
///
|
||||
/// if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END)
|
||||
/// throw new Exception("inflating: " + decompressor.Message);
|
||||
///
|
||||
///
|
||||
/// ms.Write(decompressor.OutputBuffer, 0, buffer.Length - decompressor.AvailableBytesOut);
|
||||
/// }
|
||||
/// while (decompressor.AvailableBytesIn > 0 || decompressor.AvailableBytesOut == 0);
|
||||
///
|
||||
///
|
||||
/// // pass 2: finish and flush
|
||||
/// do
|
||||
/// {
|
||||
/// decompressor.NextOut = 0;
|
||||
/// decompressor.AvailableBytesOut = buffer.Length;
|
||||
/// rc = decompressor.Inflate(FlushType.Finish);
|
||||
///
|
||||
///
|
||||
/// if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK)
|
||||
/// throw new Exception("inflating: " + decompressor.Message);
|
||||
///
|
||||
///
|
||||
/// if (buffer.Length - decompressor.AvailableBytesOut > 0)
|
||||
/// ms.Write(buffer, 0, buffer.Length - decompressor.AvailableBytesOut);
|
||||
/// }
|
||||
/// while (decompressor.AvailableBytesIn > 0 || decompressor.AvailableBytesOut == 0);
|
||||
///
|
||||
///
|
||||
/// decompressor.EndInflate();
|
||||
/// }
|
||||
///
|
||||
@@ -361,10 +361,10 @@ namespace Compress.ZipFile.ZLib
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Ends an inflation session.
|
||||
/// Ends an inflation session.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Call this after successively calling Inflate(). This will cause all buffers to be flushed.
|
||||
/// Call this after successively calling Inflate(). This will cause all buffers to be flushed.
|
||||
/// After calling this you cannot call Inflate() without a intervening call to one of the
|
||||
/// InitializeInflate() overloads.
|
||||
/// </remarks>
|
||||
@@ -400,32 +400,32 @@ namespace Compress.ZipFile.ZLib
|
||||
/// int bufferSize = 40000;
|
||||
/// byte[] CompressedBytes = new byte[bufferSize];
|
||||
/// byte[] DecompressedBytes = new byte[bufferSize];
|
||||
///
|
||||
///
|
||||
/// ZlibCodec compressor = new ZlibCodec();
|
||||
///
|
||||
///
|
||||
/// compressor.InitializeDeflate(CompressionLevel.Default);
|
||||
///
|
||||
///
|
||||
/// compressor.InputBuffer = System.Text.ASCIIEncoding.ASCII.GetBytes(TextToCompress);
|
||||
/// compressor.NextIn = 0;
|
||||
/// compressor.AvailableBytesIn = compressor.InputBuffer.Length;
|
||||
///
|
||||
///
|
||||
/// compressor.OutputBuffer = CompressedBytes;
|
||||
/// compressor.NextOut = 0;
|
||||
/// compressor.AvailableBytesOut = CompressedBytes.Length;
|
||||
///
|
||||
///
|
||||
/// while (compressor.TotalBytesIn != TextToCompress.Length && compressor.TotalBytesOut < bufferSize)
|
||||
/// {
|
||||
/// compressor.Deflate(FlushType.None);
|
||||
/// }
|
||||
///
|
||||
///
|
||||
/// while (true)
|
||||
/// {
|
||||
/// int rc= compressor.Deflate(FlushType.Finish);
|
||||
/// if (rc == ZlibConstants.Z_STREAM_END) break;
|
||||
/// }
|
||||
///
|
||||
///
|
||||
/// compressor.EndDeflate();
|
||||
///
|
||||
///
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <returns>Z_OK if all goes well. You generally don't need to check the return code.</returns>
|
||||
@@ -451,7 +451,7 @@ namespace Compress.ZipFile.ZLib
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel,
|
||||
/// Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel,
|
||||
/// and the explicit flag governing whether to emit an RFC1950 header byte pair.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
@@ -459,7 +459,7 @@ namespace Compress.ZipFile.ZLib
|
||||
/// If you want to generate a zlib stream, you should specify true for
|
||||
/// wantRfc1950Header. In this case, the library will emit a ZLIB
|
||||
/// header, as defined in <see href="http://www.ietf.org/rfc/rfc1950.txt">RFC
|
||||
/// 1950</see>, in the compressed stream.
|
||||
/// 1950</see>, in the compressed stream.
|
||||
/// </remarks>
|
||||
/// <param name="level">The compression level for the codec.</param>
|
||||
/// <param name="wantRfc1950Header">whether to emit an initial RFC1950 byte pair in the compressed stream.</param>
|
||||
@@ -472,8 +472,8 @@ namespace Compress.ZipFile.ZLib
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel,
|
||||
/// and the specified number of window bits.
|
||||
/// Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel,
|
||||
/// and the specified number of window bits.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The codec will use the specified number of window bits and the specified CompressionLevel.
|
||||
@@ -527,59 +527,59 @@ namespace Compress.ZipFile.ZLib
|
||||
/// int bufferSize = 1024;
|
||||
/// byte[] buffer = new byte[bufferSize];
|
||||
/// ZlibCodec compressor = new ZlibCodec();
|
||||
///
|
||||
///
|
||||
/// Console.WriteLine("\n============================================");
|
||||
/// Console.WriteLine("Size of Buffer to Deflate: {0} bytes.", UncompressedBytes.Length);
|
||||
/// MemoryStream ms = new MemoryStream();
|
||||
///
|
||||
///
|
||||
/// int rc = compressor.InitializeDeflate(level);
|
||||
///
|
||||
///
|
||||
/// compressor.InputBuffer = UncompressedBytes;
|
||||
/// compressor.NextIn = 0;
|
||||
/// compressor.AvailableBytesIn = UncompressedBytes.Length;
|
||||
///
|
||||
///
|
||||
/// compressor.OutputBuffer = buffer;
|
||||
///
|
||||
/// // pass 1: deflate
|
||||
///
|
||||
/// // pass 1: deflate
|
||||
/// do
|
||||
/// {
|
||||
/// compressor.NextOut = 0;
|
||||
/// compressor.AvailableBytesOut = buffer.Length;
|
||||
/// rc = compressor.Deflate(FlushType.None);
|
||||
///
|
||||
///
|
||||
/// if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END)
|
||||
/// throw new Exception("deflating: " + compressor.Message);
|
||||
///
|
||||
///
|
||||
/// ms.Write(compressor.OutputBuffer, 0, buffer.Length - compressor.AvailableBytesOut);
|
||||
/// }
|
||||
/// while (compressor.AvailableBytesIn > 0 || compressor.AvailableBytesOut == 0);
|
||||
///
|
||||
///
|
||||
/// // pass 2: finish and flush
|
||||
/// do
|
||||
/// {
|
||||
/// compressor.NextOut = 0;
|
||||
/// compressor.AvailableBytesOut = buffer.Length;
|
||||
/// rc = compressor.Deflate(FlushType.Finish);
|
||||
///
|
||||
///
|
||||
/// if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK)
|
||||
/// throw new Exception("deflating: " + compressor.Message);
|
||||
///
|
||||
///
|
||||
/// if (buffer.Length - compressor.AvailableBytesOut > 0)
|
||||
/// ms.Write(buffer, 0, buffer.Length - compressor.AvailableBytesOut);
|
||||
/// }
|
||||
/// while (compressor.AvailableBytesIn > 0 || compressor.AvailableBytesOut == 0);
|
||||
///
|
||||
///
|
||||
/// compressor.EndDeflate();
|
||||
///
|
||||
///
|
||||
/// ms.Seek(0, SeekOrigin.Begin);
|
||||
/// CompressedBytes = new byte[compressor.TotalBytesOut];
|
||||
/// ms.Read(CompressedBytes, 0, CompressedBytes.Length);
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <param name="flush">whether to flush all data as you deflate. Generally you will want to
|
||||
/// use Z_NO_FLUSH here, in a series of calls to Deflate(), and then call EndDeflate() to
|
||||
/// flush everything.
|
||||
/// <param name="flush">whether to flush all data as you deflate. Generally you will want to
|
||||
/// use Z_NO_FLUSH here, in a series of calls to Deflate(), and then call EndDeflate() to
|
||||
/// flush everything.
|
||||
/// </param>
|
||||
/// <returns>Z_OK if all goes well.</returns>
|
||||
public int Deflate(FlushType flush)
|
||||
@@ -677,10 +677,10 @@ namespace Compress.ZipFile.ZLib
|
||||
|
||||
Array.Copy(dstate.pending, dstate.nextPending, OutputBuffer, NextOut, len);
|
||||
|
||||
NextOut += len;
|
||||
dstate.nextPending += len;
|
||||
TotalBytesOut += len;
|
||||
AvailableBytesOut -= len;
|
||||
NextOut += len;
|
||||
dstate.nextPending += len;
|
||||
TotalBytesOut += len;
|
||||
AvailableBytesOut -= len;
|
||||
dstate.pendingCount -= len;
|
||||
if (dstate.pendingCount == 0)
|
||||
{
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
// ZlibConstants.cs
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
|
||||
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code module is part of DotNetZip, a zipfile class library.
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// This code is licensed under the Microsoft Public License.
|
||||
// This code is licensed under the Microsoft Public License.
|
||||
// See the file License.txt for the license details.
|
||||
// More info on: http://dotnetzip.codeplex.com
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// last saved (in emacs):
|
||||
// last saved (in emacs):
|
||||
// Time-stamp: <2009-November-03 18:50:19>
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
@@ -25,22 +25,22 @@
|
||||
// copyright to that code is included here.
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in
|
||||
// the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
//
|
||||
// 3. The names of the authors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
@@ -51,7 +51,7 @@
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
//
|
||||
// This program is based on zlib-1.1.3; credit to authors
|
||||
@@ -89,7 +89,7 @@ namespace Compress.ZipFile.ZLib
|
||||
public const int Z_STREAM_END = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The operation ended in need of a dictionary.
|
||||
/// The operation ended in need of a dictionary.
|
||||
/// </summary>
|
||||
public const int Z_NEED_DICT = 2;
|
||||
|
||||
@@ -111,10 +111,10 @@ namespace Compress.ZipFile.ZLib
|
||||
/// <summary>
|
||||
/// The size of the working buffer used in the ZlibCodec class. Defaults to 8192 bytes.
|
||||
/// </summary>
|
||||
#if NETCF
|
||||
#if NETCF
|
||||
public const int WorkingBufferSizeDefault = 8192;
|
||||
#else
|
||||
public const int WorkingBufferSizeDefault = 16384;
|
||||
public const int WorkingBufferSizeDefault = 16384;
|
||||
#endif
|
||||
/// <summary>
|
||||
/// The minimum size of the working buffer used in the ZlibCodec class. Currently it is 128 bytes.
|
||||
@@ -123,3 +123,4 @@ namespace Compress.ZipFile.ZLib
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
140
SabreTools.FileTypes/Compress/ZipFile/Zip.cs
Normal file
140
SabreTools.FileTypes/Compress/ZipFile/Zip.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using FileInfo = RVIO.FileInfo;
|
||||
|
||||
// UInt16 = ushort
|
||||
// UInt32 = uint
|
||||
// ULong = ulong
|
||||
|
||||
namespace Compress.ZipFile
|
||||
{
|
||||
public partial class Zip : ICompress
|
||||
{
|
||||
private readonly List<LocalFile> _localFiles = new List<LocalFile>();
|
||||
|
||||
|
||||
private FileInfo _zipFileInfo;
|
||||
|
||||
|
||||
private byte[] _fileComment;
|
||||
private Stream _zipFs;
|
||||
|
||||
private uint _localFilesCount;
|
||||
|
||||
private bool _zip64;
|
||||
|
||||
public string ZipFilename => _zipFileInfo != null ? _zipFileInfo.FullName : "";
|
||||
|
||||
public long TimeStamp => _zipFileInfo?.LastWriteTime ?? 0;
|
||||
|
||||
public ZipOpenType ZipOpen { get; private set; }
|
||||
|
||||
|
||||
public ZipStatus ZipStatus { get; set; }
|
||||
|
||||
public int LocalFilesCount()
|
||||
{
|
||||
return _localFiles.Count;
|
||||
}
|
||||
|
||||
public string Filename(int i)
|
||||
{
|
||||
return _localFiles[i].FileName;
|
||||
}
|
||||
|
||||
public ulong UncompressedSize(int i)
|
||||
{
|
||||
return _localFiles[i].UncompressedSize;
|
||||
}
|
||||
|
||||
public ulong? LocalHeader(int i)
|
||||
{
|
||||
return (_localFiles[i].GeneralPurposeBitFlag & 8) == 0 ? (ulong?)_localFiles[i].RelativeOffsetOfLocalHeader : null;
|
||||
}
|
||||
|
||||
public byte[] CRC32(int i)
|
||||
{
|
||||
return _localFiles[i].CRC;
|
||||
}
|
||||
|
||||
public bool IsDirectory(int i)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_localFiles[i].UncompressedSize != 0)
|
||||
return false;
|
||||
string filename = _localFiles[i].FileName;
|
||||
char lastChar = filename[filename.Length - 1];
|
||||
return lastChar == '/' || lastChar == '\\';
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ArgumentException argEx = new ArgumentException("Error in file " + _zipFileInfo?.FullName + " : " + ex.Message, ex.InnerException);
|
||||
throw argEx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public long LastModified(int i)
|
||||
{
|
||||
return _localFiles[i].DateTime;
|
||||
}
|
||||
|
||||
public long? Created(int i)
|
||||
{
|
||||
return _localFiles[i].DateTimeCreate;
|
||||
}
|
||||
|
||||
public long? Accessed(int i)
|
||||
{
|
||||
return _localFiles[i].DateTimeAccess;
|
||||
}
|
||||
|
||||
public void ZipFileClose()
|
||||
{
|
||||
if (ZipOpen == ZipOpenType.Closed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ZipOpen == ZipOpenType.OpenRead)
|
||||
{
|
||||
zipFileCloseRead();
|
||||
return;
|
||||
}
|
||||
|
||||
zipFileCloseWrite();
|
||||
}
|
||||
|
||||
public byte[] Filecomment => _fileComment;
|
||||
|
||||
/*
|
||||
public void BreakTrrntZip(string filename)
|
||||
{
|
||||
_zipFs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite);
|
||||
using (BinaryReader zipBr = new BinaryReader(_zipFs,Encoding.UTF8,true))
|
||||
{
|
||||
_zipFs.Position = _zipFs.Length - 22;
|
||||
byte[] fileComment = zipBr.ReadBytes(22);
|
||||
if (GetString(fileComment).Substring(0, 14) == "TORRENTZIPPED-")
|
||||
{
|
||||
_zipFs.Position = _zipFs.Length - 8;
|
||||
_zipFs.WriteByte(48); _zipFs.WriteByte(48); _zipFs.WriteByte(48); _zipFs.WriteByte(48);
|
||||
_zipFs.WriteByte(48); _zipFs.WriteByte(48); _zipFs.WriteByte(48); _zipFs.WriteByte(48);
|
||||
}
|
||||
}
|
||||
_zipFs.Flush();
|
||||
_zipFs.Close();
|
||||
}
|
||||
*/
|
||||
|
||||
~Zip()
|
||||
{
|
||||
ZipFileClose();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
239
SabreTools.FileTypes/Compress/ZipFile/ZipCentralDir.cs
Normal file
239
SabreTools.FileTypes/Compress/ZipFile/ZipCentralDir.cs
Normal file
@@ -0,0 +1,239 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Compress.ZipFile
|
||||
{
|
||||
public partial class Zip
|
||||
{
|
||||
private const uint EndOfCentralDirSignature = 0x06054b50;
|
||||
private const uint Zip64EndOfCentralDirSignature = 0x06064b50;
|
||||
private const uint Zip64EndOfCentralDirectoryLocator = 0x07064b50;
|
||||
|
||||
private ZipReturn FindEndOfCentralDirSignature()
|
||||
{
|
||||
long fileSize = _zipFs.Length;
|
||||
long maxBackSearch = 0xffff;
|
||||
|
||||
if (_zipFs.Length < maxBackSearch)
|
||||
{
|
||||
maxBackSearch = fileSize;
|
||||
}
|
||||
|
||||
const long buffSize = 0x400;
|
||||
|
||||
byte[] buffer = new byte[buffSize + 4];
|
||||
|
||||
long backPosition = 4;
|
||||
while (backPosition < maxBackSearch)
|
||||
{
|
||||
backPosition += buffSize;
|
||||
if (backPosition > maxBackSearch)
|
||||
{
|
||||
backPosition = maxBackSearch;
|
||||
}
|
||||
|
||||
long readSize = backPosition > buffSize + 4 ? buffSize + 4 : backPosition;
|
||||
|
||||
_zipFs.Position = fileSize - backPosition;
|
||||
|
||||
_zipFs.Read(buffer, 0, (int)readSize);
|
||||
|
||||
|
||||
for (long i = readSize - 4; i >= 0; i--)
|
||||
{
|
||||
if (buffer[i] != 0x50 || buffer[i + 1] != 0x4b || buffer[i + 2] != 0x05 || buffer[i + 3] != 0x06)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_zipFs.Position = fileSize - backPosition + i;
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
}
|
||||
return ZipReturn.ZipCentralDirError;
|
||||
}
|
||||
|
||||
|
||||
private ZipReturn EndOfCentralDirRead()
|
||||
{
|
||||
using (BinaryReader zipBr = new BinaryReader(_zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
uint thisSignature = zipBr.ReadUInt32();
|
||||
if (thisSignature != EndOfCentralDirSignature)
|
||||
{
|
||||
return ZipReturn.ZipEndOfCentralDirectoryError;
|
||||
}
|
||||
|
||||
ushort tUShort = zipBr.ReadUInt16(); // NumberOfThisDisk
|
||||
if (tUShort != 0)
|
||||
{
|
||||
return ZipReturn.ZipEndOfCentralDirectoryError;
|
||||
}
|
||||
|
||||
tUShort = zipBr.ReadUInt16(); // NumberOfThisDiskCenterDir
|
||||
if (tUShort != 0)
|
||||
{
|
||||
return ZipReturn.ZipEndOfCentralDirectoryError;
|
||||
}
|
||||
|
||||
_localFilesCount = zipBr.ReadUInt16(); // TotalNumberOfEntriesDisk
|
||||
|
||||
tUShort = zipBr.ReadUInt16(); // TotalNumber of entries in the central directory
|
||||
if (tUShort != _localFilesCount)
|
||||
{
|
||||
return ZipReturn.ZipEndOfCentralDirectoryError;
|
||||
}
|
||||
|
||||
_centralDirSize = zipBr.ReadUInt32(); // SizeOfCentralDir
|
||||
_centralDirStart = zipBr.ReadUInt32(); // Offset
|
||||
|
||||
ushort zipFileCommentLength = zipBr.ReadUInt16();
|
||||
|
||||
_fileComment = zipBr.ReadBytes(zipFileCommentLength);
|
||||
|
||||
if (_zipFs.Position != _zipFs.Length)
|
||||
{
|
||||
ZipStatus |= ZipStatus.ExtraData;
|
||||
}
|
||||
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void EndOfCentralDirWrite()
|
||||
{
|
||||
using (BinaryWriter bw = new BinaryWriter(_zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
bw.Write(EndOfCentralDirSignature);
|
||||
bw.Write((ushort)0); // NumberOfThisDisk
|
||||
bw.Write((ushort)0); // NumberOfThisDiskCenterDir
|
||||
bw.Write((ushort)(_localFiles.Count >= 0xffff ? 0xffff : _localFiles.Count)); // TotalNumberOfEntriesDisk
|
||||
bw.Write((ushort)(_localFiles.Count >= 0xffff ? 0xffff : _localFiles.Count)); // TotalNumber of entries in the central directory
|
||||
bw.Write((uint)(_centralDirSize >= 0xffffffff ? 0xffffffff : _centralDirSize));
|
||||
bw.Write((uint)(_centralDirStart >= 0xffffffff ? 0xffffffff : _centralDirStart));
|
||||
bw.Write((ushort)_fileComment.Length);
|
||||
bw.Write(_fileComment, 0, _fileComment.Length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private ZipReturn Zip64EndOfCentralDirRead()
|
||||
{
|
||||
using (BinaryReader zipBr = new BinaryReader(_zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
uint thisSignature = zipBr.ReadUInt32();
|
||||
if (thisSignature != Zip64EndOfCentralDirSignature)
|
||||
{
|
||||
return ZipReturn.ZipEndOfCentralDirectoryError;
|
||||
}
|
||||
|
||||
//_zip64 = true;
|
||||
ulong tULong = zipBr.ReadUInt64(); // Size of zip64 end of central directory record
|
||||
if (tULong != 44)
|
||||
{
|
||||
return ZipReturn.Zip64EndOfCentralDirError;
|
||||
}
|
||||
|
||||
zipBr.ReadUInt16(); // version made by
|
||||
|
||||
ushort tUShort = zipBr.ReadUInt16(); // version needed to extract
|
||||
if (tUShort != 45)
|
||||
{
|
||||
return ZipReturn.Zip64EndOfCentralDirError;
|
||||
}
|
||||
|
||||
uint tUInt = zipBr.ReadUInt32(); // number of this disk
|
||||
if (tUInt != 0)
|
||||
{
|
||||
return ZipReturn.Zip64EndOfCentralDirError;
|
||||
}
|
||||
|
||||
tUInt = zipBr.ReadUInt32(); // number of the disk with the start of the central directory
|
||||
if (tUInt != 0)
|
||||
{
|
||||
return ZipReturn.Zip64EndOfCentralDirError;
|
||||
}
|
||||
|
||||
_localFilesCount =
|
||||
(uint)zipBr.ReadUInt64(); // total number of entries in the central directory on this disk
|
||||
|
||||
tULong = zipBr.ReadUInt64(); // total number of entries in the central directory
|
||||
if (tULong != _localFilesCount)
|
||||
{
|
||||
return ZipReturn.Zip64EndOfCentralDirError;
|
||||
}
|
||||
|
||||
_zip64 = true;
|
||||
_centralDirSize = zipBr.ReadUInt64(); // size of central directory
|
||||
|
||||
_centralDirStart = zipBr.ReadUInt64(); // offset of start of central directory with respect to the starting disk number
|
||||
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Zip64EndOfCentralDirWrite()
|
||||
{
|
||||
using (BinaryWriter bw = new BinaryWriter(_zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
bw.Write(Zip64EndOfCentralDirSignature);
|
||||
bw.Write((ulong)44); // Size of zip64 end of central directory record
|
||||
bw.Write((ushort)45); // version made by
|
||||
bw.Write((ushort)45); // version needed to extract
|
||||
bw.Write((uint)0); // number of this disk
|
||||
bw.Write((uint)0); // number of the disk with the start of the central directory
|
||||
bw.Write((ulong)_localFiles.Count); // total number of entries in the central directory on this disk
|
||||
bw.Write((ulong)_localFiles.Count); // total number of entries in the central directory
|
||||
bw.Write(_centralDirSize); // size of central directory
|
||||
bw.Write(_centralDirStart); // offset of start of central directory with respect to the starting disk number
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ZipReturn Zip64EndOfCentralDirectoryLocatorRead()
|
||||
{
|
||||
using (BinaryReader zipBr = new BinaryReader(_zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
uint thisSignature = zipBr.ReadUInt32();
|
||||
if (thisSignature != Zip64EndOfCentralDirectoryLocator)
|
||||
{
|
||||
return ZipReturn.ZipEndOfCentralDirectoryError;
|
||||
}
|
||||
|
||||
uint tUInt = zipBr.ReadUInt32(); // number of the disk with the start of the zip64 end of central directory
|
||||
if (tUInt != 0)
|
||||
{
|
||||
return ZipReturn.Zip64EndOfCentralDirectoryLocatorError;
|
||||
}
|
||||
|
||||
_endOfCenterDir64 = zipBr.ReadUInt64(); // relative offset of the zip64 end of central directory record
|
||||
|
||||
tUInt = zipBr.ReadUInt32(); // total number of disks
|
||||
if (tUInt != 1)
|
||||
{
|
||||
return ZipReturn.Zip64EndOfCentralDirectoryLocatorError;
|
||||
}
|
||||
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
}
|
||||
|
||||
private void Zip64EndOfCentralDirectoryLocatorWrite()
|
||||
{
|
||||
using (BinaryWriter bw = new BinaryWriter(_zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
bw.Write(Zip64EndOfCentralDirectoryLocator);
|
||||
bw.Write((uint)0); // number of the disk with the start of the zip64 end of central directory
|
||||
bw.Write(_endOfCenterDir64); // relative offset of the zip64 end of central directory record
|
||||
bw.Write((uint)1); // total number of disks
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
605
SabreTools.FileTypes/Compress/ZipFile/ZipExtraField.cs
Normal file
605
SabreTools.FileTypes/Compress/ZipFile/ZipExtraField.cs
Normal file
@@ -0,0 +1,605 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Compress.Utils;
|
||||
|
||||
namespace Compress.ZipFile
|
||||
{
|
||||
internal partial class LocalFile
|
||||
{
|
||||
private static class ZipExtraField
|
||||
{
|
||||
public static ZipReturn ReadLocalExtraField(byte[] extraField, byte[] bFileName, LocalFile lf, bool centralDir)
|
||||
{
|
||||
int extraFieldLength = extraField.Length;
|
||||
|
||||
lf.Zip64 = false;
|
||||
int blockPos = 0;
|
||||
while (extraFieldLength > blockPos)
|
||||
{
|
||||
ushort type = BitConverter.ToUInt16(extraField, blockPos);
|
||||
blockPos += 2;
|
||||
ushort blockLength = BitConverter.ToUInt16(extraField, blockPos);
|
||||
blockPos += 2;
|
||||
|
||||
int pos = blockPos;
|
||||
switch (type)
|
||||
{
|
||||
/*
|
||||
-Zip64 Extended Information Extra Field (0x0001):
|
||||
===============================================
|
||||
|
||||
The following is the layout of the zip64 extended
|
||||
information "extra" block. If one of the size or
|
||||
offset fields in the Local or Central directory
|
||||
record is too small to hold the required data,
|
||||
a zip64 extended information record is created.
|
||||
The order of the fields in the zip64 extended
|
||||
information record is fixed, but the fields will
|
||||
only appear if the corresponding Local or Central
|
||||
directory record field is set to 0xFFFF or 0xFFFFFFFF.
|
||||
|
||||
Note: all fields stored in Intel low-byte/high-byte order.
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(ZIP64) 0x0001 2 bytes Tag for this "extra" block type
|
||||
Size 2 bytes Size of this "extra" block
|
||||
Original
|
||||
Size 8 bytes Original uncompressed file size
|
||||
Compressed
|
||||
Size 8 bytes Size of compressed data
|
||||
Relative Header
|
||||
Offset 8 bytes Offset of local header record
|
||||
Disk Start
|
||||
Number 4 bytes Number of the disk on which
|
||||
this file starts
|
||||
|
||||
This entry in the Local header must include BOTH original
|
||||
and compressed file size fields. If encrypting the
|
||||
central directory and bit 13 of the general purpose bit
|
||||
flag is set indicating masking, the value stored in the
|
||||
Local Header for the original file size will be zero.
|
||||
*/
|
||||
case 0x0001:
|
||||
lf.Zip64 = true;
|
||||
if (centralDir)
|
||||
{
|
||||
if (lf.UncompressedSize == 0xffffffff)
|
||||
{
|
||||
lf.UncompressedSize = BitConverter.ToUInt64(extraField, pos);
|
||||
pos += 8;
|
||||
}
|
||||
if (lf._compressedSize == 0xffffffff)
|
||||
{
|
||||
lf._compressedSize = BitConverter.ToUInt64(extraField, pos);
|
||||
pos += 8;
|
||||
}
|
||||
if (lf.RelativeOffsetOfLocalHeader == 0xffffffff)
|
||||
{
|
||||
lf.RelativeOffsetOfLocalHeader = BitConverter.ToUInt64(extraField, pos);
|
||||
pos += 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lf._localHeaderUncompressedSize == 0xffffffff)
|
||||
{
|
||||
lf._localHeaderUncompressedSize = BitConverter.ToUInt64(extraField, pos);
|
||||
pos += 8;
|
||||
}
|
||||
if (lf._localHeaderCompressedSize == 0xffffffff)
|
||||
{
|
||||
lf._localHeaderCompressedSize = BitConverter.ToUInt64(extraField, pos);
|
||||
pos += 8;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/* PKWARE's authenticity verification */
|
||||
case 0x0007: // Not Needed
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
-PKWARE Win95/WinNT Extra Field (0x000a):
|
||||
=======================================
|
||||
|
||||
The following description covers PKWARE's "NTFS" attributes
|
||||
"extra" block, introduced with the release of PKZIP 2.50 for
|
||||
Windows. (Last Revision 20001118)
|
||||
|
||||
(Note: At this time the Mtime, Atime and Ctime values may
|
||||
be used on any WIN32 system.)
|
||||
[Info-ZIP note: In the current implementations, this field has
|
||||
a fixed total data size of 32 bytes and is only stored as local
|
||||
extra field.]
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(NTFS) 0x000a Short Tag for this "extra" block type
|
||||
TSize Short Total Data Size for this block
|
||||
Reserved Long for future use
|
||||
Tag1 Short NTFS attribute tag value #1
|
||||
Size1 Short Size of attribute #1, in bytes
|
||||
(var.) SubSize1 Attribute #1 data
|
||||
.
|
||||
.
|
||||
.
|
||||
TagN Short NTFS attribute tag value #N
|
||||
SizeN Short Size of attribute #N, in bytes
|
||||
(var.) SubSizeN Attribute #N data
|
||||
|
||||
For NTFS, values for Tag1 through TagN are as follows:
|
||||
(currently only one set of attributes is defined for NTFS)
|
||||
|
||||
Tag Size Description
|
||||
----- ---- -----------
|
||||
0x0001 2 bytes Tag for attribute #1
|
||||
Size1 2 bytes Size of attribute #1, in bytes (24)
|
||||
Mtime 8 bytes 64-bit NTFS file last modification time
|
||||
Atime 8 bytes 64-bit NTFS file last access time
|
||||
Ctime 8 bytes 64-bit NTFS file creation time
|
||||
|
||||
The total length for this block is 28 bytes, resulting in a
|
||||
fixed size value of 32 for the TSize field of the NTFS block.
|
||||
|
||||
The NTFS filetimes are 64-bit unsigned integers, stored in Intel
|
||||
(least significant byte first) byte order. They determine the
|
||||
number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch",
|
||||
which is "01-Jan-1601 00:00:00 UTC".
|
||||
*/
|
||||
case 0x000a:
|
||||
pos += 4; // Reserved Long for future use
|
||||
int tag1 = BitConverter.ToInt16(extraField, pos); // Tag1 Short NTFS attribute tag value #1
|
||||
pos += 2;
|
||||
int size1 = BitConverter.ToInt16(extraField, pos); // Size1 Short Size of attribute #1, in bytes
|
||||
pos += 2;
|
||||
if (tag1 == 0x0001 && size1 == 24
|
||||
) // (currently only one set of attributes is defined for NTFS)
|
||||
{
|
||||
lf.mTime = ZipUtils.FileTimeToUTCTime(BitConverter.ToInt64(extraField, pos)); // Mtime 8 bytes 64-bit NTFS file last modification time
|
||||
pos += 8;
|
||||
lf.aTime = ZipUtils.FileTimeToUTCTime(BitConverter.ToInt64(extraField, pos)); // Atime 8 bytes 64-bit NTFS file last access time
|
||||
pos += 8;
|
||||
lf.cTime = ZipUtils.FileTimeToUTCTime(BitConverter.ToInt64(extraField, pos)); // Ctime 8 bytes 64-bit NTFS file creation time
|
||||
pos += 8;
|
||||
|
||||
Debug.WriteLine("modtime = " + new DateTime((long)lf.mTime));
|
||||
Debug.WriteLine("Acctime = " + new DateTime((long)lf.aTime));
|
||||
Debug.WriteLine("Cretime = " + new DateTime((long)lf.cTime));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
-Windows NT Security Descriptor Extra Field (0x4453):
|
||||
===================================================
|
||||
|
||||
The following is the layout of the NT Security Descriptor (another
|
||||
type of ACL) extra block. (Last Revision 19960922)
|
||||
|
||||
Local-header version:
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(SD) 0x4453 Short tag for this extra block type ("SD")
|
||||
TSize Short total data size for this block
|
||||
BSize Long uncompressed SD data size
|
||||
Version Byte version of uncompressed SD data format
|
||||
CType Short compression type
|
||||
EACRC Long CRC value for uncompressed SD data
|
||||
(var.) variable compressed SD data
|
||||
|
||||
Central-header version:
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(SD) 0x4453 Short tag for this extra block type ("SD")
|
||||
TSize Short total data size for this block (4)
|
||||
BSize Long size of uncompressed local SD data
|
||||
|
||||
The value of CType is interpreted according to the "compression
|
||||
method" section above; i.e., 0 for stored, 8 for deflated, etc.
|
||||
Version specifies how the compressed data are to be interpreted
|
||||
and allows for future expansion of this extra field type. Currently
|
||||
only version 0 is defined.
|
||||
|
||||
For version 0, the compressed data are to be interpreted as a single
|
||||
valid Windows NT SECURITY_DESCRIPTOR data structure, in self-relative
|
||||
format.
|
||||
|
||||
*/
|
||||
case 0x4453: // Not Needed
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
-FWKCS MD5 Extra Field (0x4b46):
|
||||
==============================
|
||||
|
||||
The FWKCS Contents_Signature System, used in automatically
|
||||
identifying files independent of filename, optionally adds
|
||||
and uses an extra field to support the rapid creation of
|
||||
an enhanced contents_signature.
|
||||
There is no local-header version; the following applies
|
||||
only to the central header. (Last Revision 19961207)
|
||||
|
||||
Central-header version:
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(MD5) 0x4b46 Short tag for this extra block type ("FK")
|
||||
TSize Short total data size for this block (19)
|
||||
"MD5" 3 bytes extra-field signature
|
||||
MD5hash 16 bytes 128-bit MD5 hash of uncompressed data
|
||||
(low byte first)
|
||||
|
||||
When FWKCS revises a .ZIP file central directory to add
|
||||
this extra field for a file, it also replaces the
|
||||
central directory entry for that file's uncompressed
|
||||
file length with a measured value.
|
||||
|
||||
FWKCS provides an option to strip this extra field, if
|
||||
present, from a .ZIP file central directory. In adding
|
||||
this extra field, FWKCS preserves .ZIP file Authenticity
|
||||
Verification; if stripping this extra field, FWKCS
|
||||
preserves all versions of AV through PKZIP version 2.04g.
|
||||
|
||||
FWKCS, and FWKCS Contents_Signature System, are
|
||||
trademarks of Frederick W. Kantor.
|
||||
|
||||
(1) R. Rivest, RFC1321.TXT, MIT Laboratory for Computer
|
||||
Science and RSA Data Security, Inc., April 1992.
|
||||
ll.76-77: "The MD5 algorithm is being placed in the
|
||||
public domain for review and possible adoption as a
|
||||
standard."
|
||||
*/
|
||||
case 0x4B46: // Not Needed
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
-Extended Timestamp Extra Field:
|
||||
==============================
|
||||
|
||||
The following is the layout of the extended-timestamp extra block.
|
||||
(Last Revision 19970118)
|
||||
|
||||
Local-header version:
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(time) 0x5455 Short tag for this extra block type ("UT")
|
||||
TSize Short total data size for this block
|
||||
Flags Byte info bits
|
||||
(ModTime) Long time of last modification (UTC/GMT)
|
||||
(AcTime) Long time of last access (UTC/GMT)
|
||||
(CrTime) Long time of original creation (UTC/GMT)
|
||||
|
||||
Central-header version:
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(time) 0x5455 Short tag for this extra block type ("UT")
|
||||
TSize Short total data size for this block
|
||||
Flags Byte info bits (refers to local header!)
|
||||
(ModTime) Long time of last modification (UTC/GMT)
|
||||
|
||||
The central-header extra field contains the modification time only,
|
||||
or no timestamp at all. TSize is used to flag its presence or
|
||||
absence. But note:
|
||||
|
||||
If "Flags" indicates that Modtime is present in the local header
|
||||
field, it MUST be present in the central header field, too!
|
||||
This correspondence is required because the modification time
|
||||
value may be used to support trans-timezone freshening and
|
||||
updating operations with zip archives.
|
||||
|
||||
The time values are in standard Unix signed-long format, indicating
|
||||
the number of seconds since 1 January 1970 00:00:00. The times
|
||||
are relative to Coordinated Universal Time (UTC), also sometimes
|
||||
referred to as Greenwich Mean Time (GMT). To convert to local time,
|
||||
the software must know the local timezone offset from UTC/GMT.
|
||||
|
||||
The lower three bits of Flags in both headers indicate which time-
|
||||
stamps are present in the LOCAL extra field:
|
||||
|
||||
bit 0 if set, modification time is present
|
||||
bit 1 if set, access time is present
|
||||
bit 2 if set, creation time is present
|
||||
bits 3-7 reserved for additional timestamps; not set
|
||||
|
||||
Those times that are present will appear in the order indicated, but
|
||||
any combination of times may be omitted. (Creation time may be
|
||||
present without access time, for example.) TSize should equal
|
||||
(1 + 4*(number of set bits in Flags)), as the block is currently
|
||||
defined. Other timestamps may be added in the future.
|
||||
*/
|
||||
case 0x5455:
|
||||
byte flags = extraField[pos];
|
||||
pos += 1;
|
||||
if ((flags & 1) == 1)
|
||||
{
|
||||
lf.mTime = ZipUtils.SetDateTimeFromUnixSeconds(BitConverter.ToInt32(extraField, pos)); // (ModTime) Long time of last modification (UTC/GMT)
|
||||
Debug.WriteLine("Umodtime = " + new DateTime((long)lf.mTime));
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
if (!centralDir)
|
||||
{
|
||||
if ((flags & 2) == 2)
|
||||
{
|
||||
lf.aTime = ZipUtils.SetDateTimeFromUnixSeconds(BitConverter.ToInt32(extraField, pos)); // (AcTime) Long time of last access (UTC/GMT)
|
||||
Debug.WriteLine("UAcctime = " + new DateTime((long)lf.aTime));
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
if ((flags & 4) == 4)
|
||||
{
|
||||
lf.cTime = ZipUtils.SetDateTimeFromUnixSeconds(BitConverter.ToInt32(extraField, pos)); // (CrTime) Long time of original creation (UTC/GMT)
|
||||
Debug.WriteLine("UCretime = " + new DateTime((long)lf.cTime));
|
||||
pos += 4;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
-Info-ZIP Unix Extra Field (type 1):
|
||||
==================================
|
||||
|
||||
The following is the layout of the old Info-ZIP extra block for
|
||||
Unix. It has been replaced by the extended-timestamp extra block
|
||||
(0x5455) and the Unix type 2 extra block (0x7855).
|
||||
(Last Revision 19970118)
|
||||
|
||||
Local-header version:
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(Unix1) 0x5855 Short tag for this extra block type ("UX")
|
||||
TSize Short total data size for this block
|
||||
AcTime Long time of last access (UTC/GMT)
|
||||
ModTime Long time of last modification (UTC/GMT)
|
||||
UID Short Unix user ID (optional)
|
||||
GID Short Unix group ID (optional)
|
||||
|
||||
Central-header version:
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(Unix1) 0x5855 Short tag for this extra block type ("UX")
|
||||
TSize Short total data size for this block
|
||||
AcTime Long time of last access (GMT/UTC)
|
||||
ModTime Long time of last modification (GMT/UTC)
|
||||
|
||||
The file access and modification times are in standard Unix signed-
|
||||
long format, indicating the number of seconds since 1 January 1970
|
||||
00:00:00. The times are relative to Coordinated Universal Time
|
||||
(UTC), also sometimes referred to as Greenwich Mean Time (GMT). To
|
||||
convert to local time, the software must know the local timezone
|
||||
offset from UTC/GMT. The modification time may be used by non-Unix
|
||||
systems to support inter-timezone freshening and updating of zip
|
||||
archives.
|
||||
|
||||
The local-header extra block may optionally contain UID and GID
|
||||
info for the file. The local-header TSize value is the only
|
||||
indication of this. Note that Unix UIDs and GIDs are usually
|
||||
specific to a particular machine, and they generally require root
|
||||
access to restore.
|
||||
|
||||
This extra field type is obsolete, but it has been in use since
|
||||
mid-1994. Therefore future archiving software should continue to
|
||||
support it. Some guidelines:
|
||||
|
||||
An archive member should either contain the old "Unix1"
|
||||
extra field block or the new extra field types "time" and/or
|
||||
"Unix2".
|
||||
|
||||
If both the old "Unix1" block type and one or both of the new
|
||||
block types "time" and "Unix2" are found, the "Unix1" block
|
||||
should be considered invalid and ignored.
|
||||
|
||||
Unarchiving software should recognize both old and new extra
|
||||
field block types, but the info from new types overrides the
|
||||
old "Unix1" field.
|
||||
|
||||
Archiving software should recognize "Unix1" extra fields for
|
||||
timestamp comparison but never create it for updated, freshened
|
||||
or new archive members. When copying existing members to a new
|
||||
archive, any "Unix1" extra field blocks should be converted to
|
||||
the new "time" and/or "Unix2" types.
|
||||
*/
|
||||
case 0x5855:
|
||||
lf.aTime = ZipUtils.SetDateTimeFromUnixSeconds(BitConverter.ToInt32(extraField, pos)); // AcTime Long time of last access (UTC/GMT)
|
||||
Debug.WriteLine("UAcctime = " + new DateTime((long)lf.aTime));
|
||||
pos += 4;
|
||||
lf.mTime = ZipUtils.SetDateTimeFromUnixSeconds(BitConverter.ToInt32(extraField, pos)); // ModTime Long time of last modification (UTC/GMT)
|
||||
Debug.WriteLine("Umodtime = " + new DateTime((long)lf.mTime));
|
||||
pos += 4;
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
-Info-ZIP Unicode Path Extra Field:
|
||||
=================================
|
||||
|
||||
Stores the UTF-8 version of the entry path as stored in the
|
||||
local header and central directory header.
|
||||
(Last Revision 20070912)
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(UPath) 0x7075 Short tag for this extra block type ("up")
|
||||
TSize Short total data size for this block
|
||||
Version Byte version of this extra field, currently 1
|
||||
NameCRC32 Long CRC-32 checksum of standard name field
|
||||
UnicodeName variable UTF-8 version of the entry file name
|
||||
|
||||
Currently Version is set to the number 1. If there is a need
|
||||
to change this field, the version will be incremented. Changes
|
||||
may not be backward compatible so this extra field should not be
|
||||
used if the version is not recognized.
|
||||
|
||||
The NameCRC32 is the standard zip CRC32 checksum of the File Name
|
||||
field in the header. This is used to verify that the header
|
||||
File Name field has not changed since the Unicode Path extra field
|
||||
was created. This can happen if a utility renames the entry but
|
||||
does not update the UTF-8 path extra field. If the CRC check fails,
|
||||
this UTF-8 Path Extra Field should be ignored and the File Name field
|
||||
in the header should be used instead.
|
||||
|
||||
The UnicodeName is the UTF-8 version of the contents of the File
|
||||
Name field in the header, without any trailing NUL. The standard
|
||||
name field in the Zip entry header remains filled with the entry
|
||||
name coded in the local machine's extended ASCII system charset.
|
||||
As UnicodeName is defined to be UTF-8, no UTF-8 byte order mark
|
||||
(BOM) is used. The length of this field is determined by
|
||||
subtracting the size of the previous fields from TSize.
|
||||
If both the File Name and Comment fields are UTF-8, the new General
|
||||
Purpose Bit Flag, bit 11 (Language encoding flag (EFS)), should be
|
||||
used to indicate that both the header File Name and Comment fields
|
||||
are UTF-8 and, in this case, the Unicode Path and Unicode Comment
|
||||
extra fields are not needed and should not be created. Note that,
|
||||
for backward compatibility, bit 11 should only be used if the native
|
||||
character set of the paths and comments being zipped up are already
|
||||
in UTF-8. The same method, either general purpose bit 11 or extra
|
||||
fields, should be used in both the Local and Central Directory Header
|
||||
for a file.
|
||||
|
||||
Utilisation rules:
|
||||
1. This field shall never be created for names consisting solely of
|
||||
7-bit ASCII characters.
|
||||
2. On a system that already uses UTF-8 as system charset, this field
|
||||
shall not repeat the string pattern already stored in the Zip
|
||||
entry's standard name field. Instead, a field of exactly 9 bytes
|
||||
(70 75 05 00 01 and 4 bytes CRC) should be created.
|
||||
In this form with 5 data bytes, the field serves as indicator
|
||||
for the UTF-8 encoding of the standard Zip header's name field.
|
||||
3. This field shall not be used whenever the calculated CRC-32 of
|
||||
the entry's standard name field does not match the provided
|
||||
CRC checksum value. A mismatch of the CRC check indicates that
|
||||
the standard name field was changed by some non-"up"-aware
|
||||
utility without synchronizing this UTF-8 name e.f. block.
|
||||
*/
|
||||
case 0x7075:
|
||||
pos += 1;
|
||||
uint nameCRC32 = BitConverter.ToUInt32(extraField, pos);
|
||||
pos += 4;
|
||||
|
||||
CRC crcTest = new CRC();
|
||||
crcTest.SlurpBlock(bFileName, 0, bFileName.Length);
|
||||
uint fCRC = crcTest.Crc32ResultU;
|
||||
|
||||
if (nameCRC32 == fCRC)
|
||||
{
|
||||
int charLen = blockLength - 5;
|
||||
if (centralDir)
|
||||
lf.FileName = Encoding.UTF8.GetString(extraField, pos, charLen);
|
||||
else
|
||||
lf._localHeaderFilename = Encoding.UTF8.GetString(extraField, pos, charLen);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
-Info-ZIP UNIX Extra Field (type 2):
|
||||
==================================
|
||||
|
||||
The following is the layout of the new Info-ZIP extra block for
|
||||
Unix. (Last Revision 19960922)
|
||||
|
||||
Local-header version:
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(Unix2) 0x7855 Short tag for this extra block type ("Ux")
|
||||
TSize Short total data size for this block (4)
|
||||
UID Short Unix user ID
|
||||
GID Short Unix group ID
|
||||
|
||||
Central-header version:
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(Unix2) 0x7855 Short tag for this extra block type ("Ux")
|
||||
TSize Short total data size for this block (0)
|
||||
|
||||
The data size of the central-header version is zero; it is used
|
||||
solely as a flag that UID/GID info is present in the local-header
|
||||
extra field. If additional fields are ever added to the local
|
||||
version, the central version may be extended to indicate this.
|
||||
|
||||
Note that Unix UIDs and GIDs are usually specific to a particular
|
||||
machine, and they generally require root access to restore.
|
||||
|
||||
*/
|
||||
case 0x7855: // Not Needed
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
-Info-ZIP New Unix Extra Field:
|
||||
====================================
|
||||
|
||||
Currently stores Unix UIDs/GIDs up to 32 bits.
|
||||
(Last Revision 20080509)
|
||||
|
||||
Value Size Description
|
||||
----- ---- -----------
|
||||
(UnixN) 0x7875 Short tag for this extra block type ("ux")
|
||||
TSize Short total data size for this block
|
||||
Version 1 byte version of this extra field, currently 1
|
||||
UIDSize 1 byte Size of UID field
|
||||
UID Variable UID for this entry
|
||||
GIDSize 1 byte Size of GID field
|
||||
GID Variable GID for this entry
|
||||
|
||||
Currently Version is set to the number 1. If there is a need
|
||||
to change this field, the version will be incremented. Changes
|
||||
may not be backward compatible so this extra field should not be
|
||||
used if the version is not recognized.
|
||||
|
||||
UIDSize is the size of the UID field in bytes. This size should
|
||||
match the size of the UID field on the target OS.
|
||||
|
||||
UID is the UID for this entry in standard little endian format.
|
||||
|
||||
GIDSize is the size of the GID field in bytes. This size should
|
||||
match the size of the GID field on the target OS.
|
||||
|
||||
GID is the GID for this entry in standard little endian format.
|
||||
|
||||
If both the old 16-bit Unix extra field (tag 0x7855, Info-ZIP Unix2)
|
||||
and this extra field are present, the values in this extra field
|
||||
supercede the values in that extra field.
|
||||
*/
|
||||
case 0x7875: // Not Needed
|
||||
break;
|
||||
|
||||
|
||||
|
||||
/* UNKNOWN */
|
||||
case 0xe57a:
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
blockPos += blockLength;
|
||||
|
||||
}
|
||||
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
91
SabreTools.FileTypes/Compress/ZipFile/ZipFake.cs
Normal file
91
SabreTools.FileTypes/Compress/ZipFile/ZipFake.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System.IO;
|
||||
using Compress.Utils;
|
||||
|
||||
namespace Compress.ZipFile
|
||||
{
|
||||
public partial class Zip
|
||||
{
|
||||
|
||||
public void ZipCreateFake()
|
||||
{
|
||||
if (ZipOpen != ZipOpenType.Closed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ZipOpen = ZipOpenType.OpenFakeWrite;
|
||||
}
|
||||
|
||||
|
||||
public void ZipFileCloseFake(ulong fileOffset, out byte[] centralDir)
|
||||
{
|
||||
centralDir = null;
|
||||
if (ZipOpen != ZipOpenType.OpenFakeWrite)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_zip64 = false;
|
||||
bool lTrrntzip = true;
|
||||
|
||||
_zipFs = new MemoryStream();
|
||||
|
||||
_centralDirStart = fileOffset;
|
||||
|
||||
CrcCalculatorStream crcCs = new CrcCalculatorStream(_zipFs, true);
|
||||
|
||||
foreach (LocalFile t in _localFiles)
|
||||
{
|
||||
t.CenteralDirectoryWrite(crcCs);
|
||||
lTrrntzip &= t.TrrntZip;
|
||||
}
|
||||
|
||||
crcCs.Flush();
|
||||
crcCs.Close();
|
||||
|
||||
_centralDirSize = (ulong)_zipFs.Position;
|
||||
|
||||
_fileComment = lTrrntzip ? ZipUtils.GetBytes("TORRENTZIPPED-" + crcCs.Crc.ToString("X8")) : new byte[0];
|
||||
ZipStatus = lTrrntzip ? ZipStatus.TrrntZip : ZipStatus.None;
|
||||
|
||||
crcCs.Dispose();
|
||||
|
||||
_zip64 = (_centralDirStart >= 0xffffffff) || (_centralDirSize >= 0xffffffff) || (_localFiles.Count >= 0xffff);
|
||||
|
||||
if (_zip64)
|
||||
{
|
||||
_endOfCenterDir64 = fileOffset + (ulong)_zipFs.Position;
|
||||
Zip64EndOfCentralDirWrite();
|
||||
Zip64EndOfCentralDirectoryLocatorWrite();
|
||||
}
|
||||
EndOfCentralDirWrite();
|
||||
|
||||
centralDir = ((MemoryStream)_zipFs).ToArray();
|
||||
_zipFs.Close();
|
||||
_zipFs.Dispose();
|
||||
ZipOpen = ZipOpenType.Closed;
|
||||
}
|
||||
|
||||
|
||||
public ZipReturn ZipFileAddFake(string filename, ulong fileOffset, ulong uncompressedSize, ulong compressedSize, byte[] crc32, out byte[] localHeader)
|
||||
{
|
||||
localHeader = null;
|
||||
|
||||
if (ZipOpen != ZipOpenType.OpenFakeWrite)
|
||||
{
|
||||
return ZipReturn.ZipWritingToInputFile;
|
||||
}
|
||||
|
||||
LocalFile lf = new LocalFile(filename);
|
||||
_localFiles.Add(lf);
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
lf.LocalFileHeaderFake(fileOffset, uncompressedSize, compressedSize, crc32, ms);
|
||||
|
||||
localHeader = ms.ToArray();
|
||||
ms.Close();
|
||||
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
}
|
||||
}
|
||||
741
SabreTools.FileTypes/Compress/ZipFile/ZipLocalFile.cs
Normal file
741
SabreTools.FileTypes/Compress/ZipFile/ZipLocalFile.cs
Normal file
@@ -0,0 +1,741 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Compress.Utils;
|
||||
using Compress.ZipFile.ZLib;
|
||||
|
||||
namespace Compress.ZipFile
|
||||
{
|
||||
internal partial class LocalFile
|
||||
{
|
||||
private const uint LocalFileHeaderSignature = 0x04034b50;
|
||||
private const uint CentralDirectoryHeaderSignature = 0x02014b50;
|
||||
|
||||
private ushort _compressionMethod;
|
||||
|
||||
private long _lastModFileTimeDate;
|
||||
private long? mTime;
|
||||
private long? cTime;
|
||||
private long? aTime;
|
||||
|
||||
private string _localHeaderFilename;
|
||||
private ulong _compressedSize;
|
||||
private ulong _localHeaderCompressedSize;
|
||||
private ulong _localHeaderUncompressedSize;
|
||||
|
||||
public ulong RelativeOffsetOfLocalHeader; // only in centeral directory
|
||||
|
||||
private ulong _crc32Location;
|
||||
private ulong _extraLocation;
|
||||
private ulong _dataLocation;
|
||||
|
||||
public LocalFile()
|
||||
{
|
||||
}
|
||||
|
||||
public LocalFile(string filename, TimeStamps dateTime = null)
|
||||
{
|
||||
Zip64 = false;
|
||||
GeneralPurposeBitFlag = 2; // Maximum Compression Deflating
|
||||
_compressionMethod = 8; // Compression Method Deflate
|
||||
|
||||
if (dateTime?.ModTime == null)
|
||||
{
|
||||
_lastModFileTimeDate = ZipUtils.trrntzipDateTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastModFileTimeDate = (long)dateTime.ModTime;
|
||||
}
|
||||
|
||||
FileName = filename;
|
||||
}
|
||||
|
||||
public string FileName { get; private set; }
|
||||
public ushort GeneralPurposeBitFlag { get; private set; }
|
||||
public byte[] CRC { get; private set; }
|
||||
public ulong UncompressedSize { get; private set; }
|
||||
|
||||
public bool Zip64 { get; private set; }
|
||||
public bool TrrntZip { get; private set; }
|
||||
|
||||
public long DateTime => mTime ?? _lastModFileTimeDate;
|
||||
|
||||
public long? DateTimeCreate => cTime;
|
||||
public long? DateTimeAccess => aTime;
|
||||
|
||||
|
||||
public ulong LocalFilePos
|
||||
{
|
||||
get => RelativeOffsetOfLocalHeader;
|
||||
set => RelativeOffsetOfLocalHeader = value;
|
||||
}
|
||||
|
||||
|
||||
public ZipReturn CenteralDirectoryRead(Stream zipFs)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
uint thisSignature = br.ReadUInt32();
|
||||
if (thisSignature != CentralDirectoryHeaderSignature)
|
||||
{
|
||||
return ZipReturn.ZipCentralDirError;
|
||||
}
|
||||
|
||||
br.ReadUInt16(); // Version Made By
|
||||
|
||||
br.ReadUInt16(); // Version Needed To Extract
|
||||
|
||||
GeneralPurposeBitFlag = br.ReadUInt16();
|
||||
_compressionMethod = br.ReadUInt16();
|
||||
if (_compressionMethod != 8 && _compressionMethod != 0)
|
||||
{
|
||||
if (_compressionMethod != 6 && _compressionMethod != 5 && _compressionMethod != 1)
|
||||
{
|
||||
return ZipReturn.ZipUnsupportedCompression;
|
||||
}
|
||||
return ZipReturn.ZipUnsupportedCompression;
|
||||
}
|
||||
|
||||
ushort lastModFileTime = br.ReadUInt16();
|
||||
ushort lastModFileDate = br.ReadUInt16();
|
||||
_lastModFileTimeDate = ZipUtils.SetDateTime(lastModFileDate, lastModFileTime);
|
||||
|
||||
CRC = ReadCRC(br);
|
||||
|
||||
_compressedSize = br.ReadUInt32();
|
||||
UncompressedSize = br.ReadUInt32();
|
||||
|
||||
ushort fileNameLength = br.ReadUInt16();
|
||||
ushort extraFieldLength = br.ReadUInt16();
|
||||
ushort fileCommentLength = br.ReadUInt16();
|
||||
|
||||
br.ReadUInt16(); // diskNumberStart
|
||||
br.ReadUInt16(); // internalFileAttributes
|
||||
br.ReadUInt32(); // externalFileAttributes
|
||||
|
||||
RelativeOffsetOfLocalHeader = br.ReadUInt32();
|
||||
|
||||
byte[] bFileName = br.ReadBytes(fileNameLength);
|
||||
FileName = (GeneralPurposeBitFlag & (1 << 11)) == 0
|
||||
? ZipUtils.GetString(bFileName)
|
||||
: Encoding.UTF8.GetString(bFileName, 0, fileNameLength);
|
||||
|
||||
if (extraFieldLength > 0)
|
||||
{
|
||||
byte[] extraField = br.ReadBytes(extraFieldLength);
|
||||
|
||||
|
||||
ZipReturn zr = ZipExtraField.ReadLocalExtraField(extraField, bFileName, this, true);
|
||||
if (zr != ZipReturn.ZipGood)
|
||||
return zr;
|
||||
}
|
||||
|
||||
if (ZipUtils.IsCodePage437(FileName) != ((GeneralPurposeBitFlag & (1 << 11)) == 0))
|
||||
TrrntZip = false;
|
||||
|
||||
if (fileCommentLength > 0)
|
||||
{
|
||||
byte[] fileComment = br.ReadBytes(fileCommentLength);
|
||||
}
|
||||
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return ZipReturn.ZipCentralDirError;
|
||||
}
|
||||
}
|
||||
|
||||
public void CenteralDirectoryWrite(Stream crcStream)
|
||||
{
|
||||
using (BinaryWriter bw = new BinaryWriter(crcStream, Encoding.UTF8, true))
|
||||
{
|
||||
const uint header = 0x2014B50;
|
||||
|
||||
List<byte> extraField = new List<byte>();
|
||||
|
||||
uint cdUncompressedSize;
|
||||
if (UncompressedSize >= 0xffffffff)
|
||||
{
|
||||
Zip64 = true;
|
||||
cdUncompressedSize = 0xffffffff;
|
||||
extraField.AddRange(BitConverter.GetBytes(UncompressedSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
cdUncompressedSize = (uint)UncompressedSize;
|
||||
}
|
||||
|
||||
uint cdCompressedSize;
|
||||
if (_compressedSize >= 0xffffffff)
|
||||
{
|
||||
Zip64 = true;
|
||||
cdCompressedSize = 0xffffffff;
|
||||
extraField.AddRange(BitConverter.GetBytes(_compressedSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
cdCompressedSize = (uint)_compressedSize;
|
||||
}
|
||||
|
||||
uint cdRelativeOffsetOfLocalHeader;
|
||||
if (RelativeOffsetOfLocalHeader >= 0xffffffff)
|
||||
{
|
||||
Zip64 = true;
|
||||
cdRelativeOffsetOfLocalHeader = 0xffffffff;
|
||||
extraField.AddRange(BitConverter.GetBytes(RelativeOffsetOfLocalHeader));
|
||||
}
|
||||
else
|
||||
{
|
||||
cdRelativeOffsetOfLocalHeader = (uint)RelativeOffsetOfLocalHeader;
|
||||
}
|
||||
|
||||
|
||||
if (extraField.Count > 0)
|
||||
{
|
||||
ushort exfl = (ushort)extraField.Count;
|
||||
extraField.InsertRange(0, BitConverter.GetBytes((ushort)0x0001));
|
||||
extraField.InsertRange(2, BitConverter.GetBytes(exfl));
|
||||
}
|
||||
|
||||
ushort extraFieldLength = (ushort)extraField.Count;
|
||||
|
||||
byte[] bFileName;
|
||||
if (ZipUtils.IsCodePage437(FileName))
|
||||
{
|
||||
bFileName = ZipUtils.GetBytes(FileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
GeneralPurposeBitFlag |= 1 << 11;
|
||||
bFileName = Encoding.UTF8.GetBytes(FileName);
|
||||
}
|
||||
|
||||
ushort fileNameLength = (ushort)bFileName.Length;
|
||||
|
||||
ushort versionNeededToExtract = (ushort)(Zip64 ? 45 : 20);
|
||||
|
||||
ZipUtils.SetDateTime(_lastModFileTimeDate, out ushort lastModFileDate, out ushort lastModFileTime);
|
||||
|
||||
bw.Write(header);
|
||||
bw.Write((ushort)0);
|
||||
bw.Write(versionNeededToExtract);
|
||||
bw.Write(GeneralPurposeBitFlag);
|
||||
bw.Write(_compressionMethod);
|
||||
bw.Write(lastModFileTime);
|
||||
bw.Write(lastModFileDate);
|
||||
bw.Write(CRC[3]);
|
||||
bw.Write(CRC[2]);
|
||||
bw.Write(CRC[1]);
|
||||
bw.Write(CRC[0]);
|
||||
bw.Write(cdCompressedSize);
|
||||
bw.Write(cdUncompressedSize);
|
||||
bw.Write(fileNameLength);
|
||||
bw.Write(extraFieldLength);
|
||||
bw.Write((ushort)0); // file comment length
|
||||
bw.Write((ushort)0); // disk number start
|
||||
bw.Write((ushort)0); // internal file attributes
|
||||
bw.Write((uint)0); // external file attributes
|
||||
bw.Write(cdRelativeOffsetOfLocalHeader);
|
||||
|
||||
bw.Write(bFileName, 0, fileNameLength);
|
||||
bw.Write(extraField.ToArray(), 0, extraFieldLength);
|
||||
// No File Comment
|
||||
}
|
||||
}
|
||||
public ZipReturn LocalFileHeaderRead(Stream zipFs)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
|
||||
TrrntZip = true;
|
||||
|
||||
zipFs.Position = (long)RelativeOffsetOfLocalHeader;
|
||||
uint thisSignature = br.ReadUInt32();
|
||||
if (thisSignature != LocalFileHeaderSignature)
|
||||
{
|
||||
return ZipReturn.ZipLocalFileHeaderError;
|
||||
}
|
||||
|
||||
br.ReadUInt16(); // version needed to extract
|
||||
ushort generalPurposeBitFlagLocal = br.ReadUInt16();
|
||||
if (generalPurposeBitFlagLocal != GeneralPurposeBitFlag)
|
||||
{
|
||||
TrrntZip = false;
|
||||
}
|
||||
|
||||
ushort tshort = br.ReadUInt16();
|
||||
if (tshort != _compressionMethod)
|
||||
{
|
||||
return ZipReturn.ZipLocalFileHeaderError;
|
||||
}
|
||||
|
||||
ushort lastModFileTime = br.ReadUInt16();
|
||||
ushort lastModFileDate = br.ReadUInt16();
|
||||
|
||||
long tTime = ZipUtils.SetDateTime(lastModFileDate, lastModFileTime);
|
||||
if (tTime != _lastModFileTimeDate)
|
||||
{
|
||||
return ZipReturn.ZipLocalFileHeaderError;
|
||||
}
|
||||
|
||||
byte[] tCRC = ReadCRC(br);
|
||||
_localHeaderCompressedSize = br.ReadUInt32();
|
||||
_localHeaderUncompressedSize = br.ReadUInt32();
|
||||
|
||||
ushort fileNameLength = br.ReadUInt16();
|
||||
ushort extraFieldLength = br.ReadUInt16();
|
||||
|
||||
|
||||
byte[] bFileName = br.ReadBytes(fileNameLength);
|
||||
_localHeaderFilename = (generalPurposeBitFlagLocal & (1 << 11)) == 0
|
||||
? ZipUtils.GetString(bFileName)
|
||||
: Encoding.UTF8.GetString(bFileName, 0, fileNameLength);
|
||||
|
||||
|
||||
Zip64 = false;
|
||||
if (extraFieldLength > 0)
|
||||
{
|
||||
byte[] extraField = br.ReadBytes(extraFieldLength);
|
||||
|
||||
ZipReturn zr = ZipExtraField.ReadLocalExtraField(extraField, bFileName, this, false);
|
||||
if (zr != ZipReturn.ZipGood)
|
||||
return zr;
|
||||
}
|
||||
|
||||
if (!ZipUtils.CompareString(FileName, _localHeaderFilename))
|
||||
{
|
||||
TrrntZip = false;
|
||||
if (!ZipUtils.CompareStringSlash(FileName, _localHeaderFilename))
|
||||
{
|
||||
return ZipReturn.ZipLocalFileHeaderError;
|
||||
}
|
||||
}
|
||||
|
||||
_dataLocation = (ulong)zipFs.Position;
|
||||
|
||||
if ((GeneralPurposeBitFlag & 8) == 8)
|
||||
{
|
||||
zipFs.Position += (long)_compressedSize;
|
||||
|
||||
tCRC = ReadCRC(br);
|
||||
if (!ZipUtils.ByteArrCompare(tCRC, new byte[] { 0x50, 0x4b, 0x07, 0x08 }))
|
||||
{
|
||||
tCRC = ReadCRC(br);
|
||||
}
|
||||
_localHeaderCompressedSize = br.ReadUInt32();
|
||||
_localHeaderUncompressedSize = br.ReadUInt32();
|
||||
}
|
||||
|
||||
if (ZipUtils.IsCodePage437(FileName) != ((GeneralPurposeBitFlag & (1 << 11)) == 0))
|
||||
TrrntZip = false;
|
||||
|
||||
if (!ZipUtils.ByteArrCompare(tCRC, CRC))
|
||||
{
|
||||
return ZipReturn.ZipLocalFileHeaderError;
|
||||
}
|
||||
|
||||
if (_localHeaderCompressedSize != _compressedSize)
|
||||
{
|
||||
return ZipReturn.ZipLocalFileHeaderError;
|
||||
}
|
||||
|
||||
if (_localHeaderUncompressedSize != UncompressedSize)
|
||||
{
|
||||
return ZipReturn.ZipLocalFileHeaderError;
|
||||
}
|
||||
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return ZipReturn.ZipLocalFileHeaderError;
|
||||
}
|
||||
}
|
||||
|
||||
public ZipReturn LocalFileHeaderReadQuick(Stream zipFs)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
TrrntZip = true;
|
||||
|
||||
zipFs.Position = (long)RelativeOffsetOfLocalHeader;
|
||||
uint thisSignature = br.ReadUInt32();
|
||||
if (thisSignature != LocalFileHeaderSignature)
|
||||
{
|
||||
return ZipReturn.ZipLocalFileHeaderError;
|
||||
}
|
||||
|
||||
br.ReadUInt16(); // version needed to extract
|
||||
GeneralPurposeBitFlag = br.ReadUInt16();
|
||||
if ((GeneralPurposeBitFlag & 8) == 8)
|
||||
{
|
||||
return ZipReturn.ZipCannotFastOpen;
|
||||
}
|
||||
|
||||
_compressionMethod = br.ReadUInt16();
|
||||
|
||||
ushort lastModFileTime = br.ReadUInt16();
|
||||
ushort lastModFileDate = br.ReadUInt16();
|
||||
_lastModFileTimeDate = ZipUtils.SetDateTime(lastModFileDate, lastModFileTime);
|
||||
|
||||
CRC = ReadCRC(br);
|
||||
_localHeaderCompressedSize = br.ReadUInt32();
|
||||
_localHeaderUncompressedSize = br.ReadUInt32();
|
||||
|
||||
ushort fileNameLength = br.ReadUInt16();
|
||||
ushort extraFieldLength = br.ReadUInt16();
|
||||
|
||||
byte[] bFileName = br.ReadBytes(fileNameLength);
|
||||
|
||||
_localHeaderFilename = (GeneralPurposeBitFlag & (1 << 11)) == 0
|
||||
? ZipUtils.GetString(bFileName)
|
||||
: Encoding.UTF8.GetString(bFileName, 0, fileNameLength);
|
||||
|
||||
Zip64 = false;
|
||||
if (extraFieldLength > 0)
|
||||
{
|
||||
byte[] extraField = br.ReadBytes(extraFieldLength);
|
||||
|
||||
ZipReturn zr = ZipExtraField.ReadLocalExtraField(extraField, bFileName, this, false);
|
||||
if (zr != ZipReturn.ZipGood)
|
||||
return zr;
|
||||
}
|
||||
|
||||
|
||||
_dataLocation = (ulong)zipFs.Position;
|
||||
|
||||
FileName = _localHeaderFilename;
|
||||
_compressedSize = _localHeaderCompressedSize;
|
||||
UncompressedSize = _localHeaderUncompressedSize;
|
||||
|
||||
if (ZipUtils.IsCodePage437(FileName) != ((GeneralPurposeBitFlag & (1 << 11)) == 0))
|
||||
TrrntZip = false;
|
||||
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return ZipReturn.ZipLocalFileHeaderError;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void LocalFileHeaderWrite(Stream zipFs)
|
||||
{
|
||||
using (BinaryWriter bw = new BinaryWriter(zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
Zip64 = UncompressedSize >= 0xffffffff;
|
||||
|
||||
byte[] bFileName;
|
||||
if (ZipUtils.IsCodePage437(FileName))
|
||||
{
|
||||
bFileName = ZipUtils.GetBytes(FileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
GeneralPurposeBitFlag |= 1 << 11;
|
||||
bFileName = Encoding.UTF8.GetBytes(FileName);
|
||||
}
|
||||
|
||||
ushort versionNeededToExtract = (ushort)(Zip64 ? 45 : 20);
|
||||
|
||||
RelativeOffsetOfLocalHeader = (ulong)zipFs.Position;
|
||||
const uint header = 0x4034B50;
|
||||
bw.Write(header);
|
||||
bw.Write(versionNeededToExtract);
|
||||
bw.Write(GeneralPurposeBitFlag);
|
||||
bw.Write(_compressionMethod);
|
||||
|
||||
ZipUtils.SetDateTime(_lastModFileTimeDate, out ushort lastModFileDate, out ushort lastModFileTime);
|
||||
bw.Write(lastModFileTime);
|
||||
bw.Write(lastModFileDate);
|
||||
|
||||
_crc32Location = (ulong)zipFs.Position;
|
||||
|
||||
// these 3 values will be set correctly after the file data has been written
|
||||
bw.Write(0xffffffff);
|
||||
bw.Write(0xffffffff);
|
||||
bw.Write(0xffffffff);
|
||||
|
||||
ushort fileNameLength = (ushort)bFileName.Length;
|
||||
bw.Write(fileNameLength);
|
||||
|
||||
ushort extraFieldLength = (ushort)(Zip64 ? 20 : 0);
|
||||
bw.Write(extraFieldLength);
|
||||
|
||||
bw.Write(bFileName, 0, fileNameLength);
|
||||
|
||||
_extraLocation = (ulong)zipFs.Position;
|
||||
if (Zip64)
|
||||
bw.Write(new byte[20], 0, extraFieldLength);
|
||||
}
|
||||
}
|
||||
|
||||
public void LocalFileHeaderFake(ulong filePosition, ulong uncompressedSize, ulong compressedSize, byte[] crc32, MemoryStream ms)
|
||||
{
|
||||
using (BinaryWriter bw = new BinaryWriter(ms, Encoding.UTF8, true))
|
||||
{
|
||||
RelativeOffsetOfLocalHeader = filePosition;
|
||||
TrrntZip = true;
|
||||
UncompressedSize = uncompressedSize;
|
||||
_compressedSize = compressedSize;
|
||||
CRC = crc32;
|
||||
|
||||
Zip64 = UncompressedSize >= 0xffffffff || _compressedSize >= 0xffffffff;
|
||||
|
||||
byte[] bFileName;
|
||||
if (ZipUtils.IsCodePage437(FileName))
|
||||
{
|
||||
bFileName = ZipUtils.GetBytes(FileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
GeneralPurposeBitFlag |= 1 << 11;
|
||||
bFileName = Encoding.UTF8.GetBytes(FileName);
|
||||
}
|
||||
|
||||
ushort versionNeededToExtract = (ushort)(Zip64 ? 45 : 20);
|
||||
|
||||
const uint header = 0x4034B50;
|
||||
bw.Write(header);
|
||||
bw.Write(versionNeededToExtract);
|
||||
bw.Write(GeneralPurposeBitFlag);
|
||||
bw.Write(_compressionMethod);
|
||||
|
||||
ZipUtils.SetDateTime(_lastModFileTimeDate, out ushort lastModFileDate, out ushort lastModFileTime);
|
||||
bw.Write(lastModFileTime);
|
||||
bw.Write(lastModFileDate);
|
||||
|
||||
uint tCompressedSize;
|
||||
uint tUncompressedSize;
|
||||
if (Zip64)
|
||||
{
|
||||
tCompressedSize = 0xffffffff;
|
||||
tUncompressedSize = 0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
tCompressedSize = (uint)_compressedSize;
|
||||
tUncompressedSize = (uint)UncompressedSize;
|
||||
}
|
||||
|
||||
bw.Write(CRC[3]);
|
||||
bw.Write(CRC[2]);
|
||||
bw.Write(CRC[1]);
|
||||
bw.Write(CRC[0]);
|
||||
bw.Write(tCompressedSize);
|
||||
bw.Write(tUncompressedSize);
|
||||
|
||||
ushort fileNameLength = (ushort)bFileName.Length;
|
||||
bw.Write(fileNameLength);
|
||||
|
||||
ushort extraFieldLength = (ushort)(Zip64 ? 20 : 0);
|
||||
bw.Write(extraFieldLength);
|
||||
|
||||
bw.Write(bFileName, 0, fileNameLength);
|
||||
|
||||
if (Zip64)
|
||||
{
|
||||
bw.Write((ushort)0x0001); // id
|
||||
bw.Write((ushort)16); // data length
|
||||
bw.Write(UncompressedSize);
|
||||
bw.Write(_compressedSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
public ZipReturn LocalFileOpenReadStream(Stream zipFs, bool raw, out Stream readStream, out ulong streamSize, out ushort compressionMethod)
|
||||
{
|
||||
streamSize = 0;
|
||||
compressionMethod = _compressionMethod;
|
||||
|
||||
readStream = null;
|
||||
zipFs.Seek((long)_dataLocation, SeekOrigin.Begin);
|
||||
|
||||
switch (_compressionMethod)
|
||||
{
|
||||
case 8:
|
||||
if (raw)
|
||||
{
|
||||
readStream = zipFs;
|
||||
streamSize = _compressedSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
readStream=new System.IO.Compression.DeflateStream(zipFs,System.IO.Compression.CompressionMode.Decompress,true);
|
||||
//readStream = new ZlibBaseStream(zipFs, CompressionMode.Decompress, CompressionLevel.Default, ZlibStreamFlavor.DEFLATE, true);
|
||||
streamSize = UncompressedSize;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
readStream = zipFs;
|
||||
streamSize = _compressedSize; // same as UncompressedSize
|
||||
break;
|
||||
}
|
||||
|
||||
return readStream == null ? ZipReturn.ZipErrorGettingDataStream : ZipReturn.ZipGood;
|
||||
}
|
||||
|
||||
public ZipReturn LocalFileOpenWriteStream(Stream zipFs, bool raw, bool trrntZip, ulong uncompressedSize, ushort compressionMethod, out Stream writeStream)
|
||||
{
|
||||
UncompressedSize = uncompressedSize;
|
||||
_compressionMethod = compressionMethod;
|
||||
|
||||
LocalFileHeaderWrite(zipFs);
|
||||
_dataLocation = (ulong)zipFs.Position;
|
||||
|
||||
if (raw)
|
||||
{
|
||||
writeStream = zipFs;
|
||||
TrrntZip = trrntZip;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (compressionMethod == 0)
|
||||
{
|
||||
writeStream = zipFs;
|
||||
TrrntZip = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
writeStream = new ZlibBaseStream(zipFs, CompressionMode.Compress, CompressionLevel.BestCompression, ZlibStreamFlavor.DEFLATE, true);
|
||||
TrrntZip = true;
|
||||
}
|
||||
}
|
||||
|
||||
return writeStream == null ? ZipReturn.ZipErrorGettingDataStream : ZipReturn.ZipGood;
|
||||
}
|
||||
|
||||
public ZipReturn LocalFileCloseWriteStream(Stream zipFs, byte[] crc32)
|
||||
{
|
||||
|
||||
_compressedSize = (ulong)zipFs.Position - _dataLocation;
|
||||
|
||||
if (_compressedSize == 0 && UncompressedSize == 0)
|
||||
{
|
||||
LocalFileAddZeroLengthFile(zipFs);
|
||||
_compressedSize = (ulong)zipFs.Position - _dataLocation;
|
||||
}
|
||||
else if (_compressedSize == 0 && UncompressedSize != 0)
|
||||
{
|
||||
return ZipReturn.ZipErrorWritingToOutputStream;
|
||||
}
|
||||
|
||||
CRC = crc32;
|
||||
WriteCompressedSize(zipFs);
|
||||
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
|
||||
private void FixFileForZip64(Stream zipFs)
|
||||
{
|
||||
long posNow = zipFs.Position;
|
||||
using (BinaryWriter bw = new BinaryWriter(zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
// _crc32Location - 10 needs set to 45
|
||||
zipFs.Seek((long)_crc32Location - 10, SeekOrigin.Begin);
|
||||
ushort versionNeededToExtract = 45;
|
||||
bw.Write(versionNeededToExtract);
|
||||
|
||||
zipFs.Seek((long)_crc32Location + 14, SeekOrigin.Begin);
|
||||
ushort extraFieldLength = 20;
|
||||
bw.Write(extraFieldLength);
|
||||
}
|
||||
ExpandFile(zipFs, (long)_extraLocation, posNow, 20);
|
||||
zipFs.Position = posNow + 20;
|
||||
}
|
||||
|
||||
private static void ExpandFile(Stream stream, long offset, long length, int extraBytes)
|
||||
{
|
||||
const int bufferSize = 40960;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
// Expand file
|
||||
long pos = length;
|
||||
while (pos > offset)
|
||||
{
|
||||
int toRead = pos - bufferSize >= offset ? bufferSize : (int)(pos - offset);
|
||||
pos -= toRead;
|
||||
stream.Position = pos;
|
||||
stream.Read(buffer, 0, toRead);
|
||||
stream.Position = pos + extraBytes;
|
||||
stream.Write(buffer, 0, toRead);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteCompressedSize(Stream zipFs)
|
||||
{
|
||||
if (_compressedSize >= 0xffffffff && !Zip64)
|
||||
{
|
||||
Zip64 = true;
|
||||
FixFileForZip64(zipFs);
|
||||
}
|
||||
|
||||
|
||||
long posNow = zipFs.Position;
|
||||
zipFs.Seek((long)_crc32Location, SeekOrigin.Begin);
|
||||
using (BinaryWriter bw = new BinaryWriter(zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
uint tCompressedSize;
|
||||
uint tUncompressedSize;
|
||||
if (Zip64)
|
||||
{
|
||||
tCompressedSize = 0xffffffff;
|
||||
tUncompressedSize = 0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
tCompressedSize = (uint)_compressedSize;
|
||||
tUncompressedSize = (uint)UncompressedSize;
|
||||
}
|
||||
|
||||
bw.Write(CRC[3]);
|
||||
bw.Write(CRC[2]);
|
||||
bw.Write(CRC[1]);
|
||||
bw.Write(CRC[0]);
|
||||
bw.Write(tCompressedSize);
|
||||
bw.Write(tUncompressedSize);
|
||||
|
||||
|
||||
// also need to write extradata
|
||||
if (Zip64)
|
||||
{
|
||||
zipFs.Seek((long)_extraLocation, SeekOrigin.Begin);
|
||||
bw.Write((ushort)0x0001); // id
|
||||
bw.Write((ushort)16); // data length
|
||||
bw.Write(UncompressedSize);
|
||||
bw.Write(_compressedSize);
|
||||
}
|
||||
}
|
||||
|
||||
zipFs.Seek(posNow, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
public static void LocalFileAddZeroLengthFile(Stream zipFs)
|
||||
{
|
||||
zipFs.WriteByte(03);
|
||||
zipFs.WriteByte(00);
|
||||
}
|
||||
|
||||
private static byte[] ReadCRC(BinaryReader br)
|
||||
{
|
||||
byte[] tCRC = new byte[4];
|
||||
tCRC[3] = br.ReadByte();
|
||||
tCRC[2] = br.ReadByte();
|
||||
tCRC[1] = br.ReadByte();
|
||||
tCRC[0] = br.ReadByte();
|
||||
return tCRC;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
251
SabreTools.FileTypes/Compress/ZipFile/ZipRead.cs
Normal file
251
SabreTools.FileTypes/Compress/ZipFile/ZipRead.cs
Normal file
@@ -0,0 +1,251 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Compress.Utils;
|
||||
using FileInfo = RVIO.FileInfo;
|
||||
using FileStream = RVIO.FileStream;
|
||||
|
||||
namespace Compress.ZipFile
|
||||
{
|
||||
public partial class Zip
|
||||
{
|
||||
|
||||
public ZipReturn ZipFileOpen(string newFilename, long timestamp, bool readHeaders)
|
||||
{
|
||||
ZipFileClose();
|
||||
ZipStatus = ZipStatus.None;
|
||||
_zip64 = false;
|
||||
_centralDirStart = 0;
|
||||
_centralDirSize = 0;
|
||||
_zipFileInfo = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (!RVIO.File.Exists(newFilename))
|
||||
{
|
||||
ZipFileClose();
|
||||
return ZipReturn.ZipErrorFileNotFound;
|
||||
}
|
||||
_zipFileInfo = new FileInfo(newFilename);
|
||||
if (timestamp != -1 && _zipFileInfo.LastWriteTime != timestamp)
|
||||
{
|
||||
ZipFileClose();
|
||||
return ZipReturn.ZipErrorTimeStamp;
|
||||
}
|
||||
int errorCode = FileStream.OpenFileRead(newFilename, out _zipFs);
|
||||
if (errorCode != 0)
|
||||
{
|
||||
ZipFileClose();
|
||||
if (errorCode == 32)
|
||||
{
|
||||
return ZipReturn.ZipFileLocked;
|
||||
}
|
||||
return ZipReturn.ZipErrorOpeningFile;
|
||||
}
|
||||
}
|
||||
catch (PathTooLongException)
|
||||
{
|
||||
ZipFileClose();
|
||||
return ZipReturn.ZipFileNameToLong;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
ZipFileClose();
|
||||
return ZipReturn.ZipErrorOpeningFile;
|
||||
}
|
||||
ZipOpen = ZipOpenType.OpenRead;
|
||||
|
||||
if (!readHeaders)
|
||||
{
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
|
||||
|
||||
return ZipFileReadHeaders();
|
||||
}
|
||||
|
||||
|
||||
public ZipReturn ZipFileOpen(Stream inStream)
|
||||
{
|
||||
ZipFileClose();
|
||||
ZipStatus = ZipStatus.None;
|
||||
_zip64 = false;
|
||||
_centralDirStart = 0;
|
||||
_centralDirSize = 0;
|
||||
_zipFileInfo = null;
|
||||
_zipFs = inStream;
|
||||
|
||||
ZipOpen = ZipOpenType.OpenRead;
|
||||
return ZipFileReadHeaders();
|
||||
}
|
||||
|
||||
|
||||
private void zipFileCloseRead()
|
||||
{
|
||||
if (_zipFs != null)
|
||||
{
|
||||
_zipFs.Close();
|
||||
_zipFs.Dispose();
|
||||
}
|
||||
ZipOpen = ZipOpenType.Closed;
|
||||
}
|
||||
|
||||
|
||||
private ZipReturn ZipFileReadHeaders()
|
||||
{
|
||||
try
|
||||
{
|
||||
ZipReturn zRet = FindEndOfCentralDirSignature();
|
||||
if (zRet != ZipReturn.ZipGood)
|
||||
{
|
||||
ZipFileClose();
|
||||
return zRet;
|
||||
}
|
||||
|
||||
ulong endOfCentralDir = (ulong)_zipFs.Position;
|
||||
zRet = EndOfCentralDirRead();
|
||||
if (zRet != ZipReturn.ZipGood)
|
||||
{
|
||||
ZipFileClose();
|
||||
return zRet;
|
||||
}
|
||||
|
||||
|
||||
// check if ZIP64 header is required
|
||||
bool zip64Required = (_centralDirStart == 0xffffffff || _centralDirSize == 0xffffffff || _localFilesCount == 0xffff);
|
||||
|
||||
// check for a ZIP64 header
|
||||
_zipFs.Position = (long)endOfCentralDir - 20;
|
||||
zRet = Zip64EndOfCentralDirectoryLocatorRead();
|
||||
if (zRet == ZipReturn.ZipGood)
|
||||
{
|
||||
_zipFs.Position = (long)_endOfCenterDir64;
|
||||
zRet = Zip64EndOfCentralDirRead();
|
||||
if (zRet == ZipReturn.ZipGood)
|
||||
{
|
||||
_zip64 = true;
|
||||
endOfCentralDir = _endOfCenterDir64;
|
||||
}
|
||||
}
|
||||
|
||||
if (zip64Required && !_zip64)
|
||||
{
|
||||
return ZipReturn.Zip64EndOfCentralDirError;
|
||||
}
|
||||
|
||||
bool trrntzip = false;
|
||||
|
||||
// check if the ZIP has a valid TorrentZip file comment
|
||||
if (_fileComment.Length == 22)
|
||||
{
|
||||
if (ZipUtils.GetString(_fileComment).Substring(0, 14) == "TORRENTZIPPED-")
|
||||
{
|
||||
CrcCalculatorStream crcCs = new CrcCalculatorStream(_zipFs, true);
|
||||
byte[] buffer = new byte[_centralDirSize];
|
||||
_zipFs.Position = (long)_centralDirStart;
|
||||
crcCs.Read(buffer, 0, (int)_centralDirSize);
|
||||
crcCs.Flush();
|
||||
crcCs.Close();
|
||||
|
||||
uint r = (uint)crcCs.Crc;
|
||||
crcCs.Dispose();
|
||||
|
||||
string tcrc = ZipUtils.GetString(_fileComment).Substring(14, 8);
|
||||
string zcrc = r.ToString("X8");
|
||||
if (string.Compare(tcrc, zcrc, StringComparison.Ordinal) == 0)
|
||||
{
|
||||
trrntzip = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (zip64Required != _zip64)
|
||||
trrntzip = false;
|
||||
|
||||
// now read the central directory
|
||||
_zipFs.Position = (long)_centralDirStart;
|
||||
|
||||
_localFiles.Clear();
|
||||
_localFiles.Capacity = (int)_localFilesCount;
|
||||
for (int i = 0; i < _localFilesCount; i++)
|
||||
{
|
||||
LocalFile lc = new LocalFile();
|
||||
zRet = lc.CenteralDirectoryRead(_zipFs);
|
||||
if (zRet != ZipReturn.ZipGood)
|
||||
{
|
||||
ZipFileClose();
|
||||
return zRet;
|
||||
}
|
||||
_zip64 |= lc.Zip64;
|
||||
_localFiles.Add(lc);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _localFilesCount; i++)
|
||||
{
|
||||
zRet = _localFiles[i].LocalFileHeaderRead(_zipFs);
|
||||
if (zRet != ZipReturn.ZipGood)
|
||||
{
|
||||
ZipFileClose();
|
||||
return zRet;
|
||||
}
|
||||
trrntzip &= _localFiles[i].TrrntZip;
|
||||
}
|
||||
|
||||
// check trrntzip file order
|
||||
if (trrntzip)
|
||||
{
|
||||
for (int i = 0; i < _localFilesCount - 1; i++)
|
||||
{
|
||||
if (ZipUtils.TrrntZipStringCompare(_localFiles[i].FileName, _localFiles[i + 1].FileName) < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
trrntzip = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check trrntzip directories
|
||||
if (trrntzip)
|
||||
{
|
||||
for (int i = 0; i < _localFilesCount - 1; i++)
|
||||
{
|
||||
// see if we found a directory
|
||||
string filename0 = _localFiles[i].FileName;
|
||||
if (filename0.Substring(filename0.Length - 1, 1) != "/")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// see if the next file is in that directory
|
||||
string filename1 = _localFiles[i + 1].FileName;
|
||||
if (filename1.Length <= filename0.Length)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (ZipUtils.TrrntZipStringCompare(filename0, filename1.Substring(0, filename0.Length)) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we found a file in the directory then we do not need the directory entry
|
||||
trrntzip = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (trrntzip)
|
||||
{
|
||||
ZipStatus |= ZipStatus.TrrntZip;
|
||||
}
|
||||
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
catch
|
||||
{
|
||||
ZipFileClose();
|
||||
return ZipReturn.ZipErrorReadingFile;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
80
SabreTools.FileTypes/Compress/ZipFile/ZipReadStream.cs
Normal file
80
SabreTools.FileTypes/Compress/ZipFile/ZipReadStream.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System.IO;
|
||||
using Compress.ZipFile.ZLib;
|
||||
|
||||
namespace Compress.ZipFile
|
||||
{
|
||||
public partial class Zip
|
||||
{
|
||||
public ZipReturn ZipFileOpenReadStream(int index, out Stream stream, out ulong streamSize)
|
||||
{
|
||||
return ZipFileOpenReadStream(index, false, out stream, out streamSize, out ushort _);
|
||||
}
|
||||
|
||||
public ZipReturn ZipFileOpenReadStream(int index, bool raw, out Stream stream, out ulong streamSize, out ushort compressionMethod)
|
||||
{
|
||||
ZipFileCloseReadStream();
|
||||
|
||||
streamSize = 0;
|
||||
compressionMethod = 0;
|
||||
stream = null;
|
||||
if (ZipOpen != ZipOpenType.OpenRead)
|
||||
{
|
||||
return ZipReturn.ZipReadingFromOutputFile;
|
||||
}
|
||||
|
||||
ZipReturn zRet = _localFiles[index].LocalFileHeaderRead(_zipFs);
|
||||
if (zRet != ZipReturn.ZipGood)
|
||||
{
|
||||
ZipFileClose();
|
||||
return zRet;
|
||||
}
|
||||
|
||||
zRet = _localFiles[index].LocalFileOpenReadStream(_zipFs, raw, out stream, out streamSize, out compressionMethod);
|
||||
_compressionStream = stream;
|
||||
return zRet;
|
||||
}
|
||||
|
||||
public ZipReturn ZipFileOpenReadStreamQuick(ulong pos, bool raw, out Stream stream, out ulong streamSize, out ushort compressionMethod)
|
||||
{
|
||||
ZipFileCloseReadStream();
|
||||
|
||||
LocalFile tmpFile = new LocalFile { LocalFilePos = pos };
|
||||
_localFiles.Clear();
|
||||
_localFiles.Add(tmpFile);
|
||||
ZipReturn zRet = tmpFile.LocalFileHeaderReadQuick(_zipFs);
|
||||
if (zRet != ZipReturn.ZipGood)
|
||||
{
|
||||
stream = null;
|
||||
streamSize = 0;
|
||||
compressionMethod = 0;
|
||||
return zRet;
|
||||
}
|
||||
|
||||
zRet = tmpFile.LocalFileOpenReadStream(_zipFs, raw, out stream, out streamSize, out compressionMethod);
|
||||
_compressionStream = stream;
|
||||
return zRet;
|
||||
}
|
||||
|
||||
|
||||
public ZipReturn ZipFileCloseReadStream()
|
||||
{
|
||||
if (_compressionStream == null)
|
||||
return ZipReturn.ZipGood;
|
||||
if (_compressionStream is ZlibBaseStream dfStream)
|
||||
{
|
||||
dfStream.Close();
|
||||
dfStream.Dispose();
|
||||
}
|
||||
else if (_compressionStream is System.IO.Compression.DeflateStream dfIOStream)
|
||||
{
|
||||
dfIOStream.Close();
|
||||
dfIOStream.Dispose();
|
||||
}
|
||||
_compressionStream = null;
|
||||
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
242
SabreTools.FileTypes/Compress/ZipFile/ZipUtils.cs
Normal file
242
SabreTools.FileTypes/Compress/ZipFile/ZipUtils.cs
Normal file
@@ -0,0 +1,242 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Compress.ZipFile
|
||||
{
|
||||
public static class ZipUtils
|
||||
{
|
||||
// according to the zip documents, zip filesname are stored as MS-DOS Code Page 437.
|
||||
// (Unless the uncode flag is set, in which case they are stored as UTF-8.
|
||||
private static Encoding enc = Encoding.GetEncoding(437);
|
||||
|
||||
public static string GetString(byte[] byteArr)
|
||||
{
|
||||
return enc.GetString(byteArr);
|
||||
}
|
||||
|
||||
// to test if a filename can be stored as codepage 437 we take the filename string
|
||||
// convert it to bytes using the 437 code page, and then convert it back to a string
|
||||
// and we see if we lost characters as a result of the conversion there and back.
|
||||
internal static bool IsCodePage437(string s)
|
||||
{
|
||||
byte[] bOut = enc.GetBytes(s);
|
||||
string sOut = enc.GetString(bOut);
|
||||
|
||||
return CompareString(s, sOut);
|
||||
}
|
||||
|
||||
internal static byte[] GetBytes(string s)
|
||||
{
|
||||
return enc.GetBytes(s);
|
||||
}
|
||||
|
||||
internal static bool CompareString(string s1, string s2)
|
||||
{
|
||||
char[] c1 = s1.ToCharArray();
|
||||
char[] c2 = s2.ToCharArray();
|
||||
|
||||
if (c1.Length != c2.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < c1.Length; i++)
|
||||
{
|
||||
if (c1[i] != c2[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static bool CompareStringSlash(string s1, string s2)
|
||||
{
|
||||
char[] c1 = s1.ToCharArray();
|
||||
char[] c2 = s2.ToCharArray();
|
||||
|
||||
if (c1.Length != c2.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < c1.Length; i++)
|
||||
{
|
||||
if (c1[i] == '/') c1[i] = '\\';
|
||||
if (c2[i] == '/') c2[i] = '\\';
|
||||
if (c1[i] != c2[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
internal static bool ByteArrCompare(byte[] b0, byte[] b1)
|
||||
{
|
||||
if ((b0 == null) || (b1 == null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (b0.Length != b1.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < b0.Length; i++)
|
||||
{
|
||||
if (b0[i] != b1[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
internal static int TrrntZipStringCompare(string string1, string string2)
|
||||
{
|
||||
char[] bytes1 = string1.ToCharArray();
|
||||
char[] bytes2 = string2.ToCharArray();
|
||||
|
||||
int pos1 = 0;
|
||||
int pos2 = 0;
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
if (pos1 == bytes1.Length)
|
||||
{
|
||||
return pos2 == bytes2.Length ? 0 : -1;
|
||||
}
|
||||
if (pos2 == bytes2.Length)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int byte1 = bytes1[pos1++];
|
||||
int byte2 = bytes2[pos2++];
|
||||
|
||||
if (byte1 >= 65 && byte1 <= 90)
|
||||
{
|
||||
byte1 += 0x20;
|
||||
}
|
||||
if (byte2 >= 65 && byte2 <= 90)
|
||||
{
|
||||
byte2 += 0x20;
|
||||
}
|
||||
|
||||
if (byte1 < byte2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (byte1 > byte2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string ZipErrorMessageText(ZipReturn zS)
|
||||
{
|
||||
string ret = "Unknown";
|
||||
switch (zS)
|
||||
{
|
||||
case ZipReturn.ZipGood:
|
||||
ret = "";
|
||||
break;
|
||||
case ZipReturn.ZipFileCountError:
|
||||
ret = "The number of file in the Zip does not mach the number of files in the Zips Centeral Directory";
|
||||
break;
|
||||
case ZipReturn.ZipSignatureError:
|
||||
ret = "An unknown Signature Block was found in the Zip";
|
||||
break;
|
||||
case ZipReturn.ZipExtraDataOnEndOfZip:
|
||||
ret = "Extra Data was found on the end of the Zip";
|
||||
break;
|
||||
case ZipReturn.ZipUnsupportedCompression:
|
||||
ret = "An unsupported Compression method was found in the Zip, if you recompress this zip it will be usable";
|
||||
break;
|
||||
case ZipReturn.ZipLocalFileHeaderError:
|
||||
ret = "Error reading a zipped file header information";
|
||||
break;
|
||||
case ZipReturn.ZipCentralDirError:
|
||||
ret = "There is an error in the Zip Centeral Directory";
|
||||
break;
|
||||
case ZipReturn.ZipReadingFromOutputFile:
|
||||
ret = "Trying to write to a Zip file open for output only";
|
||||
break;
|
||||
case ZipReturn.ZipWritingToInputFile:
|
||||
ret = "Tring to read from a Zip file open for input only";
|
||||
break;
|
||||
case ZipReturn.ZipErrorGettingDataStream:
|
||||
ret = "Error creating Data Stream";
|
||||
break;
|
||||
case ZipReturn.ZipCRCDecodeError:
|
||||
ret = "CRC error";
|
||||
break;
|
||||
case ZipReturn.ZipDecodeError:
|
||||
ret = "Error unzipping a file";
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
public const long fileTimeToUTCTime = 504911232000000000;
|
||||
public const long epochTimeToUTCTime = 621355968000000000;
|
||||
public const long trrntzipDateTime = 629870671200000000;
|
||||
|
||||
private const long TicksPerMillisecond = 10000;
|
||||
private const long TicksPerSecond = TicksPerMillisecond * 1000;
|
||||
|
||||
public static void SetDateTime(long ticks, out ushort DosFileDate, out ushort DosFileTime)
|
||||
{
|
||||
DateTime DateTime = new DateTime(ticks, DateTimeKind.Unspecified);
|
||||
DosFileDate = (ushort)((DateTime.Day & 0x1f) | ((DateTime.Month & 0x0f) << 5) | (((DateTime.Year - 1980) & 0x7f) << 9));
|
||||
DosFileTime = (ushort)(((DateTime.Second >> 1) & 0x1f) | ((DateTime.Minute & 0x3f) << 5) | ((DateTime.Hour & 0x1f) << 11));
|
||||
}
|
||||
|
||||
public static long SetDateTime(ushort DosFileDate, ushort DosFileTime)
|
||||
{
|
||||
if (DosFileDate == 0)
|
||||
return 0;
|
||||
|
||||
int second = (DosFileTime & 0x1f) << 1;
|
||||
int minute = (DosFileTime >> 5) & 0x3f;
|
||||
int hour = (DosFileTime >> 11) & 0x1f;
|
||||
|
||||
int day = DosFileDate & 0x1f;
|
||||
int month = (DosFileDate >> 5) & 0x0f;
|
||||
int year = ((DosFileDate >> 9) & 0x7f) + 1980;
|
||||
|
||||
// valid hours 0 to 23
|
||||
// valid minutes 0 to 59
|
||||
// valid seconds 0 to 59
|
||||
// valid month 1 to 12
|
||||
// valid day 1 to 31
|
||||
|
||||
if (hour > 23 || minute > 59 || second > 59 || month < 1 || month > 12 || day < 1 || day > 31)
|
||||
return 0;
|
||||
|
||||
try
|
||||
{
|
||||
return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Unspecified).Ticks;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static long FileTimeToUTCTime(long ticks)
|
||||
{
|
||||
return ticks + fileTimeToUTCTime;
|
||||
}
|
||||
|
||||
public static long SetDateTimeFromUnixSeconds(int seconds)
|
||||
{
|
||||
return seconds * TicksPerSecond + epochTimeToUTCTime;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
109
SabreTools.FileTypes/Compress/ZipFile/ZipWrite.cs
Normal file
109
SabreTools.FileTypes/Compress/ZipFile/ZipWrite.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using Compress.Utils;
|
||||
using FileInfo = RVIO.FileInfo;
|
||||
using FileStream = RVIO.FileStream;
|
||||
|
||||
// UInt16 = ushort
|
||||
// UInt32 = uint
|
||||
// ULong = ulong
|
||||
|
||||
namespace Compress.ZipFile
|
||||
{
|
||||
public partial class Zip
|
||||
{
|
||||
private ulong _centralDirStart;
|
||||
private ulong _centralDirSize;
|
||||
private ulong _endOfCenterDir64;
|
||||
|
||||
public ZipReturn ZipFileCreate(string newFilename)
|
||||
{
|
||||
if (ZipOpen != ZipOpenType.Closed)
|
||||
{
|
||||
return ZipReturn.ZipFileAlreadyOpen;
|
||||
}
|
||||
|
||||
DirUtil.CreateDirForFile(newFilename);
|
||||
_zipFileInfo = new FileInfo(newFilename);
|
||||
|
||||
int errorCode = FileStream.OpenFileWrite(newFilename, out _zipFs);
|
||||
if (errorCode != 0)
|
||||
{
|
||||
ZipFileClose();
|
||||
return ZipReturn.ZipErrorOpeningFile;
|
||||
}
|
||||
ZipOpen = ZipOpenType.OpenWrite;
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
|
||||
private void zipFileCloseWrite()
|
||||
{
|
||||
bool lTrrntzip = true;
|
||||
|
||||
_centralDirStart = (ulong)_zipFs.Position;
|
||||
|
||||
using (CrcCalculatorStream crcCs = new CrcCalculatorStream(_zipFs, true))
|
||||
{
|
||||
foreach (LocalFile t in _localFiles)
|
||||
{
|
||||
t.CenteralDirectoryWrite(crcCs);
|
||||
lTrrntzip &= t.TrrntZip;
|
||||
}
|
||||
|
||||
crcCs.Flush();
|
||||
crcCs.Close();
|
||||
|
||||
_centralDirSize = (ulong)_zipFs.Position - _centralDirStart;
|
||||
|
||||
_fileComment = lTrrntzip ? ZipUtils.GetBytes("TORRENTZIPPED-" + crcCs.Crc.ToString("X8")) : new byte[0];
|
||||
ZipStatus = lTrrntzip ? ZipStatus.TrrntZip : ZipStatus.None;
|
||||
}
|
||||
|
||||
_zip64 = false;
|
||||
_zip64 |= _centralDirStart >= 0xffffffff;
|
||||
_zip64 |= _centralDirSize >= 0xffffffff;
|
||||
_zip64 |= _localFiles.Count >= 0xffff;
|
||||
|
||||
if (_zip64)
|
||||
{
|
||||
_endOfCenterDir64 = (ulong)_zipFs.Position;
|
||||
Zip64EndOfCentralDirWrite();
|
||||
Zip64EndOfCentralDirectoryLocatorWrite();
|
||||
}
|
||||
EndOfCentralDirWrite();
|
||||
|
||||
_zipFs.SetLength(_zipFs.Position);
|
||||
_zipFs.Flush();
|
||||
_zipFs.Close();
|
||||
_zipFs.Dispose();
|
||||
_zipFileInfo = new FileInfo(_zipFileInfo.FullName);
|
||||
ZipOpen = ZipOpenType.Closed;
|
||||
}
|
||||
|
||||
|
||||
public void ZipFileCloseFailed()
|
||||
{
|
||||
switch (ZipOpen)
|
||||
{
|
||||
case ZipOpenType.Closed:
|
||||
return;
|
||||
case ZipOpenType.OpenRead:
|
||||
if (_zipFs != null)
|
||||
{
|
||||
_zipFs.Close();
|
||||
_zipFs.Dispose();
|
||||
}
|
||||
break;
|
||||
case ZipOpenType.OpenWrite:
|
||||
_zipFs.Flush();
|
||||
_zipFs.Close();
|
||||
_zipFs.Dispose();
|
||||
if (_zipFileInfo != null)
|
||||
RVIO.File.Delete(_zipFileInfo.FullName);
|
||||
_zipFileInfo = null;
|
||||
break;
|
||||
}
|
||||
|
||||
ZipOpen = ZipOpenType.Closed;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
73
SabreTools.FileTypes/Compress/ZipFile/ZipWriteStream.cs
Normal file
73
SabreTools.FileTypes/Compress/ZipFile/ZipWriteStream.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.IO;
|
||||
using Compress.Utils;
|
||||
using Compress.ZipFile.ZLib;
|
||||
|
||||
// UInt16 = ushort
|
||||
// UInt32 = uint
|
||||
// ULong = ulong
|
||||
|
||||
namespace Compress.ZipFile
|
||||
{
|
||||
public partial class Zip
|
||||
{
|
||||
private Stream _compressionStream;
|
||||
|
||||
public ZipReturn ZipFileOpenWriteStream(bool raw, bool trrntzip, string filename, ulong uncompressedSize, ushort compressionMethod, out Stream stream, TimeStamps timeStamp = null)
|
||||
{
|
||||
stream = null;
|
||||
if (ZipOpen != ZipOpenType.OpenWrite)
|
||||
{
|
||||
return ZipReturn.ZipWritingToInputFile;
|
||||
}
|
||||
|
||||
LocalFile lf = new LocalFile(filename, timeStamp);
|
||||
|
||||
ZipReturn retVal = lf.LocalFileOpenWriteStream(_zipFs, raw, trrntzip, uncompressedSize, compressionMethod, out stream);
|
||||
|
||||
_compressionStream = stream;
|
||||
_localFiles.Add(lf);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public void ZipFileAddZeroLengthFile()
|
||||
{
|
||||
LocalFile.LocalFileAddZeroLengthFile(_zipFs);
|
||||
}
|
||||
|
||||
|
||||
public ZipReturn ZipFileCloseWriteStream(byte[] crc32)
|
||||
{
|
||||
if (_compressionStream is ZlibBaseStream dfStream)
|
||||
{
|
||||
dfStream.Flush();
|
||||
dfStream.Close();
|
||||
dfStream.Dispose();
|
||||
}
|
||||
_compressionStream = null;
|
||||
|
||||
return _localFiles[_localFiles.Count - 1].LocalFileCloseWriteStream(_zipFs, crc32);
|
||||
}
|
||||
|
||||
public ZipReturn ZipFileRollBack()
|
||||
{
|
||||
if (ZipOpen != ZipOpenType.OpenWrite)
|
||||
{
|
||||
return ZipReturn.ZipWritingToInputFile;
|
||||
}
|
||||
|
||||
int fileCount = _localFiles.Count;
|
||||
if (fileCount == 0)
|
||||
{
|
||||
return ZipReturn.ZipErrorRollBackFile;
|
||||
}
|
||||
|
||||
LocalFile lf = _localFiles[fileCount - 1];
|
||||
|
||||
_localFiles.RemoveAt(fileCount - 1);
|
||||
_zipFs.Position = (long)lf.LocalFilePos;
|
||||
return ZipReturn.ZipGood;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user