mirror of
https://github.com/0x5eal/rbxts-pako.git
synced 2025-05-04 10:33:48 +01:00
fix reading gzip headers & add test for inflate gz headers
This commit is contained in:
parent
c92edab663
commit
144a94e3f8
7 changed files with 178 additions and 11 deletions
|
@ -6,6 +6,7 @@ var utils = require('./zlib/utils');
|
||||||
var c = require('./zlib/constants');
|
var c = require('./zlib/constants');
|
||||||
var msg = require('./zlib/messages');
|
var msg = require('./zlib/messages');
|
||||||
var zstream = require('./zlib/zstream');
|
var zstream = require('./zlib/zstream');
|
||||||
|
var gzheader = require('./zlib/gzheader');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -128,6 +129,13 @@ var Inflate = function(options) {
|
||||||
if (status !== c.Z_OK) {
|
if (status !== c.Z_OK) {
|
||||||
throw new Error(msg[status]);
|
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
33
lib/zlib/gzheader.js
Normal file
33
lib/zlib/gzheader.js
Normal file
|
@ -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;
|
|
@ -476,7 +476,7 @@ function inflate(strm, flush) {
|
||||||
}
|
}
|
||||||
state.flags = 0; /* expect zlib header */
|
state.flags = 0; /* expect zlib header */
|
||||||
if (state.head) {
|
if (state.head) {
|
||||||
state.head.done = -1;
|
state.head.done = false;
|
||||||
}
|
}
|
||||||
if (!(state.wrap & 1) || /* check if zlib header allowed */
|
if (!(state.wrap & 1) || /* check if zlib header allowed */
|
||||||
(((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
|
(((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
|
||||||
|
@ -636,13 +636,21 @@ function inflate(strm, flush) {
|
||||||
copy = state.length;
|
copy = state.length;
|
||||||
if (copy > have) { copy = have; }
|
if (copy > have) { copy = have; }
|
||||||
if (copy) {
|
if (copy) {
|
||||||
if (state.head &&
|
if (state.head) {
|
||||||
state.head.extra) {
|
|
||||||
len = state.head.extra_len - state.length;
|
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,
|
//zmemcpy(state.head.extra + len, next,
|
||||||
// len + copy > state.head.extra_max ?
|
// len + copy > state.head.extra_max ?
|
||||||
// state.head.extra_max - len : copy);
|
// state.head.extra_max - len : copy);
|
||||||
throw 'Review & implement right';
|
|
||||||
}
|
}
|
||||||
if (state.flags & 0x0200) {
|
if (state.flags & 0x0200) {
|
||||||
state.check = crc32(state.check, input, copy, next);
|
state.check = crc32(state.check, input, copy, next);
|
||||||
|
@ -663,11 +671,12 @@ function inflate(strm, flush) {
|
||||||
do {
|
do {
|
||||||
// TODO: 2 or 1 bytes?
|
// TODO: 2 or 1 bytes?
|
||||||
len = input[next + copy++];
|
len = input[next + copy++];
|
||||||
if (state.head && state.head.name &&
|
if (state.head && len &&
|
||||||
(state.length < state.head.name_max)) {
|
(state.length < state.head.name_max)) {
|
||||||
state.head.name[state.length++] = len;
|
state.head.name += String.fromCharCode(len);
|
||||||
}
|
}
|
||||||
} while (len && copy < have);
|
} while (len && copy < have);
|
||||||
|
|
||||||
if (state.flags & 0x0200) {
|
if (state.flags & 0x0200) {
|
||||||
state.check = crc32(state.check, input, copy, next);
|
state.check = crc32(state.check, input, copy, next);
|
||||||
}
|
}
|
||||||
|
@ -687,9 +696,9 @@ function inflate(strm, flush) {
|
||||||
copy = 0;
|
copy = 0;
|
||||||
do {
|
do {
|
||||||
len = input[next + copy++];
|
len = input[next + copy++];
|
||||||
if (state.head && state.head.comment &&
|
if (state.head && len &&
|
||||||
(state.length < state.head.comm_max)) {
|
(state.length < state.head.comm_max)) {
|
||||||
state.head.comment[state.length++] = len;
|
state.head.comment += String.fromCharCode(len);
|
||||||
}
|
}
|
||||||
} while (len && copy < have);
|
} while (len && copy < have);
|
||||||
if (state.flags & 0x0200) {
|
if (state.flags & 0x0200) {
|
||||||
|
@ -726,7 +735,7 @@ function inflate(strm, flush) {
|
||||||
}
|
}
|
||||||
if (state.head) {
|
if (state.head) {
|
||||||
state.head.hcrc = ((state.flags >> 9) & 1);
|
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)*/;
|
strm.adler = state.check = 0 /*crc32(0L, Z_NULL, 0)*/;
|
||||||
state.mode = TYPE;
|
state.mode = TYPE;
|
||||||
|
@ -1477,6 +1486,20 @@ function inflateEnd(strm) {
|
||||||
return Z_OK;
|
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.inflateReset = inflateReset;
|
||||||
exports.inflateReset2 = inflateReset2;
|
exports.inflateReset2 = inflateReset2;
|
||||||
|
@ -1486,11 +1509,11 @@ exports.inflateInit2 = inflateInit2;
|
||||||
exports.inflatePrime = inflatePrime;
|
exports.inflatePrime = inflatePrime;
|
||||||
exports.inflate = inflate;
|
exports.inflate = inflate;
|
||||||
exports.inflateEnd = inflateEnd;
|
exports.inflateEnd = inflateEnd;
|
||||||
|
exports.inflateGetHeader = inflateGetHeader;
|
||||||
exports.inflateInfo = 'pako inflate (from Nodeca project)';
|
exports.inflateInfo = 'pako inflate (from Nodeca project)';
|
||||||
|
|
||||||
/* Not implemented
|
/* Not implemented
|
||||||
exports.inflateGetDictionary = inflateGetDictionary;
|
exports.inflateGetDictionary = inflateGetDictionary;
|
||||||
exports.inflateGetHeader = inflateGetHeader;
|
|
||||||
exports.inflateSetDictionary = inflateSetDictionary;
|
exports.inflateSetDictionary = inflateSetDictionary;
|
||||||
exports.inflateSync = inflateSync;
|
exports.inflateSync = inflateSync;
|
||||||
exports.inflateSyncPoint = inflateSyncPoint;
|
exports.inflateSyncPoint = inflateSyncPoint;
|
||||||
|
|
BIN
test/fixtures/header/test.gz
vendored
Normal file
BIN
test/fixtures/header/test.gz
vendored
Normal file
Binary file not shown.
|
@ -17,6 +17,9 @@ function loadSamples() {
|
||||||
var dir = path.join(__dirname, 'fixtures');
|
var dir = path.join(__dirname, 'fixtures');
|
||||||
|
|
||||||
fs.readdirSync(dir).sort().forEach(function (sample) {
|
fs.readdirSync(dir).sort().forEach(function (sample) {
|
||||||
|
if (fs.statSync(path.join(dir, sample)).isDirectory()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
var filepath = path.join(dir, sample),
|
var filepath = path.join(dir, sample),
|
||||||
extname = path.extname(filepath),
|
extname = path.extname(filepath),
|
||||||
basename = path.basename(filepath, extname),
|
basename = path.basename(filepath, extname),
|
||||||
|
|
|
@ -155,4 +155,3 @@ describe('Inflate RAW', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
101
test/inflate_cover.js
Normal file
101
test/inflate_cover.js
Normal file
|
@ -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<tmp.length; i++) {
|
||||||
|
res[i] = parseInt(tmp[i], 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function testInflate(hex, wbits, err) {
|
||||||
|
var inflator;
|
||||||
|
|
||||||
|
var assert_fn = err === c.Z_OK ? assert.doesNotThrow : assert.throws;
|
||||||
|
|
||||||
|
assert_fn(function() {
|
||||||
|
inflator = new pako.Inflate({windowBits: wbits});
|
||||||
|
inflator.push(h2b(hex), true);
|
||||||
|
if (inflator.err) {
|
||||||
|
throw new Error(inflator.err);
|
||||||
|
}
|
||||||
|
}, pako_msg[err]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testInflateGzHeader(sample, field, expected) {
|
||||||
|
var data, actual;
|
||||||
|
data = new Uint8Array(fs.readFileSync(path.join(__dirname, 'fixtures/header', sample)));
|
||||||
|
|
||||||
|
var inflator = new pako.Inflate();
|
||||||
|
inflator.push(data, true);
|
||||||
|
|
||||||
|
actual = inflator.header[field];
|
||||||
|
if (actual instanceof pako_utils.Buf8) {
|
||||||
|
actual = String.fromCharCode.apply(null, actual);
|
||||||
|
}
|
||||||
|
assert.equal(actual, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
describe('Inflate coverage wrap', function() {
|
||||||
|
it('bad gzip method', function() {
|
||||||
|
testInflate('1f 8b 0 0', 31, c.Z_DATA_ERROR);
|
||||||
|
});
|
||||||
|
it('bad gzip flags', function() {
|
||||||
|
testInflate('1f 8b 8 80', 31, c.Z_DATA_ERROR);
|
||||||
|
});
|
||||||
|
it('bad zlib method', function() {
|
||||||
|
testInflate('77 85', 15, c.Z_DATA_ERROR);
|
||||||
|
});
|
||||||
|
it('set window size from header', function() {
|
||||||
|
testInflate('8 99', 0, c.Z_OK);
|
||||||
|
});
|
||||||
|
it('bad zlib window size', function() {
|
||||||
|
testInflate('78 9c', 8, c.Z_DATA_ERROR);
|
||||||
|
});
|
||||||
|
it('check adler32', function() {
|
||||||
|
testInflate('78 9c 63 0 0 0 1 0 1', 15, c.Z_OK);
|
||||||
|
});
|
||||||
|
it('bad header crc', function() {
|
||||||
|
testInflate('1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0', 47, c.Z_DATA_ERROR);
|
||||||
|
});
|
||||||
|
it('check gzip length', function() {
|
||||||
|
testInflate('1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0', 47, c.Z_OK);
|
||||||
|
});
|
||||||
|
it('bad zlib header check', function() {
|
||||||
|
testInflate('78 90', 47, c.Z_DATA_ERROR);
|
||||||
|
});
|
||||||
|
it('need dictionary', function() {
|
||||||
|
testInflate('8 b8 0 0 0 1', 8, c.Z_NEED_DICT);
|
||||||
|
});
|
||||||
|
it('compute adler32', function() {
|
||||||
|
testInflate('78 9c 63 0', 15, c.Z_OK);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Inflate coverage gzip header', function() {
|
||||||
|
it('check filename', function() {
|
||||||
|
testInflateGzHeader('test.gz', 'name', 'test name');
|
||||||
|
});
|
||||||
|
it('check comment', function() {
|
||||||
|
testInflateGzHeader('test.gz', 'comment', 'test comment');
|
||||||
|
});
|
||||||
|
it('check extra', function() {
|
||||||
|
testInflateGzHeader('test.gz', 'extra', 'test extra');
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Reference in a new issue