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; // done |
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
|
|
|
// build decoding table for trees--single level, 7 bit lookup |
314
|
|
|
bitList = 7; |
315
|
|
|
var hufTable = new HuffTable(ll, 19, 19, null, null, bitList); |
316
|
|
|
if(hufTable.status != 0) |
317
|
|
|
return -1; // incomplete code set |
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); // done |
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 = { |
442
|
|
|
x: new JSInflater(inbuf) |
443
|
|
|
}; |
444
|
|
|
x.x.inflate(outputBuffer); |
445
|
|
|
delete(x.x); |
446
|
|
|
} |
447
|
|
|
} |
448
|
|
|
}; |
449
|
|
|
|