mirror of
https://github.com/0x5eal/rbxts-pako.git
synced 2025-05-04 10:33:48 +01:00
Deflate: added custom gzip headers support
This commit is contained in:
parent
e4593facbb
commit
b165c9c945
3 changed files with 207 additions and 13 deletions
|
@ -86,6 +86,14 @@ var Z_DEFLATED = 8;
|
|||
* - `gzip` (Boolean) - create gzip wrapper
|
||||
* - `to` (String) - if equal to 'string', then result will be "binary string"
|
||||
* (each char code [0..255])
|
||||
* - `header` (Object) - custom header for gzip
|
||||
* - `text` (Boolean) - true if compressed data believed to be text
|
||||
* - `time` (Number) - modification time, unix timestamp
|
||||
* - `os` (Number) - operation system code
|
||||
* - `extra` (Array) - array of bytes with extra data (max 65536)
|
||||
* - `name` (String) - file name (binary string)
|
||||
* - `comment` (String) - comment (binary string)
|
||||
* - `hcrc` (Boolean) - true if header crc should be added
|
||||
*
|
||||
* ##### Example:
|
||||
*
|
||||
|
@ -146,6 +154,10 @@ var Deflate = function(options) {
|
|||
if (status !== Z_OK) {
|
||||
throw new Error(msg[status]);
|
||||
}
|
||||
|
||||
if (opt.header) {
|
||||
zlib_deflate.deflateSetHeader(this.strm, opt.header);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1179,13 +1179,6 @@ function DeflateState() {
|
|||
zero(this.dyn_dtree);
|
||||
zero(this.bl_tree);
|
||||
|
||||
// struct tree_desc_s l_desc; /* desc. for literal tree */
|
||||
// struct tree_desc_s d_desc; /* desc. for distance tree */
|
||||
// struct tree_desc_s bl_desc; /* desc. for bit length tree */
|
||||
|
||||
// Seems to init better from `tree` with direct structures,
|
||||
// (?) with separate constructor for bl_desc or not?
|
||||
// Make sure objects have the same hidden class if needed
|
||||
this.l_desc = null; /* desc. for literal tree */
|
||||
this.d_desc = null; /* desc. for distance tree */
|
||||
this.bl_desc = null; /* desc. for bit length tree */
|
||||
|
@ -1264,6 +1257,7 @@ function DeflateState() {
|
|||
*/
|
||||
}
|
||||
|
||||
|
||||
function deflateResetKeep(strm) {
|
||||
var s;
|
||||
|
||||
|
@ -1292,6 +1286,7 @@ function deflateResetKeep(strm) {
|
|||
return Z_OK;
|
||||
}
|
||||
|
||||
|
||||
function deflateReset(strm) {
|
||||
var ret = deflateResetKeep(strm);
|
||||
if (ret === Z_OK) {
|
||||
|
@ -1300,6 +1295,15 @@ function deflateReset(strm) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
function deflateSetHeader(strm, head) {
|
||||
if (!strm || !strm.state) { return Z_STREAM_ERROR; }
|
||||
if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; }
|
||||
strm.state.gzhead = head;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
|
||||
function deflateInit2(strm, level, method, windowBits, memLevel, strategy) {
|
||||
if (!strm) { // === Z_NULL
|
||||
return err(strm, Z_STREAM_ERROR);
|
||||
|
@ -1378,6 +1382,7 @@ function deflateInit(strm, level) {
|
|||
|
||||
function deflate(strm, flush) {
|
||||
var old_flush, s;
|
||||
var beg, val; // for gzip header write only
|
||||
|
||||
if (!strm || !strm.state ||
|
||||
flush > Z_BLOCK || flush < 0) {
|
||||
|
@ -1417,7 +1422,29 @@ function deflate(strm, flush) {
|
|||
s.status = BUSY_STATE;
|
||||
}
|
||||
else {
|
||||
throw new Error('Custom GZIP headers not supported');
|
||||
put_byte(s, (s.gzhead.text ? 1 : 0) +
|
||||
(s.gzhead.hcrc ? 2 : 0) +
|
||||
(!s.gzhead.extra ? 0 : 4) +
|
||||
(!s.gzhead.name ? 0 : 8) +
|
||||
(!s.gzhead.comment ? 0 : 16)
|
||||
);
|
||||
put_byte(s, s.gzhead.time & 0xff);
|
||||
put_byte(s, (s.gzhead.time >> 8) & 0xff);
|
||||
put_byte(s, (s.gzhead.time >> 16) & 0xff);
|
||||
put_byte(s, (s.gzhead.time >> 24) & 0xff);
|
||||
put_byte(s, s.level === 9 ? 2 :
|
||||
(s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
|
||||
4 : 0));
|
||||
put_byte(s, s.gzhead.os & 0xff);
|
||||
if (s.gzhead.extra && s.gzhead.extra.length) {
|
||||
put_byte(s, s.gzhead.extra.length & 0xff);
|
||||
put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);
|
||||
}
|
||||
if (s.gzhead.hcrc) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0);
|
||||
}
|
||||
s.gzindex = 0;
|
||||
s.status = EXTRA_STATE;
|
||||
}
|
||||
}
|
||||
else // DEFLATE header
|
||||
|
@ -1450,6 +1477,130 @@ function deflate(strm, flush) {
|
|||
}
|
||||
}
|
||||
|
||||
//#ifdef GZIP
|
||||
if (s.status === EXTRA_STATE) {
|
||||
if (s.gzhead.extra/* != Z_NULL*/) {
|
||||
beg = s.pending; /* start of bytes to update crc */
|
||||
|
||||
while (s.gzindex < (s.gzhead.extra.length & 0xffff)) {
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
flush_pending(strm);
|
||||
beg = s.pending;
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);
|
||||
s.gzindex++;
|
||||
}
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
if (s.gzindex === s.gzhead.extra.length) {
|
||||
s.gzindex = 0;
|
||||
s.status = NAME_STATE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
s.status = NAME_STATE;
|
||||
}
|
||||
}
|
||||
if (s.status === NAME_STATE) {
|
||||
if (s.gzhead.name/* != Z_NULL*/) {
|
||||
beg = s.pending; /* start of bytes to update crc */
|
||||
//int val;
|
||||
|
||||
do {
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
flush_pending(strm);
|
||||
beg = s.pending;
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
val = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// JS specific: little magic to add zero terminator to end of string
|
||||
if (s.gzindex < s.gzhead.name.length) {
|
||||
val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
put_byte(s, val);
|
||||
} while (val !== 0);
|
||||
|
||||
if (s.gzhead.hcrc && s.pending > beg){
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
if (val === 0) {
|
||||
s.gzindex = 0;
|
||||
s.status = COMMENT_STATE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
s.status = COMMENT_STATE;
|
||||
}
|
||||
}
|
||||
if (s.status === COMMENT_STATE) {
|
||||
if (s.gzhead.comment/* != Z_NULL*/) {
|
||||
beg = s.pending; /* start of bytes to update crc */
|
||||
//int val;
|
||||
|
||||
do {
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
flush_pending(strm);
|
||||
beg = s.pending;
|
||||
if (s.pending === s.pending_buf_size) {
|
||||
val = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// JS specific: little magic to add zero terminator to end of string
|
||||
if (s.gzindex < s.gzhead.comment.length) {
|
||||
val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
put_byte(s, val);
|
||||
} while (val !== 0);
|
||||
|
||||
if (s.gzhead.hcrc && s.pending > beg) {
|
||||
strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
|
||||
}
|
||||
if (val === 0) {
|
||||
s.status = HCRC_STATE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
s.status = HCRC_STATE;
|
||||
}
|
||||
}
|
||||
if (s.status === HCRC_STATE) {
|
||||
if (s.gzhead.hcrc) {
|
||||
if (s.pending + 2 > s.pending_buf_size) {
|
||||
flush_pending(strm);
|
||||
}
|
||||
if (s.pending + 2 <= s.pending_buf_size) {
|
||||
put_byte(s, strm.adler & 0xff);
|
||||
put_byte(s, (strm.adler >> 8) & 0xff);
|
||||
strm.adler = 0; //crc32(0L, Z_NULL, 0);
|
||||
s.status = BUSY_STATE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
s.status = BUSY_STATE;
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
|
||||
/* Flush as much pending output as possible */
|
||||
if (s.pending !== 0) {
|
||||
flush_pending(strm);
|
||||
|
@ -1597,6 +1748,7 @@ function deflateEnd(strm) {
|
|||
exports.deflateInit = deflateInit;
|
||||
exports.deflateInit2 = deflateInit2;
|
||||
exports.deflateReset = deflateReset;
|
||||
exports.deflateSetHeader = deflateSetHeader;
|
||||
exports.deflate = deflate;
|
||||
exports.deflateEnd = deflateEnd;
|
||||
exports.deflateInfo = 'pako deflate (from Nodeca project)';
|
||||
|
@ -1604,7 +1756,6 @@ exports.deflateInfo = 'pako deflate (from Nodeca project)';
|
|||
/* Not implemented
|
||||
exports.deflateSetDictionary = deflateSetDictionary;
|
||||
exports.deflateParams = deflateParams;
|
||||
exports.deflateSetHeader = deflateSetHeader;
|
||||
exports.deflateBound = deflateBound;
|
||||
exports.deflatePending = deflatePending;
|
||||
*/
|
|
@ -4,12 +4,13 @@
|
|||
'use strict';
|
||||
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var assert = require('assert');
|
||||
|
||||
var pako_utils = require('../lib/utils/common');
|
||||
var pako = require('../index');
|
||||
var pako = require('../index');
|
||||
var cmp = require('./helpers').cmpBuf;
|
||||
|
||||
|
||||
function a2s(array) {
|
||||
|
@ -29,6 +30,36 @@ describe('Gzip special cases', function() {
|
|||
assert.equal(a2s(inflator.header.extra), 'test extra');
|
||||
});
|
||||
|
||||
it('Write custom headers', function() {
|
||||
var data = ' ';
|
||||
|
||||
var deflator = new pako.Deflate({
|
||||
gzip: true,
|
||||
header: {
|
||||
hcrc: true,
|
||||
time: 1234567,
|
||||
os: 15,
|
||||
name: 'test name',
|
||||
comment: 'test comment',
|
||||
extra: [4,5,6]
|
||||
}
|
||||
});
|
||||
deflator.push(data, true);
|
||||
|
||||
var inflator = new pako.Inflate({ to: 'string' });
|
||||
inflator.push(deflator.result, true);
|
||||
|
||||
assert.equal(inflator.err, 0);
|
||||
assert.equal(inflator.result, data);
|
||||
|
||||
var header = inflator.header;
|
||||
assert.equal(header.time, 1234567);
|
||||
assert.equal(header.os, 15);
|
||||
assert.equal(header.name, 'test name');
|
||||
assert.equal(header.comment, 'test comment');
|
||||
assert(cmp(header.extra, [4,5,6]));
|
||||
});
|
||||
|
||||
it('Read stream with SYNC marks', function() {
|
||||
var inflator, strm, _in, len, pos = 0, i = 0;
|
||||
var data = fs.readFileSync(path.join(__dirname, 'fixtures/gzip-joined.gz'));
|
||||
|
|
Loading…
Add table
Reference in a new issue