libmspack 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/README.md +75 -0
- data/Rakefile +22 -0
- data/UNLICENSE +24 -0
- data/ext/Rakefile +16 -0
- data/ext/i386-windows/libmspack.dll +0 -0
- data/ext/libmspack/AUTHORS +12 -0
- data/ext/libmspack/COPYING.LIB +504 -0
- data/ext/libmspack/ChangeLog +491 -0
- data/ext/libmspack/Makefile.am +100 -0
- data/ext/libmspack/NEWS +0 -0
- data/ext/libmspack/README +130 -0
- data/ext/libmspack/TODO +8 -0
- data/ext/libmspack/cleanup.sh +9 -0
- data/ext/libmspack/configure.ac +50 -0
- data/ext/libmspack/debian/changelog +6 -0
- data/ext/libmspack/debian/control +14 -0
- data/ext/libmspack/debian/rules +101 -0
- data/ext/libmspack/doc/Doxyfile.in +22 -0
- data/ext/libmspack/doc/Makefile.in +14 -0
- data/ext/libmspack/doc/szdd_kwaj_format.html +331 -0
- data/ext/libmspack/libmspack.pc.in +10 -0
- data/ext/libmspack/mspack/cab.h +127 -0
- data/ext/libmspack/mspack/cabc.c +24 -0
- data/ext/libmspack/mspack/cabd.c +1444 -0
- data/ext/libmspack/mspack/chm.h +122 -0
- data/ext/libmspack/mspack/chmc.c +24 -0
- data/ext/libmspack/mspack/chmd.c +1392 -0
- data/ext/libmspack/mspack/crc32.c +95 -0
- data/ext/libmspack/mspack/crc32.h +17 -0
- data/ext/libmspack/mspack/des.h +15 -0
- data/ext/libmspack/mspack/hlp.h +33 -0
- data/ext/libmspack/mspack/hlpc.c +24 -0
- data/ext/libmspack/mspack/hlpd.c +24 -0
- data/ext/libmspack/mspack/kwaj.h +118 -0
- data/ext/libmspack/mspack/kwajc.c +24 -0
- data/ext/libmspack/mspack/kwajd.c +561 -0
- data/ext/libmspack/mspack/lit.h +35 -0
- data/ext/libmspack/mspack/litc.c +24 -0
- data/ext/libmspack/mspack/litd.c +24 -0
- data/ext/libmspack/mspack/lzss.h +66 -0
- data/ext/libmspack/mspack/lzssd.c +93 -0
- data/ext/libmspack/mspack/lzx.h +221 -0
- data/ext/libmspack/mspack/lzxc.c +18 -0
- data/ext/libmspack/mspack/lzxd.c +895 -0
- data/ext/libmspack/mspack/mspack.def +28 -0
- data/ext/libmspack/mspack/mspack.h +2353 -0
- data/ext/libmspack/mspack/mszip.h +126 -0
- data/ext/libmspack/mspack/mszipc.c +18 -0
- data/ext/libmspack/mspack/mszipd.c +514 -0
- data/ext/libmspack/mspack/oab.h +60 -0
- data/ext/libmspack/mspack/oabc.c +24 -0
- data/ext/libmspack/mspack/oabd.c +408 -0
- data/ext/libmspack/mspack/qtm.h +128 -0
- data/ext/libmspack/mspack/qtmc.c +18 -0
- data/ext/libmspack/mspack/qtmd.c +489 -0
- data/ext/libmspack/mspack/readbits.h +207 -0
- data/ext/libmspack/mspack/readhuff.h +173 -0
- data/ext/libmspack/mspack/sha.h +15 -0
- data/ext/libmspack/mspack/system.c +239 -0
- data/ext/libmspack/mspack/system.h +124 -0
- data/ext/libmspack/mspack/szdd.h +39 -0
- data/ext/libmspack/mspack/szddc.c +24 -0
- data/ext/libmspack/mspack/szddd.c +247 -0
- data/ext/libmspack/rebuild.sh +8 -0
- data/ext/libmspack/test/cabd_c10 +19 -0
- data/ext/libmspack/test/cabd_compare +34 -0
- data/ext/libmspack/test/cabd_md5.c +161 -0
- data/ext/libmspack/test/cabd_memory.c +179 -0
- data/ext/libmspack/test/cabd_test.c +386 -0
- data/ext/libmspack/test/cabrip.c +81 -0
- data/ext/libmspack/test/chmd_compare +38 -0
- data/ext/libmspack/test/chmd_find.c +95 -0
- data/ext/libmspack/test/chmd_md5.c +67 -0
- data/ext/libmspack/test/chmd_order.c +144 -0
- data/ext/libmspack/test/chminfo.c +284 -0
- data/ext/libmspack/test/chmx.c +216 -0
- data/ext/libmspack/test/error.h +22 -0
- data/ext/libmspack/test/expand.c +79 -0
- data/ext/libmspack/test/md5.c +457 -0
- data/ext/libmspack/test/md5.h +165 -0
- data/ext/libmspack/test/md5_fh.h +123 -0
- data/ext/libmspack/test/msdecompile_md5 +24 -0
- data/ext/libmspack/test/msexpand_md5 +39 -0
- data/ext/libmspack/test/multifh.c +435 -0
- data/ext/libmspack/test/oabx.c +41 -0
- data/ext/libmspack/test/test_files/cabd/1.pl +84 -0
- data/ext/libmspack/test/test_files/cabd/2.pl +75 -0
- data/ext/libmspack/test/test_files/cabd/bad_folderindex.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_nofiles.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_nofolders.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_signature.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt1.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt2.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt3.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt4.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt5.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/normal_255c_filename.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/normal_2files_1folder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nodata.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nofiles.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nofolder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortextheader.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfile1.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfile2.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfolder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortheader.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nofname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_noninfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nonname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nopinfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nopname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortfname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortninfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortnname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortpinfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortpname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_---.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_--D.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_-F-.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_-FD.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_H--.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_H-D.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_HF-.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_HFD.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/search_basic.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/search_tricky1.cab +0 -0
- data/ext/libmspack/winbuild.sh +26 -0
- data/ext/x86_64-windows/libmspack.dll +0 -0
- data/lib/libmspack/constants.rb +9 -0
- data/lib/libmspack/exceptions.rb +12 -0
- data/lib/libmspack/mscab.rb +722 -0
- data/lib/libmspack/mschm.rb +301 -0
- data/lib/libmspack/mshlp.rb +15 -0
- data/lib/libmspack/mskwaj.rb +124 -0
- data/lib/libmspack/mslit.rb +18 -0
- data/lib/libmspack/msoab.rb +36 -0
- data/lib/libmspack/mspack.rb +208 -0
- data/lib/libmspack/msszdd.rb +81 -0
- data/lib/libmspack/system.rb +84 -0
- data/lib/libmspack/version.rb +4 -0
- data/lib/libmspack.rb +121 -0
- data/libmspack.gemspec +33 -0
- data/spec/libmspack_spec.rb +26 -0
- data/spec/spec_helper.rb +5 -0
- metadata +309 -0
@@ -0,0 +1,126 @@
|
|
1
|
+
/* This file is part of libmspack.
|
2
|
+
* (C) 2003-2004 Stuart Caie.
|
3
|
+
*
|
4
|
+
* The deflate method was created by Phil Katz. MSZIP is equivalent to the
|
5
|
+
* deflate method.
|
6
|
+
*
|
7
|
+
* libmspack is free software; you can redistribute it and/or modify it under
|
8
|
+
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
9
|
+
*
|
10
|
+
* For further details, see the file COPYING.LIB distributed with libmspack
|
11
|
+
*/
|
12
|
+
|
13
|
+
#ifndef MSPACK_MSZIP_H
|
14
|
+
#define MSPACK_MSZIP_H 1
|
15
|
+
|
16
|
+
#ifdef __cplusplus
|
17
|
+
extern "C" {
|
18
|
+
#endif
|
19
|
+
|
20
|
+
/* MSZIP (deflate) compression / (inflate) decompression definitions */
|
21
|
+
|
22
|
+
#define MSZIP_FRAME_SIZE (32768) /* size of LZ history window */
|
23
|
+
#define MSZIP_LITERAL_MAXSYMBOLS (288) /* literal/length huffman tree */
|
24
|
+
#define MSZIP_LITERAL_TABLEBITS (9)
|
25
|
+
#define MSZIP_DISTANCE_MAXSYMBOLS (32) /* distance huffman tree */
|
26
|
+
#define MSZIP_DISTANCE_TABLEBITS (6)
|
27
|
+
|
28
|
+
/* if there are less direct lookup entries than symbols, the longer
|
29
|
+
* code pointers will be <= maxsymbols. This must not happen, or we
|
30
|
+
* will decode entries badly */
|
31
|
+
#if (1 << MSZIP_LITERAL_TABLEBITS) < (MSZIP_LITERAL_MAXSYMBOLS * 2)
|
32
|
+
# define MSZIP_LITERAL_TABLESIZE (MSZIP_LITERAL_MAXSYMBOLS * 4)
|
33
|
+
#else
|
34
|
+
# define MSZIP_LITERAL_TABLESIZE ((1 << MSZIP_LITERAL_TABLEBITS) + \
|
35
|
+
(MSZIP_LITERAL_MAXSYMBOLS * 2))
|
36
|
+
#endif
|
37
|
+
|
38
|
+
#if (1 << MSZIP_DISTANCE_TABLEBITS) < (MSZIP_DISTANCE_MAXSYMBOLS * 2)
|
39
|
+
# define MSZIP_DISTANCE_TABLESIZE (MSZIP_DISTANCE_MAXSYMBOLS * 4)
|
40
|
+
#else
|
41
|
+
# define MSZIP_DISTANCE_TABLESIZE ((1 << MSZIP_DISTANCE_TABLEBITS) + \
|
42
|
+
(MSZIP_DISTANCE_MAXSYMBOLS * 2))
|
43
|
+
#endif
|
44
|
+
|
45
|
+
struct mszipd_stream {
|
46
|
+
struct mspack_system *sys; /* I/O routines */
|
47
|
+
struct mspack_file *input; /* input file handle */
|
48
|
+
struct mspack_file *output; /* output file handle */
|
49
|
+
unsigned int window_posn; /* offset within window */
|
50
|
+
|
51
|
+
/* inflate() will call this whenever the window should be emptied. */
|
52
|
+
int (*flush_window)(struct mszipd_stream *, unsigned int);
|
53
|
+
|
54
|
+
int error, repair_mode, bytes_output;
|
55
|
+
|
56
|
+
/* I/O buffering */
|
57
|
+
unsigned char *inbuf, *i_ptr, *i_end, *o_ptr, *o_end, input_end;
|
58
|
+
unsigned int bit_buffer, bits_left, inbuf_size;
|
59
|
+
|
60
|
+
|
61
|
+
/* huffman code lengths */
|
62
|
+
unsigned char LITERAL_len[MSZIP_LITERAL_MAXSYMBOLS];
|
63
|
+
unsigned char DISTANCE_len[MSZIP_DISTANCE_MAXSYMBOLS];
|
64
|
+
|
65
|
+
/* huffman decoding tables */
|
66
|
+
unsigned short LITERAL_table [MSZIP_LITERAL_TABLESIZE];
|
67
|
+
unsigned short DISTANCE_table[MSZIP_DISTANCE_TABLESIZE];
|
68
|
+
|
69
|
+
/* 32kb history window */
|
70
|
+
unsigned char window[MSZIP_FRAME_SIZE];
|
71
|
+
};
|
72
|
+
|
73
|
+
/* allocates MS-ZIP decompression stream for decoding the given stream.
|
74
|
+
*
|
75
|
+
* - uses system->alloc() to allocate memory
|
76
|
+
*
|
77
|
+
* - returns NULL if not enough memory
|
78
|
+
*
|
79
|
+
* - input_buffer_size is how many bytes to use as an input bitstream buffer
|
80
|
+
*
|
81
|
+
* - if repair_mode is non-zero, errors in decompression will be skipped
|
82
|
+
* and 'holes' left will be filled with zero bytes. This allows at least
|
83
|
+
* a partial recovery of erroneous data.
|
84
|
+
*/
|
85
|
+
extern struct mszipd_stream *mszipd_init(struct mspack_system *system,
|
86
|
+
struct mspack_file *input,
|
87
|
+
struct mspack_file *output,
|
88
|
+
int input_buffer_size,
|
89
|
+
int repair_mode);
|
90
|
+
|
91
|
+
/* decompresses, or decompresses more of, an MS-ZIP stream.
|
92
|
+
*
|
93
|
+
* - out_bytes of data will be decompressed and the function will return
|
94
|
+
* with an MSPACK_ERR_OK return code.
|
95
|
+
*
|
96
|
+
* - decompressing will stop as soon as out_bytes is reached. if the true
|
97
|
+
* amount of bytes decoded spills over that amount, they will be kept for
|
98
|
+
* a later invocation of mszipd_decompress().
|
99
|
+
*
|
100
|
+
* - the output bytes will be passed to the system->write() function given in
|
101
|
+
* mszipd_init(), using the output file handle given in mszipd_init(). More
|
102
|
+
* than one call may be made to system->write()
|
103
|
+
*
|
104
|
+
* - MS-ZIP will read input bytes as necessary using the system->read()
|
105
|
+
* function given in mszipd_init(), using the input file handle given in
|
106
|
+
* mszipd_init(). This will continue until system->read() returns 0 bytes,
|
107
|
+
* or an error.
|
108
|
+
*/
|
109
|
+
extern int mszipd_decompress(struct mszipd_stream *zip, off_t out_bytes);
|
110
|
+
|
111
|
+
/* decompresses an entire MS-ZIP stream in a KWAJ file. Acts very much
|
112
|
+
* like mszipd_decompress(), but doesn't take an out_bytes parameter
|
113
|
+
*/
|
114
|
+
extern int mszipd_decompress_kwaj(struct mszipd_stream *zip);
|
115
|
+
|
116
|
+
/* frees all stream associated with an MS-ZIP data stream
|
117
|
+
*
|
118
|
+
* - calls system->free() using the system pointer given in mszipd_init()
|
119
|
+
*/
|
120
|
+
void mszipd_free(struct mszipd_stream *zip);
|
121
|
+
|
122
|
+
#ifdef __cplusplus
|
123
|
+
}
|
124
|
+
#endif
|
125
|
+
|
126
|
+
#endif
|
@@ -0,0 +1,18 @@
|
|
1
|
+
/* This file is part of libmspack.
|
2
|
+
* (C) 2003-2004 Stuart Caie.
|
3
|
+
*
|
4
|
+
* The deflate method was created by Phil Katz. MSZIP is equivalent to the
|
5
|
+
* deflate method.
|
6
|
+
*
|
7
|
+
* libmspack is free software; you can redistribute it and/or modify it under
|
8
|
+
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
9
|
+
*
|
10
|
+
* For further details, see the file COPYING.LIB distributed with libmspack
|
11
|
+
*/
|
12
|
+
|
13
|
+
/* MS-ZIP compression implementation */
|
14
|
+
|
15
|
+
#include <system.h>
|
16
|
+
#include <mszip.h>
|
17
|
+
|
18
|
+
/* todo */
|
@@ -0,0 +1,514 @@
|
|
1
|
+
/* This file is part of libmspack.
|
2
|
+
* (C) 2003-2010 Stuart Caie.
|
3
|
+
*
|
4
|
+
* The deflate method was created by Phil Katz. MSZIP is equivalent to the
|
5
|
+
* deflate method.
|
6
|
+
*
|
7
|
+
* libmspack is free software; you can redistribute it and/or modify it under
|
8
|
+
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
9
|
+
*
|
10
|
+
* For further details, see the file COPYING.LIB distributed with libmspack
|
11
|
+
*/
|
12
|
+
|
13
|
+
/* MS-ZIP decompression implementation. */
|
14
|
+
|
15
|
+
#include <system.h>
|
16
|
+
#include <mszip.h>
|
17
|
+
|
18
|
+
/* import bit-reading macros and code */
|
19
|
+
#define BITS_TYPE struct mszipd_stream
|
20
|
+
#define BITS_VAR zip
|
21
|
+
#define BITS_ORDER_LSB
|
22
|
+
#define BITS_LSB_TABLE
|
23
|
+
#define READ_BYTES do { \
|
24
|
+
READ_IF_NEEDED; \
|
25
|
+
INJECT_BITS(*i_ptr++, 8); \
|
26
|
+
} while (0)
|
27
|
+
#include <readbits.h>
|
28
|
+
|
29
|
+
/* import huffman macros and code */
|
30
|
+
#define TABLEBITS(tbl) MSZIP_##tbl##_TABLEBITS
|
31
|
+
#define MAXSYMBOLS(tbl) MSZIP_##tbl##_MAXSYMBOLS
|
32
|
+
#define HUFF_TABLE(tbl,idx) zip->tbl##_table[idx]
|
33
|
+
#define HUFF_LEN(tbl,idx) zip->tbl##_len[idx]
|
34
|
+
#define HUFF_ERROR return INF_ERR_HUFFSYM
|
35
|
+
#include <readhuff.h>
|
36
|
+
|
37
|
+
#define FLUSH_IF_NEEDED do { \
|
38
|
+
if (zip->window_posn == MSZIP_FRAME_SIZE) { \
|
39
|
+
if (zip->flush_window(zip, MSZIP_FRAME_SIZE)) { \
|
40
|
+
return INF_ERR_FLUSH; \
|
41
|
+
} \
|
42
|
+
zip->window_posn = 0; \
|
43
|
+
} \
|
44
|
+
} while (0)
|
45
|
+
|
46
|
+
/* match lengths for literal codes 257.. 285 */
|
47
|
+
static const unsigned short lit_lengths[29] = {
|
48
|
+
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
|
49
|
+
31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
|
50
|
+
};
|
51
|
+
|
52
|
+
/* match offsets for distance codes 0 .. 29 */
|
53
|
+
static const unsigned short dist_offsets[30] = {
|
54
|
+
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
|
55
|
+
513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
|
56
|
+
};
|
57
|
+
|
58
|
+
/* extra bits required for literal codes 257.. 285 */
|
59
|
+
static const unsigned char lit_extrabits[29] = {
|
60
|
+
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
|
61
|
+
2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
|
62
|
+
};
|
63
|
+
|
64
|
+
/* extra bits required for distance codes 0 .. 29 */
|
65
|
+
static const unsigned char dist_extrabits[30] = {
|
66
|
+
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
|
67
|
+
6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
|
68
|
+
};
|
69
|
+
|
70
|
+
/* the order of the bit length Huffman code lengths */
|
71
|
+
static const unsigned char bitlen_order[19] = {
|
72
|
+
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
73
|
+
};
|
74
|
+
|
75
|
+
/* inflate() error codes */
|
76
|
+
#define INF_ERR_BLOCKTYPE (-1) /* unknown block type */
|
77
|
+
#define INF_ERR_COMPLEMENT (-2) /* block size complement mismatch */
|
78
|
+
#define INF_ERR_FLUSH (-3) /* error from flush_window() callback */
|
79
|
+
#define INF_ERR_BITBUF (-4) /* too many bits in bit buffer */
|
80
|
+
#define INF_ERR_SYMLENS (-5) /* too many symbols in blocktype 2 header */
|
81
|
+
#define INF_ERR_BITLENTBL (-6) /* failed to build bitlens huffman table */
|
82
|
+
#define INF_ERR_LITERALTBL (-7) /* failed to build literals huffman table */
|
83
|
+
#define INF_ERR_DISTANCETBL (-8) /* failed to build distance huffman table */
|
84
|
+
#define INF_ERR_BITOVERRUN (-9) /* bitlen RLE code goes over table size */
|
85
|
+
#define INF_ERR_BADBITLEN (-10) /* invalid bit-length code */
|
86
|
+
#define INF_ERR_LITCODE (-11) /* out-of-range literal code */
|
87
|
+
#define INF_ERR_DISTCODE (-12) /* out-of-range distance code */
|
88
|
+
#define INF_ERR_DISTANCE (-13) /* somehow, distance is beyond 32k */
|
89
|
+
#define INF_ERR_HUFFSYM (-14) /* out of bits decoding huffman symbol */
|
90
|
+
|
91
|
+
static int zip_read_lens(struct mszipd_stream *zip) {
|
92
|
+
/* for the bit buffer and huffman decoding */
|
93
|
+
register unsigned int bit_buffer;
|
94
|
+
register int bits_left;
|
95
|
+
unsigned char *i_ptr, *i_end;
|
96
|
+
|
97
|
+
/* bitlen Huffman codes -- immediate lookup, 7 bit max code length */
|
98
|
+
unsigned short bl_table[(1 << 7)];
|
99
|
+
unsigned char bl_len[19];
|
100
|
+
|
101
|
+
unsigned char lens[MSZIP_LITERAL_MAXSYMBOLS + MSZIP_DISTANCE_MAXSYMBOLS];
|
102
|
+
unsigned int lit_codes, dist_codes, code, last_code=0, bitlen_codes, i, run;
|
103
|
+
|
104
|
+
RESTORE_BITS;
|
105
|
+
|
106
|
+
/* read the number of codes */
|
107
|
+
READ_BITS(lit_codes, 5); lit_codes += 257;
|
108
|
+
READ_BITS(dist_codes, 5); dist_codes += 1;
|
109
|
+
READ_BITS(bitlen_codes, 4); bitlen_codes += 4;
|
110
|
+
if (lit_codes > MSZIP_LITERAL_MAXSYMBOLS) return INF_ERR_SYMLENS;
|
111
|
+
if (dist_codes > MSZIP_DISTANCE_MAXSYMBOLS) return INF_ERR_SYMLENS;
|
112
|
+
|
113
|
+
/* read in the bit lengths in their unusual order */
|
114
|
+
for (i = 0; i < bitlen_codes; i++) READ_BITS(bl_len[bitlen_order[i]], 3);
|
115
|
+
while (i < 19) bl_len[bitlen_order[i++]] = 0;
|
116
|
+
|
117
|
+
/* create decoding table with an immediate lookup */
|
118
|
+
if (make_decode_table(19, 7, &bl_len[0], &bl_table[0])) {
|
119
|
+
return INF_ERR_BITLENTBL;
|
120
|
+
}
|
121
|
+
|
122
|
+
/* read literal / distance code lengths */
|
123
|
+
for (i = 0; i < (lit_codes + dist_codes); i++) {
|
124
|
+
/* single-level huffman lookup */
|
125
|
+
ENSURE_BITS(7);
|
126
|
+
code = bl_table[PEEK_BITS(7)];
|
127
|
+
REMOVE_BITS(bl_len[code]);
|
128
|
+
|
129
|
+
if (code < 16) lens[i] = last_code = code;
|
130
|
+
else {
|
131
|
+
switch (code) {
|
132
|
+
case 16: READ_BITS(run, 2); run += 3; code = last_code; break;
|
133
|
+
case 17: READ_BITS(run, 3); run += 3; code = 0; break;
|
134
|
+
case 18: READ_BITS(run, 7); run += 11; code = 0; break;
|
135
|
+
default: D(("bad code!: %u", code)) return INF_ERR_BADBITLEN;
|
136
|
+
}
|
137
|
+
if ((i + run) > (lit_codes + dist_codes)) return INF_ERR_BITOVERRUN;
|
138
|
+
while (run--) lens[i++] = code;
|
139
|
+
i--;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
/* copy LITERAL code lengths and clear any remaining */
|
144
|
+
i = lit_codes;
|
145
|
+
zip->sys->copy(&lens[0], &zip->LITERAL_len[0], i);
|
146
|
+
while (i < MSZIP_LITERAL_MAXSYMBOLS) zip->LITERAL_len[i++] = 0;
|
147
|
+
|
148
|
+
i = dist_codes;
|
149
|
+
zip->sys->copy(&lens[lit_codes], &zip->DISTANCE_len[0], i);
|
150
|
+
while (i < MSZIP_DISTANCE_MAXSYMBOLS) zip->DISTANCE_len[i++] = 0;
|
151
|
+
|
152
|
+
STORE_BITS;
|
153
|
+
return 0;
|
154
|
+
}
|
155
|
+
|
156
|
+
/* a clean implementation of RFC 1951 / inflate */
|
157
|
+
static int inflate(struct mszipd_stream *zip) {
|
158
|
+
unsigned int last_block, block_type, distance, length, this_run, i;
|
159
|
+
|
160
|
+
/* for the bit buffer and huffman decoding */
|
161
|
+
register unsigned int bit_buffer;
|
162
|
+
register int bits_left;
|
163
|
+
register unsigned short sym;
|
164
|
+
unsigned char *i_ptr, *i_end;
|
165
|
+
|
166
|
+
RESTORE_BITS;
|
167
|
+
|
168
|
+
do {
|
169
|
+
/* read in last block bit */
|
170
|
+
READ_BITS(last_block, 1);
|
171
|
+
|
172
|
+
/* read in block type */
|
173
|
+
READ_BITS(block_type, 2);
|
174
|
+
|
175
|
+
if (block_type == 0) {
|
176
|
+
/* uncompressed block */
|
177
|
+
unsigned char lens_buf[4];
|
178
|
+
|
179
|
+
/* go to byte boundary */
|
180
|
+
i = bits_left & 7; REMOVE_BITS(i);
|
181
|
+
|
182
|
+
/* read 4 bytes of data, emptying the bit-buffer if necessary */
|
183
|
+
for (i = 0; (bits_left >= 8); i++) {
|
184
|
+
if (i == 4) return INF_ERR_BITBUF;
|
185
|
+
lens_buf[i] = PEEK_BITS(8);
|
186
|
+
REMOVE_BITS(8);
|
187
|
+
}
|
188
|
+
if (bits_left != 0) return INF_ERR_BITBUF;
|
189
|
+
while (i < 4) {
|
190
|
+
READ_IF_NEEDED;
|
191
|
+
lens_buf[i++] = *i_ptr++;
|
192
|
+
}
|
193
|
+
|
194
|
+
/* get the length and its complement */
|
195
|
+
length = lens_buf[0] | (lens_buf[1] << 8);
|
196
|
+
i = lens_buf[2] | (lens_buf[3] << 8);
|
197
|
+
if (length != (~i & 0xFFFF)) return INF_ERR_COMPLEMENT;
|
198
|
+
|
199
|
+
/* read and copy the uncompressed data into the window */
|
200
|
+
while (length > 0) {
|
201
|
+
READ_IF_NEEDED;
|
202
|
+
|
203
|
+
this_run = length;
|
204
|
+
if (this_run > (unsigned int)(i_end - i_ptr)) this_run = i_end - i_ptr;
|
205
|
+
if (this_run > (MSZIP_FRAME_SIZE - zip->window_posn))
|
206
|
+
this_run = MSZIP_FRAME_SIZE - zip->window_posn;
|
207
|
+
|
208
|
+
zip->sys->copy(i_ptr, &zip->window[zip->window_posn], this_run);
|
209
|
+
zip->window_posn += this_run;
|
210
|
+
i_ptr += this_run;
|
211
|
+
length -= this_run;
|
212
|
+
FLUSH_IF_NEEDED;
|
213
|
+
}
|
214
|
+
}
|
215
|
+
else if ((block_type == 1) || (block_type == 2)) {
|
216
|
+
/* Huffman-compressed LZ77 block */
|
217
|
+
unsigned int match_posn, code;
|
218
|
+
|
219
|
+
if (block_type == 1) {
|
220
|
+
/* block with fixed Huffman codes */
|
221
|
+
i = 0;
|
222
|
+
while (i < 144) zip->LITERAL_len[i++] = 8;
|
223
|
+
while (i < 256) zip->LITERAL_len[i++] = 9;
|
224
|
+
while (i < 280) zip->LITERAL_len[i++] = 7;
|
225
|
+
while (i < 288) zip->LITERAL_len[i++] = 8;
|
226
|
+
for (i = 0; i < 32; i++) zip->DISTANCE_len[i] = 5;
|
227
|
+
}
|
228
|
+
else {
|
229
|
+
/* block with dynamic Huffman codes */
|
230
|
+
STORE_BITS;
|
231
|
+
if ((i = zip_read_lens(zip))) return i;
|
232
|
+
RESTORE_BITS;
|
233
|
+
}
|
234
|
+
|
235
|
+
/* now huffman lengths are read for either kind of block,
|
236
|
+
* create huffman decoding tables */
|
237
|
+
if (make_decode_table(MSZIP_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS,
|
238
|
+
&zip->LITERAL_len[0], &zip->LITERAL_table[0]))
|
239
|
+
{
|
240
|
+
return INF_ERR_LITERALTBL;
|
241
|
+
}
|
242
|
+
|
243
|
+
if (make_decode_table(MSZIP_DISTANCE_MAXSYMBOLS,MSZIP_DISTANCE_TABLEBITS,
|
244
|
+
&zip->DISTANCE_len[0], &zip->DISTANCE_table[0]))
|
245
|
+
{
|
246
|
+
return INF_ERR_DISTANCETBL;
|
247
|
+
}
|
248
|
+
|
249
|
+
/* decode forever until end of block code */
|
250
|
+
for (;;) {
|
251
|
+
READ_HUFFSYM(LITERAL, code);
|
252
|
+
if (code < 256) {
|
253
|
+
zip->window[zip->window_posn++] = (unsigned char) code;
|
254
|
+
FLUSH_IF_NEEDED;
|
255
|
+
}
|
256
|
+
else if (code == 256) {
|
257
|
+
/* END OF BLOCK CODE: loop break point */
|
258
|
+
break;
|
259
|
+
}
|
260
|
+
else {
|
261
|
+
code -= 257; /* codes 257-285 are matches */
|
262
|
+
if (code >= 29) return INF_ERR_LITCODE; /* codes 286-287 are illegal */
|
263
|
+
READ_BITS_T(length, lit_extrabits[code]);
|
264
|
+
length += lit_lengths[code];
|
265
|
+
|
266
|
+
READ_HUFFSYM(DISTANCE, code);
|
267
|
+
if (code > 30) return INF_ERR_DISTCODE;
|
268
|
+
READ_BITS_T(distance, dist_extrabits[code]);
|
269
|
+
distance += dist_offsets[code];
|
270
|
+
|
271
|
+
/* match position is window position minus distance. If distance
|
272
|
+
* is more than window position numerically, it must 'wrap
|
273
|
+
* around' the frame size. */
|
274
|
+
match_posn = ((distance > zip->window_posn) ? MSZIP_FRAME_SIZE : 0)
|
275
|
+
+ zip->window_posn - distance;
|
276
|
+
|
277
|
+
/* copy match */
|
278
|
+
if (length < 12) {
|
279
|
+
/* short match, use slower loop but no loop setup code */
|
280
|
+
while (length--) {
|
281
|
+
zip->window[zip->window_posn++] = zip->window[match_posn++];
|
282
|
+
match_posn &= MSZIP_FRAME_SIZE - 1;
|
283
|
+
FLUSH_IF_NEEDED;
|
284
|
+
}
|
285
|
+
}
|
286
|
+
else {
|
287
|
+
/* longer match, use faster loop but with setup expense */
|
288
|
+
unsigned char *runsrc, *rundest;
|
289
|
+
do {
|
290
|
+
this_run = length;
|
291
|
+
if ((match_posn + this_run) > MSZIP_FRAME_SIZE)
|
292
|
+
this_run = MSZIP_FRAME_SIZE - match_posn;
|
293
|
+
if ((zip->window_posn + this_run) > MSZIP_FRAME_SIZE)
|
294
|
+
this_run = MSZIP_FRAME_SIZE - zip->window_posn;
|
295
|
+
|
296
|
+
rundest = &zip->window[zip->window_posn]; zip->window_posn += this_run;
|
297
|
+
runsrc = &zip->window[match_posn]; match_posn += this_run;
|
298
|
+
length -= this_run;
|
299
|
+
while (this_run--) *rundest++ = *runsrc++;
|
300
|
+
if (match_posn == MSZIP_FRAME_SIZE) match_posn = 0;
|
301
|
+
FLUSH_IF_NEEDED;
|
302
|
+
} while (length > 0);
|
303
|
+
}
|
304
|
+
|
305
|
+
} /* else (code >= 257) */
|
306
|
+
|
307
|
+
} /* for(;;) -- break point at 'code == 256' */
|
308
|
+
}
|
309
|
+
else {
|
310
|
+
/* block_type == 3 -- bad block type */
|
311
|
+
return INF_ERR_BLOCKTYPE;
|
312
|
+
}
|
313
|
+
} while (!last_block);
|
314
|
+
|
315
|
+
/* flush the remaining data */
|
316
|
+
if (zip->window_posn) {
|
317
|
+
if (zip->flush_window(zip, zip->window_posn)) return INF_ERR_FLUSH;
|
318
|
+
}
|
319
|
+
STORE_BITS;
|
320
|
+
|
321
|
+
/* return success */
|
322
|
+
return 0;
|
323
|
+
}
|
324
|
+
|
325
|
+
/* inflate() calls this whenever the window should be flushed. As
|
326
|
+
* MSZIP only expands to the size of the window, the implementation used
|
327
|
+
* simply keeps track of the amount of data flushed, and if more than 32k
|
328
|
+
* is flushed, an error is raised.
|
329
|
+
*/
|
330
|
+
static int mszipd_flush_window(struct mszipd_stream *zip,
|
331
|
+
unsigned int data_flushed)
|
332
|
+
{
|
333
|
+
zip->bytes_output += data_flushed;
|
334
|
+
if (zip->bytes_output > MSZIP_FRAME_SIZE) {
|
335
|
+
D(("overflow: %u bytes flushed, total is now %u",
|
336
|
+
data_flushed, zip->bytes_output))
|
337
|
+
return 1;
|
338
|
+
}
|
339
|
+
return 0;
|
340
|
+
}
|
341
|
+
|
342
|
+
struct mszipd_stream *mszipd_init(struct mspack_system *system,
|
343
|
+
struct mspack_file *input,
|
344
|
+
struct mspack_file *output,
|
345
|
+
int input_buffer_size,
|
346
|
+
int repair_mode)
|
347
|
+
{
|
348
|
+
struct mszipd_stream *zip;
|
349
|
+
|
350
|
+
if (!system) return NULL;
|
351
|
+
|
352
|
+
input_buffer_size = (input_buffer_size + 1) & -2;
|
353
|
+
if (!input_buffer_size) return NULL;
|
354
|
+
|
355
|
+
/* allocate decompression state */
|
356
|
+
if (!(zip = (struct mszipd_stream *) system->alloc(system, sizeof(struct mszipd_stream)))) {
|
357
|
+
return NULL;
|
358
|
+
}
|
359
|
+
|
360
|
+
/* allocate input buffer */
|
361
|
+
zip->inbuf = (unsigned char *) system->alloc(system, (size_t) input_buffer_size);
|
362
|
+
if (!zip->inbuf) {
|
363
|
+
system->free(zip);
|
364
|
+
return NULL;
|
365
|
+
}
|
366
|
+
|
367
|
+
/* initialise decompression state */
|
368
|
+
zip->sys = system;
|
369
|
+
zip->input = input;
|
370
|
+
zip->output = output;
|
371
|
+
zip->inbuf_size = input_buffer_size;
|
372
|
+
zip->input_end = 0;
|
373
|
+
zip->error = MSPACK_ERR_OK;
|
374
|
+
zip->repair_mode = repair_mode;
|
375
|
+
zip->flush_window = &mszipd_flush_window;
|
376
|
+
|
377
|
+
zip->i_ptr = zip->i_end = &zip->inbuf[0];
|
378
|
+
zip->o_ptr = zip->o_end = NULL;
|
379
|
+
zip->bit_buffer = 0; zip->bits_left = 0;
|
380
|
+
return zip;
|
381
|
+
}
|
382
|
+
|
383
|
+
int mszipd_decompress(struct mszipd_stream *zip, off_t out_bytes) {
|
384
|
+
/* for the bit buffer */
|
385
|
+
register unsigned int bit_buffer;
|
386
|
+
register int bits_left;
|
387
|
+
unsigned char *i_ptr, *i_end;
|
388
|
+
|
389
|
+
int i, state, error;
|
390
|
+
|
391
|
+
/* easy answers */
|
392
|
+
if (!zip || (out_bytes < 0)) return MSPACK_ERR_ARGS;
|
393
|
+
if (zip->error) return zip->error;
|
394
|
+
|
395
|
+
/* flush out any stored-up bytes before we begin */
|
396
|
+
i = zip->o_end - zip->o_ptr;
|
397
|
+
if ((off_t) i > out_bytes) i = (int) out_bytes;
|
398
|
+
if (i) {
|
399
|
+
if (zip->sys->write(zip->output, zip->o_ptr, i) != i) {
|
400
|
+
return zip->error = MSPACK_ERR_WRITE;
|
401
|
+
}
|
402
|
+
zip->o_ptr += i;
|
403
|
+
out_bytes -= i;
|
404
|
+
}
|
405
|
+
if (out_bytes == 0) return MSPACK_ERR_OK;
|
406
|
+
|
407
|
+
|
408
|
+
while (out_bytes > 0) {
|
409
|
+
/* unpack another block */
|
410
|
+
RESTORE_BITS;
|
411
|
+
|
412
|
+
/* skip to next read 'CK' header */
|
413
|
+
i = bits_left & 7; REMOVE_BITS(i); /* align to bytestream */
|
414
|
+
state = 0;
|
415
|
+
do {
|
416
|
+
READ_BITS(i, 8);
|
417
|
+
if (i == 'C') state = 1;
|
418
|
+
else if ((state == 1) && (i == 'K')) state = 2;
|
419
|
+
else state = 0;
|
420
|
+
} while (state != 2);
|
421
|
+
|
422
|
+
/* inflate a block, repair and realign if necessary */
|
423
|
+
zip->window_posn = 0;
|
424
|
+
zip->bytes_output = 0;
|
425
|
+
STORE_BITS;
|
426
|
+
if ((error = inflate(zip))) {
|
427
|
+
D(("inflate error %d", error))
|
428
|
+
if (zip->repair_mode) {
|
429
|
+
/* recover partially-inflated buffers */
|
430
|
+
if (zip->bytes_output == 0 && zip->window_posn > 0) {
|
431
|
+
zip->flush_window(zip, zip->window_posn);
|
432
|
+
}
|
433
|
+
zip->sys->message(NULL, "MSZIP error, %u bytes of data lost.",
|
434
|
+
MSZIP_FRAME_SIZE - zip->bytes_output);
|
435
|
+
for (i = zip->bytes_output; i < MSZIP_FRAME_SIZE; i++) {
|
436
|
+
zip->window[i] = '\0';
|
437
|
+
}
|
438
|
+
zip->bytes_output = MSZIP_FRAME_SIZE;
|
439
|
+
}
|
440
|
+
else {
|
441
|
+
return zip->error = (error > 0) ? error : MSPACK_ERR_DECRUNCH;
|
442
|
+
}
|
443
|
+
}
|
444
|
+
zip->o_ptr = &zip->window[0];
|
445
|
+
zip->o_end = &zip->o_ptr[zip->bytes_output];
|
446
|
+
|
447
|
+
/* write a frame */
|
448
|
+
i = (out_bytes < (off_t)zip->bytes_output) ?
|
449
|
+
(int)out_bytes : zip->bytes_output;
|
450
|
+
if (zip->sys->write(zip->output, zip->o_ptr, i) != i) {
|
451
|
+
return zip->error = MSPACK_ERR_WRITE;
|
452
|
+
}
|
453
|
+
|
454
|
+
/* mspack errors (i.e. read errors) are fatal and can't be recovered */
|
455
|
+
if ((error > 0) && zip->repair_mode) return error;
|
456
|
+
|
457
|
+
zip->o_ptr += i;
|
458
|
+
out_bytes -= i;
|
459
|
+
}
|
460
|
+
|
461
|
+
if (out_bytes) {
|
462
|
+
D(("bytes left to output"))
|
463
|
+
return zip->error = MSPACK_ERR_DECRUNCH;
|
464
|
+
}
|
465
|
+
return MSPACK_ERR_OK;
|
466
|
+
}
|
467
|
+
|
468
|
+
int mszipd_decompress_kwaj(struct mszipd_stream *zip) {
|
469
|
+
/* for the bit buffer */
|
470
|
+
register unsigned int bit_buffer;
|
471
|
+
register int bits_left;
|
472
|
+
unsigned char *i_ptr, *i_end;
|
473
|
+
|
474
|
+
int i, error, block_len;
|
475
|
+
|
476
|
+
/* unpack blocks until block_len == 0 */
|
477
|
+
for (;;) {
|
478
|
+
RESTORE_BITS;
|
479
|
+
|
480
|
+
/* align to bytestream, read block_len */
|
481
|
+
i = bits_left & 7; REMOVE_BITS(i);
|
482
|
+
READ_BITS(block_len, 8);
|
483
|
+
READ_BITS(i, 8); block_len |= i << 8;
|
484
|
+
|
485
|
+
if (block_len == 0) break;
|
486
|
+
|
487
|
+
/* read "CK" header */
|
488
|
+
READ_BITS(i, 8); if (i != 'C') return MSPACK_ERR_DATAFORMAT;
|
489
|
+
READ_BITS(i, 8); if (i != 'K') return MSPACK_ERR_DATAFORMAT;
|
490
|
+
|
491
|
+
/* inflate block */
|
492
|
+
zip->window_posn = 0;
|
493
|
+
zip->bytes_output = 0;
|
494
|
+
STORE_BITS;
|
495
|
+
if ((error = inflate(zip))) {
|
496
|
+
D(("inflate error %d", error))
|
497
|
+
return zip->error = (error > 0) ? error : MSPACK_ERR_DECRUNCH;
|
498
|
+
}
|
499
|
+
|
500
|
+
/* write inflated block */
|
501
|
+
if (zip->sys->write(zip->output, &zip->window[0], zip->bytes_output)
|
502
|
+
!= zip->bytes_output) return zip->error = MSPACK_ERR_WRITE;
|
503
|
+
}
|
504
|
+
return MSPACK_ERR_OK;
|
505
|
+
}
|
506
|
+
|
507
|
+
void mszipd_free(struct mszipd_stream *zip) {
|
508
|
+
struct mspack_system *sys;
|
509
|
+
if (zip) {
|
510
|
+
sys = zip->sys;
|
511
|
+
sys->free(zip->inbuf);
|
512
|
+
sys->free(zip);
|
513
|
+
}
|
514
|
+
}
|