diff --git a/lib/inflate.js b/lib/inflate.js index 8cf8695..af37e03 100644 --- a/lib/inflate.js +++ b/lib/inflate.js @@ -6,6 +6,7 @@ var utils = require('./zlib/utils'); var c = require('./zlib/constants'); var msg = require('./zlib/messages'); var zstream = require('./zlib/zstream'); +var gzheader = require('./zlib/gzheader'); /** @@ -128,6 +129,13 @@ var Inflate = function(options) { if (status !== c.Z_OK) { throw new Error(msg[status]); } + + this.header = new gzheader(); + this.header.name_max = 65536; + this.header.comm_max = 65536; + this.header.extra_max = 65536; + + zlib_inflate.inflateGetHeader(this.strm, this.header); }; /** diff --git a/lib/zlib/gzheader.js b/lib/zlib/gzheader.js new file mode 100644 index 0000000..d89781f --- /dev/null +++ b/lib/zlib/gzheader.js @@ -0,0 +1,33 @@ +'use strict'; + + +function GZheader() { + /* true if compressed data believed to be text */ + this.text = 0; + /* modification time */ + this.time = 0; + /* extra flags (not used when writing a gzip file) */ + this.xflags = 0; + /* operating system */ + this.os = 0; + /* pointer to extra field or Z_NULL if none */ + this.extra = null; + /* extra field length (valid if extra != Z_NULL) */ + this.extra_len = 0; + /* space at extra (only when reading header) */ + this.extra_max = 0; + /* pointer to zero-terminated file name or Z_NULL */ + this.name = ''; + /* space at name (only when reading header) */ + this.name_max = 0; + /* pointer to zero-terminated comment or Z_NULL */ + this.comment = ''; + /* space at comment (only when reading header) */ + this.comm_max = 0; + /* true if there was or will be a header crc */ + this.hcrc = 0; + /* true when done reading gzip header (not used when writing a gzip file) */ + this.done = false; +} + +module.exports = GZheader; \ No newline at end of file diff --git a/lib/zlib/inflate.js b/lib/zlib/inflate.js index 6ebdfb0..83bbc7e 100644 --- a/lib/zlib/inflate.js +++ b/lib/zlib/inflate.js @@ -476,7 +476,7 @@ function inflate(strm, flush) { } state.flags = 0; /* expect zlib header */ if (state.head) { - state.head.done = -1; + state.head.done = false; } if (!(state.wrap & 1) || /* check if zlib header allowed */ (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { @@ -636,13 +636,21 @@ function inflate(strm, flush) { copy = state.length; if (copy > have) { copy = have; } if (copy) { - if (state.head && - state.head.extra) { + if (state.head) { len = state.head.extra_len - state.length; + if (!state.head.extra) { + state.head.extra = new utils.Buf8(state.head.extra_len); + } + utils.arraySet( + state.head.extra, + input, + next, + len + copy > state.head.extra_max - len ? state.head.extra_max : copy, + len + ); //zmemcpy(state.head.extra + len, next, // len + copy > state.head.extra_max ? // state.head.extra_max - len : copy); - throw 'Review & implement right'; } if (state.flags & 0x0200) { state.check = crc32(state.check, input, copy, next); @@ -663,11 +671,12 @@ function inflate(strm, flush) { do { // TODO: 2 or 1 bytes? len = input[next + copy++]; - if (state.head && state.head.name && + if (state.head && len && (state.length < state.head.name_max)) { - state.head.name[state.length++] = len; + state.head.name += String.fromCharCode(len); } } while (len && copy < have); + if (state.flags & 0x0200) { state.check = crc32(state.check, input, copy, next); } @@ -687,9 +696,9 @@ function inflate(strm, flush) { copy = 0; do { len = input[next + copy++]; - if (state.head && state.head.comment && + if (state.head && len && (state.length < state.head.comm_max)) { - state.head.comment[state.length++] = len; + state.head.comment += String.fromCharCode(len); } } while (len && copy < have); if (state.flags & 0x0200) { @@ -726,7 +735,7 @@ function inflate(strm, flush) { } if (state.head) { state.head.hcrc = ((state.flags >> 9) & 1); - state.head.done = 1; + state.head.done = true; } strm.adler = state.check = 0 /*crc32(0L, Z_NULL, 0)*/; state.mode = TYPE; @@ -1477,6 +1486,20 @@ function inflateEnd(strm) { return Z_OK; } +function inflateGetHeader(strm, head) { + var state; + + /* check state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } + + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK; +} + exports.inflateReset = inflateReset; exports.inflateReset2 = inflateReset2; @@ -1486,11 +1509,11 @@ exports.inflateInit2 = inflateInit2; exports.inflatePrime = inflatePrime; exports.inflate = inflate; exports.inflateEnd = inflateEnd; +exports.inflateGetHeader = inflateGetHeader; exports.inflateInfo = 'pako inflate (from Nodeca project)'; /* Not implemented exports.inflateGetDictionary = inflateGetDictionary; -exports.inflateGetHeader = inflateGetHeader; exports.inflateSetDictionary = inflateSetDictionary; exports.inflateSync = inflateSync; exports.inflateSyncPoint = inflateSyncPoint; diff --git a/test/fixtures/header/test.gz b/test/fixtures/header/test.gz new file mode 100644 index 0000000..2956b22 Binary files /dev/null and b/test/fixtures/header/test.gz differ diff --git a/test/helpers.js b/test/helpers.js index 9c89de2..bf95058 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -17,6 +17,9 @@ function loadSamples() { var dir = path.join(__dirname, 'fixtures'); fs.readdirSync(dir).sort().forEach(function (sample) { + if (fs.statSync(path.join(dir, sample)).isDirectory()) { + return; + } var filepath = path.join(dir, sample), extname = path.extname(filepath), basename = path.basename(filepath, extname), diff --git a/test/inflate.js b/test/inflate.js index d667c8e..7f934db 100644 --- a/test/inflate.js +++ b/test/inflate.js @@ -155,4 +155,3 @@ describe('Inflate RAW', function () { }); }); - diff --git a/test/inflate_cover.js b/test/inflate_cover.js new file mode 100644 index 0000000..452fbcb --- /dev/null +++ b/test/inflate_cover.js @@ -0,0 +1,101 @@ +/*global describe, it*/ + + +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var assert = require('assert'); + +var c = require('../lib/zlib/constants'); + +var pako_utils = require('../lib/zlib/utils'); +var pako_msg = require('../lib/zlib/messages'); +var pako = require('../index'); + +function h2b(hex) { + var tmp = hex.split(' '); + var res = new pako_utils.Buf8(tmp.length); + for (var i=0; i