libmspack 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +5 -0
  4. data/.yardopts +1 -0
  5. data/Gemfile +4 -0
  6. data/README.md +75 -0
  7. data/Rakefile +22 -0
  8. data/UNLICENSE +24 -0
  9. data/ext/Rakefile +16 -0
  10. data/ext/i386-windows/libmspack.dll +0 -0
  11. data/ext/libmspack/AUTHORS +12 -0
  12. data/ext/libmspack/COPYING.LIB +504 -0
  13. data/ext/libmspack/ChangeLog +491 -0
  14. data/ext/libmspack/Makefile.am +100 -0
  15. data/ext/libmspack/NEWS +0 -0
  16. data/ext/libmspack/README +130 -0
  17. data/ext/libmspack/TODO +8 -0
  18. data/ext/libmspack/cleanup.sh +9 -0
  19. data/ext/libmspack/configure.ac +50 -0
  20. data/ext/libmspack/debian/changelog +6 -0
  21. data/ext/libmspack/debian/control +14 -0
  22. data/ext/libmspack/debian/rules +101 -0
  23. data/ext/libmspack/doc/Doxyfile.in +22 -0
  24. data/ext/libmspack/doc/Makefile.in +14 -0
  25. data/ext/libmspack/doc/szdd_kwaj_format.html +331 -0
  26. data/ext/libmspack/libmspack.pc.in +10 -0
  27. data/ext/libmspack/mspack/cab.h +127 -0
  28. data/ext/libmspack/mspack/cabc.c +24 -0
  29. data/ext/libmspack/mspack/cabd.c +1444 -0
  30. data/ext/libmspack/mspack/chm.h +122 -0
  31. data/ext/libmspack/mspack/chmc.c +24 -0
  32. data/ext/libmspack/mspack/chmd.c +1392 -0
  33. data/ext/libmspack/mspack/crc32.c +95 -0
  34. data/ext/libmspack/mspack/crc32.h +17 -0
  35. data/ext/libmspack/mspack/des.h +15 -0
  36. data/ext/libmspack/mspack/hlp.h +33 -0
  37. data/ext/libmspack/mspack/hlpc.c +24 -0
  38. data/ext/libmspack/mspack/hlpd.c +24 -0
  39. data/ext/libmspack/mspack/kwaj.h +118 -0
  40. data/ext/libmspack/mspack/kwajc.c +24 -0
  41. data/ext/libmspack/mspack/kwajd.c +561 -0
  42. data/ext/libmspack/mspack/lit.h +35 -0
  43. data/ext/libmspack/mspack/litc.c +24 -0
  44. data/ext/libmspack/mspack/litd.c +24 -0
  45. data/ext/libmspack/mspack/lzss.h +66 -0
  46. data/ext/libmspack/mspack/lzssd.c +93 -0
  47. data/ext/libmspack/mspack/lzx.h +221 -0
  48. data/ext/libmspack/mspack/lzxc.c +18 -0
  49. data/ext/libmspack/mspack/lzxd.c +895 -0
  50. data/ext/libmspack/mspack/mspack.def +28 -0
  51. data/ext/libmspack/mspack/mspack.h +2353 -0
  52. data/ext/libmspack/mspack/mszip.h +126 -0
  53. data/ext/libmspack/mspack/mszipc.c +18 -0
  54. data/ext/libmspack/mspack/mszipd.c +514 -0
  55. data/ext/libmspack/mspack/oab.h +60 -0
  56. data/ext/libmspack/mspack/oabc.c +24 -0
  57. data/ext/libmspack/mspack/oabd.c +408 -0
  58. data/ext/libmspack/mspack/qtm.h +128 -0
  59. data/ext/libmspack/mspack/qtmc.c +18 -0
  60. data/ext/libmspack/mspack/qtmd.c +489 -0
  61. data/ext/libmspack/mspack/readbits.h +207 -0
  62. data/ext/libmspack/mspack/readhuff.h +173 -0
  63. data/ext/libmspack/mspack/sha.h +15 -0
  64. data/ext/libmspack/mspack/system.c +239 -0
  65. data/ext/libmspack/mspack/system.h +124 -0
  66. data/ext/libmspack/mspack/szdd.h +39 -0
  67. data/ext/libmspack/mspack/szddc.c +24 -0
  68. data/ext/libmspack/mspack/szddd.c +247 -0
  69. data/ext/libmspack/rebuild.sh +8 -0
  70. data/ext/libmspack/test/cabd_c10 +19 -0
  71. data/ext/libmspack/test/cabd_compare +34 -0
  72. data/ext/libmspack/test/cabd_md5.c +161 -0
  73. data/ext/libmspack/test/cabd_memory.c +179 -0
  74. data/ext/libmspack/test/cabd_test.c +386 -0
  75. data/ext/libmspack/test/cabrip.c +81 -0
  76. data/ext/libmspack/test/chmd_compare +38 -0
  77. data/ext/libmspack/test/chmd_find.c +95 -0
  78. data/ext/libmspack/test/chmd_md5.c +67 -0
  79. data/ext/libmspack/test/chmd_order.c +144 -0
  80. data/ext/libmspack/test/chminfo.c +284 -0
  81. data/ext/libmspack/test/chmx.c +216 -0
  82. data/ext/libmspack/test/error.h +22 -0
  83. data/ext/libmspack/test/expand.c +79 -0
  84. data/ext/libmspack/test/md5.c +457 -0
  85. data/ext/libmspack/test/md5.h +165 -0
  86. data/ext/libmspack/test/md5_fh.h +123 -0
  87. data/ext/libmspack/test/msdecompile_md5 +24 -0
  88. data/ext/libmspack/test/msexpand_md5 +39 -0
  89. data/ext/libmspack/test/multifh.c +435 -0
  90. data/ext/libmspack/test/oabx.c +41 -0
  91. data/ext/libmspack/test/test_files/cabd/1.pl +84 -0
  92. data/ext/libmspack/test/test_files/cabd/2.pl +75 -0
  93. data/ext/libmspack/test/test_files/cabd/bad_folderindex.cab +0 -0
  94. data/ext/libmspack/test/test_files/cabd/bad_nofiles.cab +0 -0
  95. data/ext/libmspack/test/test_files/cabd/bad_nofolders.cab +0 -0
  96. data/ext/libmspack/test/test_files/cabd/bad_signature.cab +0 -0
  97. data/ext/libmspack/test/test_files/cabd/multi_basic_pt1.cab +0 -0
  98. data/ext/libmspack/test/test_files/cabd/multi_basic_pt2.cab +0 -0
  99. data/ext/libmspack/test/test_files/cabd/multi_basic_pt3.cab +0 -0
  100. data/ext/libmspack/test/test_files/cabd/multi_basic_pt4.cab +0 -0
  101. data/ext/libmspack/test/test_files/cabd/multi_basic_pt5.cab +0 -0
  102. data/ext/libmspack/test/test_files/cabd/normal_255c_filename.cab +0 -0
  103. data/ext/libmspack/test/test_files/cabd/normal_2files_1folder.cab +0 -0
  104. data/ext/libmspack/test/test_files/cabd/partial_nodata.cab +0 -0
  105. data/ext/libmspack/test/test_files/cabd/partial_nofiles.cab +0 -0
  106. data/ext/libmspack/test/test_files/cabd/partial_nofolder.cab +0 -0
  107. data/ext/libmspack/test/test_files/cabd/partial_shortextheader.cab +0 -0
  108. data/ext/libmspack/test/test_files/cabd/partial_shortfile1.cab +0 -0
  109. data/ext/libmspack/test/test_files/cabd/partial_shortfile2.cab +0 -0
  110. data/ext/libmspack/test/test_files/cabd/partial_shortfolder.cab +0 -0
  111. data/ext/libmspack/test/test_files/cabd/partial_shortheader.cab +0 -0
  112. data/ext/libmspack/test/test_files/cabd/partial_str_nofname.cab +0 -0
  113. data/ext/libmspack/test/test_files/cabd/partial_str_noninfo.cab +0 -0
  114. data/ext/libmspack/test/test_files/cabd/partial_str_nonname.cab +0 -0
  115. data/ext/libmspack/test/test_files/cabd/partial_str_nopinfo.cab +0 -0
  116. data/ext/libmspack/test/test_files/cabd/partial_str_nopname.cab +0 -0
  117. data/ext/libmspack/test/test_files/cabd/partial_str_shortfname.cab +0 -0
  118. data/ext/libmspack/test/test_files/cabd/partial_str_shortninfo.cab +0 -0
  119. data/ext/libmspack/test/test_files/cabd/partial_str_shortnname.cab +0 -0
  120. data/ext/libmspack/test/test_files/cabd/partial_str_shortpinfo.cab +0 -0
  121. data/ext/libmspack/test/test_files/cabd/partial_str_shortpname.cab +0 -0
  122. data/ext/libmspack/test/test_files/cabd/reserve_---.cab +0 -0
  123. data/ext/libmspack/test/test_files/cabd/reserve_--D.cab +0 -0
  124. data/ext/libmspack/test/test_files/cabd/reserve_-F-.cab +0 -0
  125. data/ext/libmspack/test/test_files/cabd/reserve_-FD.cab +0 -0
  126. data/ext/libmspack/test/test_files/cabd/reserve_H--.cab +0 -0
  127. data/ext/libmspack/test/test_files/cabd/reserve_H-D.cab +0 -0
  128. data/ext/libmspack/test/test_files/cabd/reserve_HF-.cab +0 -0
  129. data/ext/libmspack/test/test_files/cabd/reserve_HFD.cab +0 -0
  130. data/ext/libmspack/test/test_files/cabd/search_basic.cab +0 -0
  131. data/ext/libmspack/test/test_files/cabd/search_tricky1.cab +0 -0
  132. data/ext/libmspack/winbuild.sh +26 -0
  133. data/ext/x86_64-windows/libmspack.dll +0 -0
  134. data/lib/libmspack/constants.rb +9 -0
  135. data/lib/libmspack/exceptions.rb +12 -0
  136. data/lib/libmspack/mscab.rb +722 -0
  137. data/lib/libmspack/mschm.rb +301 -0
  138. data/lib/libmspack/mshlp.rb +15 -0
  139. data/lib/libmspack/mskwaj.rb +124 -0
  140. data/lib/libmspack/mslit.rb +18 -0
  141. data/lib/libmspack/msoab.rb +36 -0
  142. data/lib/libmspack/mspack.rb +208 -0
  143. data/lib/libmspack/msszdd.rb +81 -0
  144. data/lib/libmspack/system.rb +84 -0
  145. data/lib/libmspack/version.rb +4 -0
  146. data/lib/libmspack.rb +121 -0
  147. data/libmspack.gemspec +33 -0
  148. data/spec/libmspack_spec.rb +26 -0
  149. data/spec/spec_helper.rb +5 -0
  150. metadata +309 -0
