--- /dev/null
+var Buffer = require("buffer").Buffer;
+
+function JSInflater(/*Buffer*/input) {
+
+ var WSIZE = 0x8000,
+ slide = new Buffer(0x10000),
+ windowPos = 0,
+ fixedTableList = null,
+ fixedTableDist,
+ fixedLookup,
+ bitBuf = 0,
+ bitLen = 0,
+ method = -1,
+ eof = false,
+ copyLen = 0,
+ copyDist = 0,
+ tblList, tblDist, bitList, bitdist,
+
+ inputPosition = 0,
+
+ MASK_BITS = [0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff],
+ 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],
+ 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],
+ 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],
+ 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],
+ BITORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
+
+ function HuffTable(clen, cnum, cval, blist, elist, lookupm) {
+
+ this.status = 0;
+ this.root = null;
+ this.maxbit = 0;
+
+ var el, f, tail,
+ offsets = [],
+ countTbl = [],
+ sTbl = [],
+ values = [],
+ tentry = {extra: 0, bitcnt: 0, lbase: 0, next: null};
+
+ tail = this.root = null;
+ for(var i = 0; i < 0x11; i++) { countTbl[i] = 0; sTbl[i] = 0; offsets[i] = 0; }
+ for(i = 0; i < 0x120; i++) values[i] = 0;
+
+ el = cnum > 256 ? clen[256] : 16;
+
+ var pidx = -1;
+ while (++pidx < cnum) countTbl[clen[pidx]]++;
+
+ if(countTbl[0] == cnum) return;
+
+ for(var j = 1; j <= 16; j++) if(countTbl[j] != 0) break;
+ var bitLen = j;
+ for(i = 16; i != 0; i--) if(countTbl[i] != 0) break;
+ var maxLen = i;
+
+ lookupm < j && (lookupm = j);
+
+ var dCodes = 1 << j;
+ for(; j < i; j++, dCodes <<= 1)
+ if((dCodes -= countTbl[j]) < 0) {
+ this.status = 2;
+ this.maxbit = lookupm;
+ return;
+ }
+
+ if((dCodes -= countTbl[i]) < 0) {
+ this.status = 2;
+ this.maxbit = lookupm;
+ return;
+ }
+
+ countTbl[i] += dCodes;
+ offsets[1] = j = 0;
+ pidx = 1;
+ var xp = 2;
+ while(--i > 0) offsets[xp++] = (j += countTbl[pidx++]);
+ pidx = 0;
+ i = 0;
+ do {
+ (j = clen[pidx++]) && (values[offsets[j]++] = i);
+ } while(++i < cnum);
+ cnum = offsets[maxLen];
+ offsets[0] = i = 0;
+ pidx = 0;
+
+ var level = -1,
+ w = sTbl[0] = 0,
+ cnode = null,
+ tblCnt = 0,
+ tblStack = [];
+
+ for(; bitLen <= maxLen; bitLen++) {
+ var kccnt = countTbl[bitLen];
+ while(kccnt-- > 0) {
+ while(bitLen > w + sTbl[1 + level]) {
+ w += sTbl[1 + level];
+ level++;
+ tblCnt = (tblCnt = maxLen - w) > lookupm ? lookupm : tblCnt;
+ if((f = 1 << (j = bitLen - w)) > kccnt + 1) {
+ f -= kccnt + 1;
+ xp = bitLen;
+ while(++j < tblCnt) {
+ if((f <<= 1) <= countTbl[++xp]) break;
+ f -= countTbl[xp];
+ }
+ }
+ if(w + j > el && w < el) j = el - w;
+ tblCnt = 1 << j;
+ sTbl[1 + level] = j;
+ cnode = [];
+ while (cnode.length < tblCnt) cnode.push({extra: 0, bitcnt: 0, lbase: 0, next: null});
+ if (tail == null) {
+ tail = this.root = {next:null, list:null};
+ } else {
+ tail = tail.next = {next:null, list:null}
+ }
+ tail.next = null;
+ tail.list = cnode;
+
+ tblStack[level] = cnode;
+
+ if(level > 0) {
+ offsets[level] = i;
+ tentry.bitcnt = sTbl[level];
+ tentry.extra = 16 + j;
+ tentry.next = cnode;
+ j = (i & ((1 << w) - 1)) >> (w - sTbl[level]);
+
+ tblStack[level-1][j].extra = tentry.extra;
+ tblStack[level-1][j].bitcnt = tentry.bitcnt;
+ tblStack[level-1][j].lbase = tentry.lbase;
+ tblStack[level-1][j].next = tentry.next;
+ }
+ }
+ tentry.bitcnt = bitLen - w;
+ if(pidx >= cnum)
+ tentry.extra = 99;
+ else if(values[pidx] < cval) {
+ tentry.extra = (values[pidx] < 256 ? 16 : 15);
+ tentry.lbase = values[pidx++];
+ } else {
+ tentry.extra = elist[values[pidx] - cval];
+ tentry.lbase = blist[values[pidx++] - cval];
+ }
+
+ f = 1 << (bitLen - w);
+ for(j = i >> w; j < tblCnt; j += f) {
+ cnode[j].extra = tentry.extra;
+ cnode[j].bitcnt = tentry.bitcnt;
+ cnode[j].lbase = tentry.lbase;
+ cnode[j].next = tentry.next;
+ }
+ for(j = 1 << (bitLen - 1); (i & j) != 0; j >>= 1)
+ i ^= j;
+ i ^= j;
+ while((i & ((1 << w) - 1)) != offsets[level]) {
+ w -= sTbl[level];
+ level--;
+ }
+ }
+ }
+
+ this.maxbit = sTbl[1];
+ this.status = ((dCodes != 0 && maxLen != 1) ? 1 : 0);
+ }
+
+ function addBits(n) {
+ while(bitLen < n) {
+ bitBuf |= input[inputPosition++] << bitLen;
+ bitLen += 8;
+ }
+ return bitBuf;
+ }
+
+ function cutBits(n) {
+ bitLen -= n;
+ return bitBuf >>= n;
+ }
+
+ function maskBits(n) {
+ while(bitLen < n) {
+ bitBuf |= input[inputPosition++] << bitLen;
+ bitLen += 8;
+ }
+ var res = bitBuf & MASK_BITS[n];
+ bitBuf >>= n;
+ bitLen -= n;
+ return res;
+ }
+
+ function codes(buff, off, size) {
+ var e, t;
+ if(size == 0) return 0;
+
+ var n = 0;
+ for(;;) {
+ t = tblList.list[addBits(bitList) & MASK_BITS[bitList]];
+ e = t.extra;
+ while(e > 16) {
+ if(e == 99) return -1;
+ cutBits(t.bitcnt);
+ e -= 16;
+ t = t.next[addBits(e) & MASK_BITS[e]];
+ e = t.extra;
+ }
+ cutBits(t.bitcnt);
+ if(e == 16) {
+ windowPos &= WSIZE - 1;
+ buff[off + n++] = slide[windowPos++] = t.lbase;
+ if(n == size) return size;
+ continue;
+ }
+ if(e == 15) break;
+
+ copyLen = t.lbase + maskBits(e);
+ t = tblDist.list[addBits(bitdist) & MASK_BITS[bitdist]];
+ e = t.extra;
+
+ while(e > 16) {
+ if(e == 99) return -1;
+ cutBits(t.bitcnt);
+ e -= 16;
+ t = t.next[addBits(e) & MASK_BITS[e]];
+ e = t.extra
+ }
+ cutBits(t.bitcnt);
+ copyDist = windowPos - t.lbase - maskBits(e);
+
+ while(copyLen > 0 && n < size) {
+ copyLen--;
+ copyDist &= WSIZE - 1;
+ windowPos &= WSIZE - 1;
+ buff[off + n++] = slide[windowPos++] = slide[copyDist++];
+ }
+
+ if(n == size) return size;
+ }
+
+ method = -1; // done
+ return n;
+ }
+
+ function stored(buff, off, size) {
+ cutBits(bitLen & 7);
+ var n = maskBits(0x10);
+ if(n != ((~maskBits(0x10)) & 0xffff)) return -1;
+ copyLen = n;
+
+ n = 0;
+ while(copyLen > 0 && n < size) {
+ copyLen--;
+ windowPos &= WSIZE - 1;
+ buff[off + n++] = slide[windowPos++] = maskBits(8);
+ }
+
+ if(copyLen == 0) method = -1;
+ return n;
+ }
+
+ function fixed(buff, off, size) {
+ var fixed_bd = 0;
+ if(fixedTableList == null) {
+ var lengths = [];
+
+ for(var symbol = 0; symbol < 144; symbol++) lengths[symbol] = 8;
+ for(; symbol < 256; symbol++) lengths[symbol] = 9;
+ for(; symbol < 280; symbol++) lengths[symbol] = 7;
+ for(; symbol < 288; symbol++) lengths[symbol] = 8;
+
+ fixedLookup = 7;
+
+ var htbl = new HuffTable(lengths, 288, 257, LENS, LEXT, fixedLookup);
+
+ if(htbl.status != 0) return -1;
+
+ fixedTableList = htbl.root;
+ fixedLookup = htbl.maxbit;
+
+ for(symbol = 0; symbol < 30; symbol++) lengths[symbol] = 5;
+ fixed_bd = 5;
+
+ htbl = new HuffTable(lengths, 30, 0, DISTS, DEXT, fixed_bd);
+ if(htbl.status > 1) {
+ fixedTableList = null;
+ return -1;
+ }
+ fixedTableDist = htbl.root;
+ fixed_bd = htbl.maxbit;
+ }
+
+ tblList = fixedTableList;
+ tblDist = fixedTableDist;
+ bitList = fixedLookup;
+ bitdist = fixed_bd;
+ return codes(buff, off, size);
+ }
+
+ function dynamic(buff, off, size) {
+ var ll = new Array(0x023C);
+
+ for (var m = 0; m < 0x023C; m++) ll[m] = 0;
+
+ var llencnt = 257 + maskBits(5),
+ dcodescnt = 1 + maskBits(5),
+ bitlencnt = 4 + maskBits(4);
+
+ if(llencnt > 286 || dcodescnt > 30) return -1;
+
+ for(var j = 0; j < bitlencnt; j++) ll[BITORDER[j]] = maskBits(3);
+ for(; j < 19; j++) ll[BITORDER[j]] = 0;
+
+ // build decoding table for trees--single level, 7 bit lookup
+ bitList = 7;
+ var hufTable = new HuffTable(ll, 19, 19, null, null, bitList);
+ if(hufTable.status != 0)
+ return -1; // incomplete code set
+
+ tblList = hufTable.root;
+ bitList = hufTable.maxbit;
+ var lencnt = llencnt + dcodescnt,
+ i = 0,
+ lastLen = 0;
+ while(i < lencnt) {
+ var hufLcode = tblList.list[addBits(bitList) & MASK_BITS[bitList]];
+ j = hufLcode.bitcnt;
+ cutBits(j);
+ j = hufLcode.lbase;
+ if(j < 16)
+ ll[i++] = lastLen = j;
+ else if(j == 16) {
+ j = 3 + maskBits(2);
+ if(i + j > lencnt) return -1;
+ while(j-- > 0) ll[i++] = lastLen;
+ } else if(j == 17) {
+ j = 3 + maskBits(3);
+ if(i + j > lencnt) return -1;
+ while(j-- > 0) ll[i++] = 0;
+ lastLen = 0;
+ } else {
+ j = 11 + maskBits(7);
+ if(i + j > lencnt) return -1;
+ while(j-- > 0) ll[i++] = 0;
+ lastLen = 0;
+ }
+ }
+ bitList = 9;
+ hufTable = new HuffTable(ll, llencnt, 257, LENS, LEXT, bitList);
+ bitList == 0 && (hufTable.status = 1);
+
+ if (hufTable.status != 0) return -1;
+
+ tblList = hufTable.root;
+ bitList = hufTable.maxbit;
+
+ for(i = 0; i < dcodescnt; i++) ll[i] = ll[i + llencnt];
+ bitdist = 6;
+ hufTable = new HuffTable(ll, dcodescnt, 0, DISTS, DEXT, bitdist);
+ tblDist = hufTable.root;
+ bitdist = hufTable.maxbit;
+
+ if((bitdist == 0 && llencnt > 257) || hufTable.status != 0) return -1;
+
+ return codes(buff, off, size);
+ }
+
+ return {
+ inflate : function(/*Buffer*/outputBuffer) {
+ tblList = null;
+
+ var size = outputBuffer.length,
+ offset = 0, i;
+
+ while(offset < size) {
+ if(eof && method == -1) return;
+ if(copyLen > 0) {
+ if(method != 0) {
+ while(copyLen > 0 && offset < size) {
+ copyLen--;
+ copyDist &= WSIZE - 1;
+ windowPos &= WSIZE - 1;
+ outputBuffer[offset++] = (slide[windowPos++] = slide[copyDist++]);
+ }
+ } else {
+ while(copyLen > 0 && offset < size) {
+ copyLen--;
+ windowPos &= WSIZE - 1;
+ outputBuffer[offset++] = (slide[windowPos++] = maskBits(8));
+ }
+ copyLen == 0 && (method = -1); // done
+ }
+ if (offset == size) return;
+ }
+
+ if(method == -1) {
+ if(eof) break;
+ eof = maskBits(1) != 0;
+ method = maskBits(2);
+ tblList = null;
+ copyLen = 0;
+ }
+ switch(method) {
+ case 0: i = stored(outputBuffer, offset, size - offset); break;
+ case 1: i = tblList != null ? codes(outputBuffer, offset, size - offset) : fixed(outputBuffer, offset, size - offset); break;
+ case 2: i = tblList != null ? codes(outputBuffer, offset, size - offset) : dynamic(outputBuffer, offset, size - offset); break;
+ default: i = -1; break;
+ }
+
+ if(i == -1) return;
+ offset += i;
+ }
+ }
+ };
+}
+
+module.exports = function(/*Buffer*/inbuf) {
+ var zlib = require("zlib");
+ return {
+ inflateAsync : function(/*Function*/callback) {
+ var tmp = zlib.createInflateRaw(),
+ parts = [], total = 0;
+ tmp.on('data', function(data) {
+ parts.push(data);
+ total += data.length;
+ });
+ tmp.on('end', function() {
+ var buf = new Buffer(total), written = 0;
+ buf.fill(0);
+
+ for (var i = 0; i < parts.length; i++) {
+ var part = parts[i];
+ part.copy(buf, written);
+ written += part.length;
+ }
+ callback && callback(buf);
+ });
+ tmp.end(inbuf)
+ },
+
+ inflate : function(/*Buffer*/outputBuffer) {
+ var x = {
+ x: new JSInflater(inbuf)
+ };
+ x.x.inflate(outputBuffer);
+ delete(x.x);
+ }
+ }
+};