1 | var Buffer = require("buffer").Buffer;
|
2 |
|
3 | function JSInflater(/*Buffer*/input) {
|
4 |
|
5 | var WSIZE = 0x8000,
|
6 | slide = new Buffer(0x10000),
|
7 | windowPos = 0,
|
8 | fixedTableList = null,
|
9 | fixedTableDist,
|
10 | fixedLookup,
|
11 | bitBuf = 0,
|
12 | bitLen = 0,
|
13 | method = -1,
|
14 | eof = false,
|
15 | copyLen = 0,
|
16 | copyDist = 0,
|
17 | tblList, tblDist, bitList, bitdist,
|
18 |
|
19 | inputPosition = 0,
|
20 |
|
21 | MASK_BITS = [0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff],
|
22 | LENS = [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],
|
23 | LEXT = [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, 99, 99],
|
24 | DISTS = [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],
|
25 | DEXT = [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],
|
26 | BITORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
|
27 |
|
28 | function HuffTable(clen, cnum, cval, blist, elist, lookupm) {
|
29 |
|
30 | this.status = 0;
|
31 | this.root = null;
|
32 | this.maxbit = 0;
|
33 |
|
34 | var el, f, tail,
|
35 | offsets = [],
|
36 | countTbl = [],
|
37 | sTbl = [],
|
38 | values = [],
|
39 | tentry = {extra: 0, bitcnt: 0, lbase: 0, next: null};
|
40 |
|
41 | tail = this.root = null;
|
42 | for(var i = 0; i < 0x11; i++) { countTbl[i] = 0; sTbl[i] = 0; offsets[i] = 0; }
|
43 | for(i = 0; i < 0x120; i++) values[i] = 0;
|
44 |
|
45 | el = cnum > 256 ? clen[256] : 16;
|
46 |
|
47 | var pidx = -1;
|
48 | while (++pidx < cnum) countTbl[clen[pidx]]++;
|
49 |
|
50 | if(countTbl[0] == cnum) return;
|
51 |
|
52 | for(var j = 1; j <= 16; j++) if(countTbl[j] != 0) break;
|
53 | var bitLen = j;
|
54 | for(i = 16; i != 0; i--) if(countTbl[i] != 0) break;
|
55 | var maxLen = i;
|
56 |
|
57 | lookupm < j && (lookupm = j);
|
58 |
|
59 | var dCodes = 1 << j;
|
60 | for(; j < i; j++, dCodes <<= 1)
|
61 | if((dCodes -= countTbl[j]) < 0) {
|
62 | this.status = 2;
|
63 | this.maxbit = lookupm;
|
64 | return;
|
65 | }
|
66 |
|
67 | if((dCodes -= countTbl[i]) < 0) {
|
68 | this.status = 2;
|
69 | this.maxbit = lookupm;
|
70 | return;
|
71 | }
|
72 |
|
73 | countTbl[i] += dCodes;
|
74 | offsets[1] = j = 0;
|
75 | pidx = 1;
|
76 | var xp = 2;
|
77 | while(--i > 0) offsets[xp++] = (j += countTbl[pidx++]);
|
78 | pidx = 0;
|
79 | i = 0;
|
80 | do {
|
81 | (j = clen[pidx++]) && (values[offsets[j]++] = i);
|
82 | } while(++i < cnum);
|
83 | cnum = offsets[maxLen];
|
84 | offsets[0] = i = 0;
|
85 | pidx = 0;
|
86 |
|
87 | var level = -1,
|
88 | w = sTbl[0] = 0,
|
89 | cnode = null,
|
90 | tblCnt = 0,
|
91 | tblStack = [];
|
92 |
|
93 | for(; bitLen <= maxLen; bitLen++) {
|
94 | var kccnt = countTbl[bitLen];
|
95 | while(kccnt-- > 0) {
|
96 | while(bitLen > w + sTbl[1 + level]) {
|
97 | w += sTbl[1 + level];
|
98 | level++;
|
99 | tblCnt = (tblCnt = maxLen - w) > lookupm ? lookupm : tblCnt;
|
100 | if((f = 1 << (j = bitLen - w)) > kccnt + 1) {
|
101 | f -= kccnt + 1;
|
102 | xp = bitLen;
|
103 | while(++j < tblCnt) {
|
104 | if((f <<= 1) <= countTbl[++xp]) break;
|
105 | f -= countTbl[xp];
|
106 | }
|
107 | }
|
108 | if(w + j > el && w < el) j = el - w;
|
109 | tblCnt = 1 << j;
|
110 | sTbl[1 + level] = j;
|
111 | cnode = [];
|
112 | while (cnode.length < tblCnt) cnode.push({extra: 0, bitcnt: 0, lbase: 0, next: null});
|
113 | if (tail == null) {
|
114 | tail = this.root = {next:null, list:null};
|
115 | } else {
|
116 | tail = tail.next = {next:null, list:null}
|
117 | }
|
118 | tail.next = null;
|
119 | tail.list = cnode;
|
120 |
|
121 | tblStack[level] = cnode;
|
122 |
|
123 | if(level > 0) {
|
124 | offsets[level] = i;
|
125 | tentry.bitcnt = sTbl[level];
|
126 | tentry.extra = 16 + j;
|
127 | tentry.next = cnode;
|
128 | j = (i & ((1 << w) - 1)) >> (w - sTbl[level]);
|
129 |
|
130 | tblStack[level-1][j].extra = tentry.extra;
|
131 | tblStack[level-1][j].bitcnt = tentry.bitcnt;
|
132 | tblStack[level-1][j].lbase = tentry.lbase;
|
133 | tblStack[level-1][j].next = tentry.next;
|
134 | }
|
135 | }
|
136 | tentry.bitcnt = bitLen - w;
|
137 | if(pidx >= cnum)
|
138 | tentry.extra = 99;
|
139 | else if(values[pidx] < cval) {
|
140 | tentry.extra = (values[pidx] < 256 ? 16 : 15);
|
141 | tentry.lbase = values[pidx++];
|
142 | } else {
|
143 | tentry.extra = elist[values[pidx] - cval];
|
144 | tentry.lbase = blist[values[pidx++] - cval];
|
145 | }
|
146 |
|
147 | f = 1 << (bitLen - w);
|
148 | for(j = i >> w; j < tblCnt; j += f) {
|
149 | cnode[j].extra = tentry.extra;
|
150 | cnode[j].bitcnt = tentry.bitcnt;
|
151 | cnode[j].lbase = tentry.lbase;
|
152 | cnode[j].next = tentry.next;
|
153 | }
|
154 | for(j = 1 << (bitLen - 1); (i & j) != 0; j >>= 1)
|
155 | i ^= j;
|
156 | i ^= j;
|
157 | while((i & ((1 << w) - 1)) != offsets[level]) {
|
158 | w -= sTbl[level];
|
159 | level--;
|
160 | }
|
161 | }
|
162 | }
|
163 |
|
164 | this.maxbit = sTbl[1];
|
165 | this.status = ((dCodes != 0 && maxLen != 1) ? 1 : 0);
|
166 | }
|
167 |
|
168 | function addBits(n) {
|
169 | while(bitLen < n) {
|
170 | bitBuf |= input[inputPosition++] << bitLen;
|
171 | bitLen += 8;
|
172 | }
|
173 | return bitBuf;
|
174 | }
|
175 |
|
176 | function cutBits(n) {
|
177 | bitLen -= n;
|
178 | return bitBuf >>= n;
|
179 | }
|
180 |
|
181 | function maskBits(n) {
|
182 | while(bitLen < n) {
|
183 | bitBuf |= input[inputPosition++] << bitLen;
|
184 | bitLen += 8;
|
185 | }
|
186 | var res = bitBuf & MASK_BITS[n];
|
187 | bitBuf >>= n;
|
188 | bitLen -= n;
|
189 | return res;
|
190 | }
|
191 |
|
192 | function codes(buff, off, size) {
|
193 | var e, t;
|
194 | if(size == 0) return 0;
|
195 |
|
196 | var n = 0;
|
197 | for(;;) {
|
198 | t = tblList.list[addBits(bitList) & MASK_BITS[bitList]];
|
199 | e = t.extra;
|
200 | while(e > 16) {
|
201 | if(e == 99) return -1;
|
202 | cutBits(t.bitcnt);
|
203 | e -= 16;
|
204 | t = t.next[addBits(e) & MASK_BITS[e]];
|
205 | e = t.extra;
|
206 | }
|
207 | cutBits(t.bitcnt);
|
208 | if(e == 16) {
|
209 | windowPos &= WSIZE - 1;
|
210 | buff[off + n++] = slide[windowPos++] = t.lbase;
|
211 | if(n == size) return size;
|
212 | continue;
|
213 | }
|
214 | if(e == 15) break;
|
215 |
|
216 | copyLen = t.lbase + maskBits(e);
|
217 | t = tblDist.list[addBits(bitdist) & MASK_BITS[bitdist]];
|
218 | e = t.extra;
|
219 |
|
220 | while(e > 16) {
|
221 | if(e == 99) return -1;
|
222 | cutBits(t.bitcnt);
|
223 | e -= 16;
|
224 | t = t.next[addBits(e) & MASK_BITS[e]];
|
225 | e = t.extra
|
226 | }
|
227 | cutBits(t.bitcnt);
|
228 | copyDist = windowPos - t.lbase - maskBits(e);
|
229 |
|
230 | while(copyLen > 0 && n < size) {
|
231 | copyLen--;
|
232 | copyDist &= WSIZE - 1;
|
233 | windowPos &= WSIZE - 1;
|
234 | buff[off + n++] = slide[windowPos++] = slide[copyDist++];
|
235 | }
|
236 |
|
237 | if(n == size) return size;
|
238 | }
|
239 |
|
240 | method = -1;
|
241 | return n;
|
242 | }
|
243 |
|
244 | function stored(buff, off, size) {
|
245 | cutBits(bitLen & 7);
|
246 | var n = maskBits(0x10);
|
247 | if(n != ((~maskBits(0x10)) & 0xffff)) return -1;
|
248 | copyLen = n;
|
249 |
|
250 | n = 0;
|
251 | while(copyLen > 0 && n < size) {
|
252 | copyLen--;
|
253 | windowPos &= WSIZE - 1;
|
254 | buff[off + n++] = slide[windowPos++] = maskBits(8);
|
255 | }
|
256 |
|
257 | if(copyLen == 0) method = -1;
|
258 | return n;
|
259 | }
|
260 |
|
261 | function fixed(buff, off, size) {
|
262 | var fixed_bd = 0;
|
263 | if(fixedTableList == null) {
|
264 | var lengths = [];
|
265 |
|
266 | for(var symbol = 0; symbol < 144; symbol++) lengths[symbol] = 8;
|
267 | for(; symbol < 256; symbol++) lengths[symbol] = 9;
|
268 | for(; symbol < 280; symbol++) lengths[symbol] = 7;
|
269 | for(; symbol < 288; symbol++) lengths[symbol] = 8;
|
270 |
|
271 | fixedLookup = 7;
|
272 |
|
273 | var htbl = new HuffTable(lengths, 288, 257, LENS, LEXT, fixedLookup);
|
274 |
|
275 | if(htbl.status != 0) return -1;
|
276 |
|
277 | fixedTableList = htbl.root;
|
278 | fixedLookup = htbl.maxbit;
|
279 |
|
280 | for(symbol = 0; symbol < 30; symbol++) lengths[symbol] = 5;
|
281 | fixed_bd = 5;
|
282 |
|
283 | htbl = new HuffTable(lengths, 30, 0, DISTS, DEXT, fixed_bd);
|
284 | if(htbl.status > 1) {
|
285 | fixedTableList = null;
|
286 | return -1;
|
287 | }
|
288 | fixedTableDist = htbl.root;
|
289 | fixed_bd = htbl.maxbit;
|
290 | }
|
291 |
|
292 | tblList = fixedTableList;
|
293 | tblDist = fixedTableDist;
|
294 | bitList = fixedLookup;
|
295 | bitdist = fixed_bd;
|
296 | return codes(buff, off, size);
|
297 | }
|
298 |
|
299 | function dynamic(buff, off, size) {
|
300 | var ll = new Array(0x023C);
|
301 |
|
302 | for (var m = 0; m < 0x023C; m++) ll[m] = 0;
|
303 |
|
304 | var llencnt = 257 + maskBits(5),
|
305 | dcodescnt = 1 + maskBits(5),
|
306 | bitlencnt = 4 + maskBits(4);
|
307 |
|
308 | if(llencnt > 286 || dcodescnt > 30) return -1;
|
309 |
|
310 | for(var j = 0; j < bitlencnt; j++) ll[BITORDER[j]] = maskBits(3);
|
311 | for(; j < 19; j++) ll[BITORDER[j]] = 0;
|
312 |
|
313 |
|
314 | bitList = 7;
|
315 | var hufTable = new HuffTable(ll, 19, 19, null, null, bitList);
|
316 | if(hufTable.status != 0)
|
317 | return -1;
|
318 |
|
319 | tblList = hufTable.root;
|
320 | bitList = hufTable.maxbit;
|
321 | var lencnt = llencnt + dcodescnt,
|
322 | i = 0,
|
323 | lastLen = 0;
|
324 | while(i < lencnt) {
|
325 | var hufLcode = tblList.list[addBits(bitList) & MASK_BITS[bitList]];
|
326 | j = hufLcode.bitcnt;
|
327 | cutBits(j);
|
328 | j = hufLcode.lbase;
|
329 | if(j < 16)
|
330 | ll[i++] = lastLen = j;
|
331 | else if(j == 16) {
|
332 | j = 3 + maskBits(2);
|
333 | if(i + j > lencnt) return -1;
|
334 | while(j-- > 0) ll[i++] = lastLen;
|
335 | } else if(j == 17) {
|
336 | j = 3 + maskBits(3);
|
337 | if(i + j > lencnt) return -1;
|
338 | while(j-- > 0) ll[i++] = 0;
|
339 | lastLen = 0;
|
340 | } else {
|
341 | j = 11 + maskBits(7);
|
342 | if(i + j > lencnt) return -1;
|
343 | while(j-- > 0) ll[i++] = 0;
|
344 | lastLen = 0;
|
345 | }
|
346 | }
|
347 | bitList = 9;
|
348 | hufTable = new HuffTable(ll, llencnt, 257, LENS, LEXT, bitList);
|
349 | bitList == 0 && (hufTable.status = 1);
|
350 |
|
351 | if (hufTable.status != 0) return -1;
|
352 |
|
353 | tblList = hufTable.root;
|
354 | bitList = hufTable.maxbit;
|
355 |
|
356 | for(i = 0; i < dcodescnt; i++) ll[i] = ll[i + llencnt];
|
357 | bitdist = 6;
|
358 | hufTable = new HuffTable(ll, dcodescnt, 0, DISTS, DEXT, bitdist);
|
359 | tblDist = hufTable.root;
|
360 | bitdist = hufTable.maxbit;
|
361 |
|
362 | if((bitdist == 0 && llencnt > 257) || hufTable.status != 0) return -1;
|
363 |
|
364 | return codes(buff, off, size);
|
365 | }
|
366 |
|
367 | return {
|
368 | inflate : function(/*Buffer*/outputBuffer) {
|
369 | tblList = null;
|
370 |
|
371 | var size = outputBuffer.length,
|
372 | offset = 0, i;
|
373 |
|
374 | while(offset < size) {
|
375 | if(eof && method == -1) return;
|
376 | if(copyLen > 0) {
|
377 | if(method != 0) {
|
378 | while(copyLen > 0 && offset < size) {
|
379 | copyLen--;
|
380 | copyDist &= WSIZE - 1;
|
381 | windowPos &= WSIZE - 1;
|
382 | outputBuffer[offset++] = slide[windowPos++] = slide[copyDist++];
|
383 | }
|
384 | } else {
|
385 | while(copyLen > 0 && offset < size) {
|
386 | copyLen--;
|
387 | windowPos &= WSIZE - 1;
|
388 | outputBuffer[offset++] = slide[windowPos++] = maskBits(8);
|
389 | }
|
390 | copyLen == 0 && (method = -1);
|
391 | }
|
392 | if (offset == size) return;
|
393 | }
|
394 |
|
395 | if(method == -1) {
|
396 | if(eof) break;
|
397 | eof = maskBits(1) != 0;
|
398 | method = maskBits(2);
|
399 | tblList = null;
|
400 | copyLen = 0;
|
401 | }
|
402 | switch(method) {
|
403 | case 0: i = stored(outputBuffer, offset, size - offset); break;
|
404 | case 1: i = tblList != null ? codes(outputBuffer, offset, size - offset) : fixed(outputBuffer, offset, size - offset); break;
|
405 | case 2: i = tblList != null ? codes(outputBuffer, offset, size - offset) : dynamic(outputBuffer, offset, size - offset); break;
|
406 | default: i = -1; break;
|
407 | }
|
408 |
|
409 | if(i == -1) return;
|
410 | offset += i;
|
411 | }
|
412 | }
|
413 | };
|
414 | }
|
415 |
|
416 | module.exports = function(/*Buffer*/inbuf) {
|
417 | var zlib = require("zlib");
|
418 | return {
|
419 | inflateAsync : function(/*Function*/callback) {
|
420 | var tmp = zlib.createInflateRaw(),
|
421 | parts = [], total = 0;
|
422 | tmp.on('data', function(data) {
|
423 | parts.push(data);
|
424 | total += data.length;
|
425 | });
|
426 | tmp.on('end', function() {
|
427 | var buf = new Buffer(total), written = 0;
|
428 | buf.fill(0);
|
429 |
|
430 | for (var i = 0; i < parts.length; i++) {
|
431 | var part = parts[i];
|
432 | part.copy(buf, written);
|
433 | written += part.length;
|
434 | }
|
435 | callback && callback(buf);
|
436 | });
|
437 | tmp.end(inbuf)
|
438 | },
|
439 |
|
440 | inflate : function(/*Buffer*/outputBuffer) {
|
441 | var x = new JSInflater(inbuf);
|
442 | x.inflate(outputBuffer);
|
443 | delete(x);
|
444 | }
|
445 | }
|
446 | }; |
\ | No newline at end of file |