@@ -0,0 +1,561 @@
1
+ /* This file is part of libmspack.
2
+ * (C) 2003-2011 Stuart Caie.
3
+ *
4
+ * KWAJ is a format very similar to SZDD. KWAJ method 3 (LZH) was
5
+ * written by Jeff Johnson.
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
+ /* KWAJ decompression implementation */
14
+
15
+ #include <system.h>
16
+ #include <kwaj.h>
17
+ #include <mszip.h>
18
+
19
+ /* prototypes */
20
+ static struct mskwajd_header *kwajd_open(
21
+ struct mskwaj_decompressor *base, const char *filename);
22
+ static void kwajd_close(
23
+ struct mskwaj_decompressor *base, struct mskwajd_header *hdr);
24
+ static int kwajd_read_headers(
25
+ struct mspack_system *sys, struct mspack_file *fh,
26
+ struct mskwajd_header *hdr);
27
+ static int kwajd_extract(
28
+ struct mskwaj_decompressor *base, struct mskwajd_header *hdr,
29
+ const char *filename);
30
+ static int kwajd_decompress(
31
+ struct mskwaj_decompressor *base, const char *input, const char *output);
32
+ static int kwajd_error(
33
+ struct mskwaj_decompressor *base);
34
+
35
+ static struct kwajd_stream *lzh_init(
36
+ struct mspack_system *sys, struct mspack_file *in, struct mspack_file *out);
37
+ static int lzh_decompress(
38
+ struct kwajd_stream *kwaj);
39
+ static void lzh_free(
40
+ struct kwajd_stream *kwaj);
41
+ static int lzh_read_lens(
42
+ struct kwajd_stream *kwaj,
43
+ unsigned int type, unsigned int numsyms,
44
+ unsigned char *lens, unsigned short *table);
45
+ static int lzh_read_input(
46
+ struct kwajd_stream *kwaj);
47
+
48
+
49
+ /***************************************
50
+ * MSPACK_CREATE_KWAJ_DECOMPRESSOR
51
+ ***************************************
52
+ * constructor
53
+ */
54
+ struct mskwaj_decompressor *
55
+ mspack_create_kwaj_decompressor(struct mspack_system *sys)
56
+ {
57
+ struct mskwaj_decompressor_p *self = NULL;
58
+
59
+ if (!sys) sys = mspack_default_system;
60
+ if (!mspack_valid_system(sys)) return NULL;
61
+
62
+ if ((self = (struct mskwaj_decompressor_p *) sys->alloc(sys, sizeof(struct mskwaj_decompressor_p)))) {
63
+ self->base.open = &kwajd_open;
64
+ self->base.close = &kwajd_close;
65
+ self->base.extract = &kwajd_extract;
66
+ self->base.decompress = &kwajd_decompress;
67
+ self->base.last_error = &kwajd_error;
68
+ self->system = sys;
69
+ self->error = MSPACK_ERR_OK;
70
+ }
71
+ return (struct mskwaj_decompressor *) self;
72
+ }
73
+
74
+ /***************************************
75
+ * MSPACK_DESTROY_KWAJ_DECOMPRESSOR
76
+ ***************************************
77
+ * destructor
78
+ */
79
+ void mspack_destroy_kwaj_decompressor(struct mskwaj_decompressor *base)
80
+ {
81
+ struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
82
+ if (self) {
83
+ struct mspack_system *sys = self->system;
84
+ sys->free(self);
85
+ }
86
+ }
87
+
88
+ /***************************************
89
+ * KWAJD_OPEN
90
+ ***************************************
91
+ * opens a KWAJ file without decompressing, reads header
92
+ */
93
+ static struct mskwajd_header *kwajd_open(struct mskwaj_decompressor *base,
94
+ const char *filename)
95
+ {
96
+ struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
97
+ struct mskwajd_header *hdr;
98
+ struct mspack_system *sys;
99
+ struct mspack_file *fh;
100
+
101
+ if (!self) return NULL;
102
+ sys = self->system;
103
+
104
+ fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ);
105
+ hdr = (struct mskwajd_header *) sys->alloc(sys, sizeof(struct mskwajd_header_p));
106
+ if (fh && hdr) {
107
+ ((struct mskwajd_header_p *) hdr)->fh = fh;
108
+ self->error = kwajd_read_headers(sys, fh, hdr);
109
+ }
110
+ else {
111
+ if (!fh) self->error = MSPACK_ERR_OPEN;
112
+ if (!hdr) self->error = MSPACK_ERR_NOMEMORY;
113
+ }
114
+
115
+ if (self->error) {
116
+ if (fh) sys->close(fh);
117
+ if (hdr) sys->free(hdr);
118
+ hdr = NULL;
119
+ }
120
+
121
+ return hdr;
122
+ }
123
+
124
+ /***************************************
125
+ * KWAJD_CLOSE
126
+ ***************************************
127
+ * closes a KWAJ file
128
+ */
129
+ static void kwajd_close(struct mskwaj_decompressor *base,
130
+ struct mskwajd_header *hdr)
131
+ {
132
+ struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
133
+ struct mskwajd_header_p *hdr_p = (struct mskwajd_header_p *) hdr;
134
+
135
+ if (!self || !self->system) return;
136
+
137
+ /* close the file handle associated */
138
+ self->system->close(hdr_p->fh);
139
+
140
+ /* free the memory associated */
141
+ self->system->free(hdr);
142
+
143
+ self->error = MSPACK_ERR_OK;
144
+ }
145
+
146
+ /***************************************
147
+ * KWAJD_READ_HEADERS
148
+ ***************************************
149
+ * reads the headers of a KWAJ format file
150
+ */
151
+ static int kwajd_read_headers(struct mspack_system *sys,
152
+ struct mspack_file *fh,
153
+ struct mskwajd_header *hdr)
154
+ {
155
+ unsigned char buf[16];
156
+ int i;
157
+
158
+ /* read in the header */
159
+ if (sys->read(fh, &buf[0], kwajh_SIZEOF) != kwajh_SIZEOF) {
160
+ return MSPACK_ERR_READ;
161
+ }
162
+
163
+ /* check for "KWAJ" signature */
164
+ if (((unsigned int) EndGetI32(&buf[kwajh_Signature1]) != 0x4A41574B) ||
165
+ ((unsigned int) EndGetI32(&buf[kwajh_Signature2]) != 0xD127F088))
166
+ {
167
+ return MSPACK_ERR_SIGNATURE;
168
+ }
169
+
170
+ /* basic header fields */
171
+ hdr->comp_type = EndGetI16(&buf[kwajh_CompMethod]);
172
+ hdr->data_offset = EndGetI16(&buf[kwajh_DataOffset]);
173
+ hdr->headers = EndGetI16(&buf[kwajh_Flags]);
174
+ hdr->length = 0;
175
+ hdr->filename = NULL;
176
+ hdr->extra = NULL;
177
+ hdr->extra_length = 0;
178
+
179
+ /* optional headers */
180
+
181
+ /* 4 bytes: length of unpacked file */
182
+ if (hdr->headers & MSKWAJ_HDR_HASLENGTH) {
183
+ if (sys->read(fh, &buf[0], 4) != 4) return MSPACK_ERR_READ;
184
+ hdr->length = EndGetI32(&buf[0]);
185
+ }
186
+
187
+ /* 2 bytes: unknown purpose */
188
+ if (hdr->headers & MSKWAJ_HDR_HASUNKNOWN1) {
189
+ if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ;
190
+ }
191
+
192
+ /* 2 bytes: length of section, then [length] bytes: unknown purpose */
193
+ if (hdr->headers & MSKWAJ_HDR_HASUNKNOWN2) {
194
+ if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ;
195
+ i = EndGetI16(&buf[0]);
196
+ if (sys->seek(fh, (off_t)i, MSPACK_SYS_SEEK_CUR)) return MSPACK_ERR_SEEK;
197
+ }
198
+
199
+ /* filename and extension */
200
+ if (hdr->headers & (MSKWAJ_HDR_HASFILENAME | MSKWAJ_HDR_HASFILEEXT)) {
201
+ off_t pos = sys->tell(fh);
202
+ char *fn = (char *) sys->alloc(sys, (size_t) 13);
203
+
204
+ /* allocate memory for maximum length filename */
205
+ if (! fn) return MSPACK_ERR_NOMEMORY;
206
+ hdr->filename = fn;
207
+
208
+ /* copy filename if present */
209
+ if (hdr->headers & MSKWAJ_HDR_HASFILENAME) {
210
+ if (sys->read(fh, &buf[0], 9) != 9) return MSPACK_ERR_READ;
211
+ for (i = 0; i < 9; i++, fn++) if (!(*fn = buf[i])) break;
212
+ pos += (i < 9) ? i+1 : 9;
213
+ if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START))
214
+ return MSPACK_ERR_SEEK;
215
+ }
216
+
217
+ /* copy extension if present */
218
+ if (hdr->headers & MSKWAJ_HDR_HASFILEEXT) {
219
+ *fn++ = '.';
220
+ if (sys->read(fh, &buf[0], 4) != 4) return MSPACK_ERR_READ;
221
+ for (i = 0; i < 4; i++, fn++) if (!(*fn = buf[i])) break;
222
+ pos += (i < 4) ? i+1 : 4;
223
+ if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START))
224
+ return MSPACK_ERR_SEEK;
225
+ }
226
+ *fn = '\0';
227
+ }
228
+
229
+ /* 2 bytes: extra text length then [length] bytes of extra text data */
230
+ if (hdr->headers & MSKWAJ_HDR_HASEXTRATEXT) {
231
+ if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ;
232
+ i = EndGetI16(&buf[0]);
233
+ hdr->extra = (char *) sys->alloc(sys, (size_t)i+1);
234
+ if (! hdr->extra) return MSPACK_ERR_NOMEMORY;
235
+ if (sys->read(fh, hdr->extra, i) != i) return MSPACK_ERR_READ;
236
+ hdr->extra[i] = '\0';
237
+ hdr->extra_length = i;
238
+ }
239
+ return MSPACK_ERR_OK;
240
+ }
241
+
242
+ /***************************************
243
+ * KWAJD_EXTRACT
244
+ ***************************************
245
+ * decompresses a KWAJ file
246
+ */
247
+ static int kwajd_extract(struct mskwaj_decompressor *base,
248
+ struct mskwajd_header *hdr, const char *filename)
249
+ {
250
+ struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
251
+ struct mspack_system *sys;
252
+ struct mspack_file *fh, *outfh;
253
+
254
+ if (!self) return MSPACK_ERR_ARGS;
255
+ if (!hdr) return self->error = MSPACK_ERR_ARGS;
256
+
257
+ sys = self->system;
258
+ fh = ((struct mskwajd_header_p *) hdr)->fh;
259
+
260
+ /* seek to the compressed data */
261
+ if (sys->seek(fh, hdr->data_offset, MSPACK_SYS_SEEK_START)) {
262
+ return self->error = MSPACK_ERR_SEEK;
263
+ }
264
+
265
+ /* open file for output */
266
+ if (!(outfh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) {
267
+ return self->error = MSPACK_ERR_OPEN;
268
+ }
269
+
270
+ self->error = MSPACK_ERR_OK;
271
+
272
+ /* decompress based on format */
273
+ if (hdr->comp_type == MSKWAJ_COMP_NONE ||
274
+ hdr->comp_type == MSKWAJ_COMP_XOR)
275
+ {
276
+ /* NONE is a straight copy. XOR is a copy xored with 0xFF */
277
+ unsigned char *buf = (unsigned char *) sys->alloc(sys, (size_t) KWAJ_INPUT_SIZE);
278
+ if (buf) {
279
+ int read, i;
280
+ while ((read = sys->read(fh, buf, KWAJ_INPUT_SIZE)) > 0) {
281
+ if (hdr->comp_type == MSKWAJ_COMP_XOR) {
282
+ for (i = 0; i < read; i++) buf[i] ^= 0xFF;
283
+ }
284
+ if (sys->write(outfh, buf, read) != read) {
285
+ self->error = MSPACK_ERR_WRITE;
286
+ break;
287
+ }
288
+ }
289
+ if (read < 0) self->error = MSPACK_ERR_READ;
290
+ sys->free(buf);
291
+ }
292
+ else {
293
+ self->error = MSPACK_ERR_NOMEMORY;
294
+ }
295
+ }
296
+ else if (hdr->comp_type == MSKWAJ_COMP_SZDD) {
297
+ self->error = lzss_decompress(sys, fh, outfh, KWAJ_INPUT_SIZE,
298
+ LZSS_MODE_EXPAND);
299
+ }
300
+ else if (hdr->comp_type == MSKWAJ_COMP_LZH) {
301
+ struct kwajd_stream *lzh = lzh_init(sys, fh, outfh);
302
+ self->error = (lzh) ? lzh_decompress(lzh) : MSPACK_ERR_NOMEMORY;
303
+ lzh_free(lzh);
304
+ }
305
+ else if (hdr->comp_type == MSKWAJ_COMP_MSZIP) {
306
+ struct mszipd_stream *zip = mszipd_init(sys,fh,outfh,KWAJ_INPUT_SIZE,0);
307
+ self->error = (zip) ? mszipd_decompress_kwaj(zip) : MSPACK_ERR_NOMEMORY;
308
+ mszipd_free(zip);
309
+ }
310
+ else {
311
+ self->error = MSPACK_ERR_DATAFORMAT;
312
+ }
313
+
314
+ /* close output file */
315
+ sys->close(outfh);
316
+
317
+ return self->error;
318
+ }
319
+
320
+ /***************************************
321
+ * KWAJD_DECOMPRESS
322
+ ***************************************
323
+ * unpacks directly from input to output
324
+ */
325
+ static int kwajd_decompress(struct mskwaj_decompressor *base,
326
+ const char *input, const char *output)
327
+ {
328
+ struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
329
+ struct mskwajd_header *hdr;
330
+ int error;
331
+
332
+ if (!self) return MSPACK_ERR_ARGS;
333
+
334
+ if (!(hdr = kwajd_open(base, input))) return self->error;
335
+ error = kwajd_extract(base, hdr, output);
336
+ kwajd_close(base, hdr);
337
+ return self->error = error;
338
+ }
339
+
340
+ /***************************************
341
+ * KWAJD_ERROR
342
+ ***************************************
343
+ * returns the last error that occurred
344
+ */
345
+ static int kwajd_error(struct mskwaj_decompressor *base)
346
+ {
347
+ struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
348
+ return (self) ? self->error : MSPACK_ERR_ARGS;
349
+ }
350
+
351
+ /***************************************
352
+ * LZH_INIT, LZH_DECOMPRESS, LZH_FREE
353
+ ***************************************
354
+ * unpacks KWAJ method 3 files
355
+ */
356
+
357
+ /* import bit-reading macros and code */
358
+ #define BITS_TYPE struct kwajd_stream
359
+ #define BITS_VAR lzh
360
+ #define BITS_ORDER_MSB
361
+ #define BITS_NO_READ_INPUT
362
+ #define READ_BYTES do { \
363
+ if (i_ptr >= i_end) { \
364
+ if ((err = lzh_read_input(lzh))) return err; \
365
+ i_ptr = lzh->i_ptr; \
366
+ i_end = lzh->i_end; \
367
+ } \
368
+ INJECT_BITS(*i_ptr++, 8); \
369
+ } while (0)
370
+ #include <readbits.h>
371
+
372
+ /* import huffman-reading macros and code */
373
+ #define TABLEBITS(tbl) KWAJ_TABLEBITS
374
+ #define MAXSYMBOLS(tbl) KWAJ_##tbl##_SYMS
375
+ #define HUFF_TABLE(tbl,idx) lzh->tbl##_table[idx]
376
+ #define HUFF_LEN(tbl,idx) lzh->tbl##_len[idx]
377
+ #define HUFF_ERROR return MSPACK_ERR_DATAFORMAT
378
+ #include <readhuff.h>
379
+
380
+ /* In the KWAJ LZH format, there is no special 'eof' marker, it just
381
+ * ends. Depending on how many bits are left in the final byte when
382
+ * the stream ends, that might be enough to start another literal or
383
+ * match. The only easy way to detect that we've come to an end is to
384
+ * guard all bit-reading. We allow fake bits to be read once we reach
385
+ * the end of the stream, but we check if we then consumed any of
386
+ * those fake bits, after doing the READ_BITS / READ_HUFFSYM. This
387
+ * isn't how the default readbits.h read_input() works (it simply lets
388
+ * 2 fake bytes in then stops), so we implement our own.
389
+ */
390
+ #define READ_BITS_SAFE(val, n) do { \
391
+ READ_BITS(val, n); \
392
+ if (lzh->input_end && bits_left < lzh->input_end) \
393
+ return MSPACK_ERR_OK; \
394
+ } while (0)
395
+
396
+ #define READ_HUFFSYM_SAFE(tbl, val) do { \
397
+ READ_HUFFSYM(tbl, val); \
398
+ if (lzh->input_end && bits_left < lzh->input_end) \
399
+ return MSPACK_ERR_OK; \
400
+ } while (0)
401
+
402
+ #define BUILD_TREE(tbl, type) \
403
+ STORE_BITS; \
404
+ err = lzh_read_lens(lzh, type, MAXSYMBOLS(tbl), \
405
+ &HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0)); \
406
+ if (err) return err; \
407
+ RESTORE_BITS; \
408
+ if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl), \
409
+ &HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0))) \
410
+ return MSPACK_ERR_DATAFORMAT;
411
+
412
+ #define WRITE_BYTE do { \
413
+ if (lzh->sys->write(lzh->output, &lzh->window[pos], 1) != 1) \
414
+ return MSPACK_ERR_WRITE; \
415
+ } while (0)
416
+
417
+ static struct kwajd_stream *lzh_init(struct mspack_system *sys,
418
+ struct mspack_file *in, struct mspack_file *out)
419
+ {
420
+ struct kwajd_stream *lzh;
421
+
422
+ if (!sys || !in || !out) return NULL;
423
+ if (!(lzh = (struct kwajd_stream *) sys->alloc(sys, sizeof(struct kwajd_stream)))) return NULL;
424
+
425
+ lzh->sys = sys;
426
+ lzh->input = in;
427
+ lzh->output = out;
428
+ return lzh;
429
+ }
430
+
431
+ static int lzh_decompress(struct kwajd_stream *lzh)
432
+ {
433
+ register unsigned int bit_buffer;
434
+ register int bits_left, i;
435
+ register unsigned short sym;
436
+ unsigned char *i_ptr, *i_end, lit_run = 0;
437
+ int j, pos = 0, len, offset, err;
438
+ unsigned int types[6];
439
+
440
+ /* reset global state */
441
+ INIT_BITS;
442
+ RESTORE_BITS;
443
+ memset(&lzh->window[0], LZSS_WINDOW_FILL, (size_t) LZSS_WINDOW_SIZE);
444
+
445
+ /* read 6 encoding types (for byte alignment) but only 5 are needed */
446
+ for (i = 0; i < 6; i++) READ_BITS_SAFE(types[i], 4);
447
+
448
+ /* read huffman table symbol lengths and build huffman trees */
449
+ BUILD_TREE(MATCHLEN1, types[0]);
450
+ BUILD_TREE(MATCHLEN2, types[1]);
451
+ BUILD_TREE(LITLEN, types[2]);
452
+ BUILD_TREE(OFFSET, types[3]);
453
+ BUILD_TREE(LITERAL, types[4]);
454
+
455
+ while (!lzh->input_end) {
456
+ if (lit_run) READ_HUFFSYM_SAFE(MATCHLEN2, len);
457
+ else READ_HUFFSYM_SAFE(MATCHLEN1, len);
458
+
459
+ if (len > 0) {
460
+ len += 2;
461
+ lit_run = 0; /* not the end of a literal run */
462
+ READ_HUFFSYM_SAFE(OFFSET, j); offset = j << 6;
463
+ READ_BITS_SAFE(j, 6); offset |= j;
464
+
465
+ /* copy match as output and into the ring buffer */
466
+ while (len-- > 0) {
467
+ lzh->window[pos] = lzh->window[(pos+4096-offset) & 4095];
468
+ WRITE_BYTE;
469
+ pos++; pos &= 4095;
470
+ }
471
+ }
472
+ else {
473
+ READ_HUFFSYM_SAFE(LITLEN, len); len++;
474
+ lit_run = (len == 32) ? 0 : 1; /* end of a literal run? */
475
+ while (len-- > 0) {
476
+ READ_HUFFSYM_SAFE(LITERAL, j);
477
+ /* copy as output and into the ring buffer */
478
+ lzh->window[pos] = j;
479
+ WRITE_BYTE;
480
+ pos++; pos &= 4095;
481
+ }
482
+ }
483
+ }
484
+ return MSPACK_ERR_OK;
485
+ }
486
+
487
+ static void lzh_free(struct kwajd_stream *lzh)
488
+ {
489
+ struct mspack_system *sys;
490
+ if (!lzh || !lzh->sys) return;
491
+ sys = lzh->sys;
492
+ sys->free(lzh);
493
+ }
494
+
495
+ static int lzh_read_lens(struct kwajd_stream *lzh,
496
+ unsigned int type, unsigned int numsyms,
497
+ unsigned char *lens, unsigned short *table)
498
+ {
499
+ register unsigned int bit_buffer;
500
+ register int bits_left;
501
+ unsigned char *i_ptr, *i_end;
502
+ unsigned int i, c, sel;
503
+ int err;
504
+
505
+ RESTORE_BITS;
506
+ switch (type) {
507
+ case 0:
508
+ i = numsyms; c = (i==16)?4: (i==32)?5: (i==64)?6: (i==256)?8 :0;
509
+ for (i = 0; i < numsyms; i++) lens[i] = c;
510
+ break;
511
+
512
+ case 1:
513
+ READ_BITS_SAFE(c, 4); lens[0] = c;
514
+ for (i = 1; i < numsyms; i++) {
515
+ READ_BITS_SAFE(sel, 1); if (sel == 0) lens[i] = c;
516
+ else { READ_BITS_SAFE(sel, 1); if (sel == 0) lens[i] = ++c;
517
+ else { READ_BITS_SAFE(c, 4); lens[i] = c; }}
518
+ }
519
+ break;
520
+
521
+ case 2:
522
+ READ_BITS_SAFE(c, 4); lens[0] = c;
523
+ for (i = 1; i < numsyms; i++) {
524
+ READ_BITS_SAFE(sel, 2);
525
+ if (sel == 3) READ_BITS_SAFE(c, 4); else c += (char) sel-1;
526
+ lens[i] = c;
527
+ }
528
+ break;
529
+
530
+ case 3:
531
+ for (i = 0; i < numsyms; i++) {
532
+ READ_BITS_SAFE(c, 4); lens[i] = c;
533
+ }
534
+ break;
535
+ }
536
+ STORE_BITS;
537
+ return MSPACK_ERR_OK;
538
+ }
539
+
540
+ static int lzh_read_input(struct kwajd_stream *lzh) {
541
+ int read;
542
+ if (lzh->input_end) {
543
+ lzh->input_end += 8;
544
+ lzh->inbuf[0] = 0;
545
+ read = 1;
546
+ }
547
+ else {
548
+ read = lzh->sys->read(lzh->input, &lzh->inbuf[0], KWAJ_INPUT_SIZE);
549
+ if (read < 0) return MSPACK_ERR_READ;
550
+ if (read == 0) {
551
+ lzh->input_end = 8;
552
+ lzh->inbuf[0] = 0;
553
+ read = 1;
554
+ }
555
+ }
556
+
557
+ /* update i_ptr and i_end */
558
+ lzh->i_ptr = &lzh->inbuf[0];
559
+ lzh->i_end = &lzh->inbuf[read];
560
+ return MSPACK_ERR_OK;
561
+ }
@@ -0,0 +1,35 @@
1
+ /* This file is part of libmspack.
2
+ * (C) 2003-2004 Stuart Caie.
3
+ *
4
+ * libmspack is free software; you can redistribute it and/or modify it under
5
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
6
+ *
7
+ * For further details, see the file COPYING.LIB distributed with libmspack
8
+ */
9
+
10
+ #ifndef MSPACK_LIT_H
11
+ #define MSPACK_LIT_H 1
12
+
13
+ #include <lzx.h>
14
+ #include <des.h>
15
+ #include <sha.h>
16
+
17
+ /* generic LIT definitions */
18
+
19
+ /* LIT compression definitions */
20
+
21
+ struct mslit_compressor_p {
22
+ struct mslit_compressor base;
23
+ struct mspack_system *system;
24
+ /* todo */
25
+ };
26
+
27
+ /* LIT decompression definitions */
28
+
29
+ struct mslit_decompressor_p {
30
+ struct mslit_decompressor base;
31
+ struct mspack_system *system;
32
+ /* todo */
33
+ };
34
+
35
+ #endif
@@ -0,0 +1,24 @@
1
+ /* This file is part of libmspack.
2
+ * (C) 2003-2004 Stuart Caie.
3
+ *
4
+ * libmspack is free software; you can redistribute it and/or modify it under
5
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
6
+ *
7
+ * For further details, see the file COPYING.LIB distributed with libmspack
8
+ */
9
+
10
+ /* LIT compression implementation */
11
+
12
+ #include <system.h>
13
+ #include <lit.h>
14
+
15
+ struct mslit_compressor *
16
+ mspack_create_lit_compressor(struct mspack_system *sys)
17
+ {
18
+ /* todo */
19
+ return NULL;
20
+ }
21
+
22
+ void mspack_destroy_lit_compressor(struct mslit_compressor *self) {
23
+ /* todo */
24
+ }
@@ -0,0 +1,24 @@
1
+ /* This file is part of libmspack.
2
+ * (C) 2003-2004 Stuart Caie.
3
+ *
4
+ * libmspack is free software; you can redistribute it and/or modify it under
5
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
6
+ *
7
+ * For further details, see the file COPYING.LIB distributed with libmspack
8
+ */
9
+
10
+ /* LIT decompression implementation */
11
+
12
+ #include <system.h>
13
+ #include <lit.h>
14
+
15
+ struct mslit_decompressor *
16
+ mspack_create_lit_decompressor(struct mspack_system *sys)
17
+ {
18
+ /* todo */
19
+ return NULL;
20
+ }
21
+
22
+ void mspack_destroy_lit_decompressor(struct mslit_decompressor *self) {
23
+ /* todo */
24
+ }
@@ -0,0 +1,66 @@
1
+ /* This file is part of libmspack.
2
+ * (C) 2003-2004 Stuart Caie.
3
+ *
4
+ * libmspack is free software; you can redistribute it and/or modify it under
5
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
6
+ *
7
+ * For further details, see the file COPYING.LIB distributed with libmspack
8
+ */
9
+
10
+ #ifndef MSPACK_LZSS_H
11
+ #define MSPACK_LZSS_H 1
12
+
13
+ #ifdef __cplusplus
14
+ extern "C" {
15
+ #endif
16
+
17
+ /* LZSS compression / decompression definitions */
18
+
19
+ #define LZSS_WINDOW_SIZE (4096)
20
+ #define LZSS_WINDOW_FILL (0x20)
21
+
22
+ #define LZSS_MODE_EXPAND (0)
23
+ #define LZSS_MODE_MSHELP (1)
24
+ #define LZSS_MODE_QBASIC (2)
25
+
26
+ /**
27
+ * Decompresses an LZSS stream.
28
+ *
29
+ * Input bytes will be read in as necessary using the system->read()
30
+ * function with the input file handle given. This will continue until
31
+ * system->read() returns 0 bytes, or an error. Errors will be passed
32
+ * out of the function as MSPACK_ERR_READ errors. Input streams should
33
+ * convey an "end of input stream" by refusing to supply all the bytes
34
+ * that LZSS asks for when they reach the end of the stream, rather
35
+ * than return an error code.
36
+ *
37
+ * Output bytes will be passed to the system->write() function, using
38
+ * the output file handle given. More than one call may be made to
39
+ * system->write().
40
+ *
41
+ * As EXPAND.EXE (SZDD/KWAJ), Microsoft Help and QBasic have slightly
42
+ * different encodings for the control byte and matches, a "mode"
43
+ * parameter is allowed, to choose the encoding.
44
+ *
45
+ * @param system an mspack_system structure used to read from
46
+ * the input stream and write to the output
47
+ * stream, also to allocate and free memory.
48
+ * @param input an input stream with the LZSS data.
49
+ * @param output an output stream to write the decoded data to.
50
+ * @param input_buffer_size the number of bytes to use as an input
51
+ * bitstream buffer.
52
+ * @param mode one of #LZSS_MODE_EXPAND, #LZSS_MODE_MSHELP or
53
+ * #LZSS_MODE_QBASIC
54
+ * @return an error code, or MSPACK_ERR_OK if successful
55
+ */
56
+ extern int lzss_decompress(struct mspack_system *system,
57
+ struct mspack_file *input,
58
+ struct mspack_file *output,
59
+ int input_buffer_size,
60
+ int mode);
61
+
62
+ #ifdef __cplusplus
63
+ }
64
+ #endif
65
+
66
+ #endif