zip-stream
Advanced tools
Comparing version 0.2.3 to 0.3.0
@@ -11,3 +11,3 @@ /** | ||
var util = require('./'); | ||
var crc32 = require('buffer-crc32'); | ||
@@ -17,4 +17,5 @@ function ChecksumStream(options) { | ||
this.checksum = util.crc32(); | ||
this.digest = null; | ||
this.checksum = new Buffer(4); | ||
this.checksum.writeInt32BE(0, 0); | ||
this.digest = 0; | ||
@@ -28,3 +29,3 @@ this.rawSize = 0; | ||
if (chunk) { | ||
this.checksum.update(chunk); | ||
this.checksum = crc32(chunk, this.checksum); | ||
this.rawSize += chunk.length; | ||
@@ -37,3 +38,3 @@ } | ||
ChecksumStream.prototype._flush = function(callback) { | ||
this.digest = this.checksum.digest(); | ||
this.digest = crc32.unsigned(0, this.checksum); | ||
@@ -40,0 +41,0 @@ callback(); |
@@ -11,3 +11,3 @@ /** | ||
var util = require('./'); | ||
var crc32 = require('buffer-crc32'); | ||
@@ -17,4 +17,5 @@ function DeflateRawChecksum(options) { | ||
this.checksum = util.crc32(); | ||
this.digest = null; | ||
this.checksum = new Buffer(4); | ||
this.checksum.writeInt32BE(0, 0); | ||
this.digest = 0; | ||
@@ -34,3 +35,3 @@ this.rawSize = 0; | ||
this.once('end', function() { | ||
this.digest = this.checksum.digest(); | ||
this.digest = crc32.unsigned(0, this.checksum); | ||
}); | ||
@@ -51,3 +52,3 @@ } | ||
if (chunk) { | ||
this.checksum.update(chunk); | ||
this.checksum = crc32(chunk, this.checksum); | ||
this.rawSize += chunk.length; | ||
@@ -54,0 +55,0 @@ } |
@@ -17,4 +17,14 @@ /** | ||
util.debug = require('debug'); | ||
util.crc32 = require('./crc32'); | ||
util.convertDateTimeDos = function(input) { | ||
return new Date( | ||
((input >> 25) & 0x7f) + 1980, | ||
((input >> 21) & 0x0f) - 1, | ||
(input >> 16) & 0x1f, | ||
(input >> 11) & 0x1f, | ||
(input >> 5) & 0x3f, | ||
(input & 0x1f) << 1 | ||
); | ||
}; | ||
util.dateify = function(dateish) { | ||
@@ -49,3 +59,5 @@ dateish = dateish || new Date(); | ||
if (year < 1980) { | ||
return (1<<21) | (1<<16); | ||
return 2162688; // 1980-1-1 00:00:00 | ||
} else if (year >= 2044) { | ||
return 2141175677; // 2043-12-31 23:59:58 | ||
} | ||
@@ -52,0 +64,0 @@ |
@@ -12,2 +12,3 @@ /** | ||
var crc32 = require('buffer-crc32'); | ||
var ChecksumStream = require('./util/ChecksumStream'); | ||
@@ -80,19 +81,18 @@ var DeflateRawChecksum = require('./util/DeflateRawChecksum'); | ||
var file = data; | ||
file.offset = self.offset; | ||
data.offset = self.offset; | ||
self.write(headers.encode('file', file)); | ||
self.write(headers.encode('file', data)); | ||
function onend() { | ||
self.write(headers.encode('fileDescriptor', file)); | ||
self.write(headers.encode('fileDescriptor', data)); | ||
self._afterAppend(file); | ||
self._afterAppend(data); | ||
callback(null, file); | ||
callback(null, data); | ||
} | ||
if (file.store || source.length === 0) { | ||
file.uncompressedSize = source.length; | ||
file.compressedSize = file.uncompressedSize; | ||
file.crc32 = util.crc32(source).digest(); | ||
if (data.store || source.length === 0) { | ||
data.uncompressedSize = source.length; | ||
data.compressedSize = data.uncompressedSize; | ||
data.crc32 = crc32.unsigned(source); | ||
@@ -103,9 +103,9 @@ self.write(source); | ||
} else { | ||
var processStream = self._newProcessStream(file.store); | ||
var processStream = self._newProcessStream(data.store); | ||
processStream.once('error', callback); | ||
processStream.once('end', function() { | ||
file.crc32 = processStream.digest; | ||
file.uncompressedSize = processStream.rawSize; | ||
file.compressedSize = processStream.compressedSize || processStream.rawSize; | ||
data.crc32 = processStream.digest; | ||
data.uncompressedSize = processStream.rawSize; | ||
data.compressedSize = processStream.compressedSize || processStream.rawSize; | ||
@@ -124,22 +124,21 @@ onend(); | ||
var file = data; | ||
file.offset = self.offset; | ||
data.offset = self.offset; | ||
self.write(headers.encode('file', file)); | ||
self.write(headers.encode('file', data)); | ||
function onend() { | ||
self.write(headers.encode('fileDescriptor', file)); | ||
self.write(headers.encode('fileDescriptor', data)); | ||
self._afterAppend(file); | ||
self._afterAppend(data); | ||
callback(null, file); | ||
callback(null, data); | ||
} | ||
var processStream = self._newProcessStream(file.store); | ||
var processStream = self._newProcessStream(data.store); | ||
processStream.once('error', callback); | ||
processStream.once('end', function() { | ||
file.crc32 = processStream.digest; | ||
file.uncompressedSize = processStream.rawSize; | ||
file.compressedSize = processStream.compressedSize || processStream.rawSize; | ||
data.crc32 = processStream.digest; | ||
data.uncompressedSize = processStream.rawSize; | ||
data.compressedSize = processStream.compressedSize || processStream.rawSize; | ||
@@ -181,6 +180,19 @@ onend(); | ||
var isDir = data.type === 'directory'; | ||
if (data.name) { | ||
data.name = util.sanitizePath(data.name); | ||
if (data.name.slice(-1) === '/') { | ||
isDir = true; | ||
data.type = 'directory'; | ||
} else if (isDir) { | ||
data.name += '/'; | ||
} | ||
} | ||
if (isDir) { | ||
data.store = true; | ||
} | ||
if (typeof data.lastModifiedDate !== 'number') { | ||
@@ -199,3 +211,5 @@ data.lastModifiedDate = util.dosDateTime(data.date, this.options.forceUTC); | ||
ZipStream.prototype._normalizeSource = function(source) { | ||
if (typeof source === 'string') { | ||
if (source === null) { | ||
return new Buffer(0); | ||
} else if (typeof source === 'string') { | ||
return new Buffer(source); | ||
@@ -260,4 +274,4 @@ } else if (util.isStream(source) && !source._readableState) { | ||
if (data.type !== 'file') { | ||
callback(new Error('only "file" entries are currently supported')); | ||
if (data.type !== 'file' && data.type !== 'directory') { | ||
callback(new Error(data.type + ' entries not currently supported')); | ||
return; | ||
@@ -267,3 +281,3 @@ } | ||
if (typeof data.name !== 'string' || data.name.length === 0) { | ||
callback(new Error('filename must be a non-empty string value')); | ||
callback(new Error('entry name must be a non-empty string value')); | ||
return; | ||
@@ -270,0 +284,0 @@ } |
{ | ||
"name": "zip-stream", | ||
"version": "0.2.3", | ||
"version": "0.3.0", | ||
"description": "a streaming zip generator.", | ||
@@ -33,3 +33,4 @@ "homepage": "https://github.com/ctalkington/node-zip-stream", | ||
"lodash.defaults": "~2.4.1", | ||
"debug": "~0.7.4" | ||
"buffer-crc32": "~0.2.1", | ||
"debug": "~0.8.0" | ||
}, | ||
@@ -36,0 +37,0 @@ "devDependencies": { |
@@ -1,2 +0,2 @@ | ||
# zip-stream v0.2.3 [![Build Status](https://travis-ci.org/ctalkington/node-zip-stream.svg?branch=master)](https://travis-ci.org/ctalkington/node-zip-stream) | ||
# zip-stream v0.3.0 [![Build Status](https://travis-ci.org/ctalkington/node-zip-stream.svg?branch=master)](https://travis-ci.org/ctalkington/node-zip-stream) | ||
@@ -32,6 +32,8 @@ zip-stream is a streaming zip generator. It was built to be a successor to [zipstream](https://npmjs.org/package/zipstream). Dependencies are kept to a minimum through the use of many of node's built-in modules including the use of zlib module for compression. | ||
archive.entry('string contents', { name: 'string.txt' }, function(err, file) { | ||
archive.entry('string contents', { name: 'string.txt' }, function(err, entry) { | ||
if (err) throw err; | ||
archive.finalize(); | ||
archive.entry(null, { name: 'directory/' }, function(err, entry) { | ||
if (err) throw err; | ||
archive.finalize(); | ||
}); | ||
}); | ||
@@ -42,3 +44,3 @@ ``` | ||
#### entry(input, data, callback(err, file)) | ||
#### entry(input, data, callback(err, entry)) | ||
@@ -59,3 +61,3 @@ Appends an input source (text string, buffer, or stream) to the instance. When the instance has received, processed, and emitted the input, the callback is fired. | ||
If true, forces the file date and time to UTC. Helps with testing across timezones. | ||
If true, forces the entry date to UTC. Helps with testing across timezones. | ||
@@ -78,3 +80,3 @@ #### store `boolean` | ||
Sets the entry type. Defaults to `file`. (allowed types to be expanded in future) | ||
Sets the entry type. Defaults to `file` or `directory` if name ends with trailing slash. | ||
@@ -81,0 +83,0 @@ #### date `string|Date` |
@@ -10,3 +10,3 @@ var crypto = require('crypto'); | ||
function adjustDateByOffset(d, offset) { | ||
d = d instanceof Date || new Date(); | ||
d = (d instanceof Date) ? d : new Date(); | ||
@@ -13,0 +13,0 @@ if (offset >= 1) { |
130
test/pack.js
@@ -12,7 +12,12 @@ /*global before,describe,it */ | ||
var packer = require('../lib/zip-stream.js'); | ||
var Packer = require('../lib/zip-stream.js'); | ||
var testBuffer = binaryBuffer(1024 * 16); | ||
var testDate = new Date('Jan 03 2013 14:26:38 GMT'); | ||
var testDate2 = new Date('Feb 10 2013 10:24:42 GMT'); | ||
var testDateOverflow = new Date('Jan 1 2044 00:00:00 GMT'); | ||
var testDateUnderflow = new Date('Dec 30 1979 23:59:58 GMT'); | ||
describe('pack', function() { | ||
@@ -26,3 +31,3 @@ before(function() { | ||
it('should append Buffer sources', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true | ||
@@ -34,3 +39,3 @@ }); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, 'f717caf8928848bb90963dfaae3f4794907ec9a3'); | ||
assert.equal(testStream.digest, '6576fe7e1ef7aa22b51c1c18a837176602c1b3b6'); | ||
done(); | ||
@@ -41,3 +46,3 @@ }); | ||
archive.entry(binaryBuffer(20000), { name: 'buffer.txt', date: testDate }); | ||
archive.entry(testBuffer, { name: 'buffer.txt', date: testDate }); | ||
archive.finalize(); | ||
@@ -47,3 +52,3 @@ }); | ||
it('should append Stream sources', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true | ||
@@ -66,3 +71,3 @@ }); | ||
it('should append multiple sources', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true | ||
@@ -74,3 +79,3 @@ }); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, '404d35e59ee6d510774445cd8710bf37e1303aae'); | ||
assert.equal(testStream.digest, '696fec6b6267159b6d0cff2f59cdc0b9259f14a1'); | ||
done(); | ||
@@ -83,3 +88,3 @@ }); | ||
if (err) throw err; | ||
archive.entry(binaryBuffer(20000), { name: 'buffer.txt', date: testDate2 }, function(err) { | ||
archive.entry(testBuffer, { name: 'buffer.txt', date: testDate2 }, function(err) { | ||
if (err) throw err; | ||
@@ -98,3 +103,3 @@ archive.entry(fs.createReadStream('test/fixtures/test.txt'), { name: 'stream.txt', date: testDate2 }, function(err) { | ||
it('should support STORE for Buffer sources', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true | ||
@@ -106,3 +111,3 @@ }); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, 'a8b0fdf44cc200f4b5e5361e0e4e59c8cf136c85'); | ||
assert.equal(testStream.digest, '7919cdab61f79a3384657f1121deb1892f2f062e'); | ||
done(); | ||
@@ -113,3 +118,3 @@ }); | ||
archive.entry(binaryBuffer(20000), { name: 'buffer.txt', date: testDate, store: true }); | ||
archive.entry(testBuffer, { name: 'buffer.txt', date: testDate, store: true }); | ||
archive.finalize(); | ||
@@ -119,3 +124,3 @@ }); | ||
it('should support STORE for Stream sources', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true | ||
@@ -138,3 +143,3 @@ }); | ||
it('should support archive and file comments', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
comment: 'this is a zip comment', | ||
@@ -147,3 +152,3 @@ forceUTC: true | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, '2fad5e4b36b5030a36e218273c1b6cb94c238208'); | ||
assert.equal(testStream.digest, '0ca2a710775e8645d8bb170f12ef5372abba4b77'); | ||
done(); | ||
@@ -154,3 +159,3 @@ }); | ||
archive.entry(binaryBuffer(20000), { name: 'buffer.txt', date: testDate, comment: 'this is a file comment' }); | ||
archive.entry(testBuffer, { name: 'buffer.txt', date: testDate, comment: 'this is a file comment' }); | ||
archive.finalize(); | ||
@@ -160,3 +165,3 @@ }); | ||
it('should STORE files when compression level is zero', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true, | ||
@@ -169,3 +174,3 @@ level: 0 | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, 'a8b0fdf44cc200f4b5e5361e0e4e59c8cf136c85'); | ||
assert.equal(testStream.digest, '7919cdab61f79a3384657f1121deb1892f2f062e'); | ||
done(); | ||
@@ -176,3 +181,3 @@ }); | ||
archive.entry(binaryBuffer(20000), { name: 'buffer.txt', date: testDate }); | ||
archive.entry(testBuffer, { name: 'buffer.txt', date: testDate }); | ||
archive.finalize(); | ||
@@ -182,3 +187,3 @@ }); | ||
it('should properly handle utf8 encoded characters in file names and comments', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true | ||
@@ -190,3 +195,3 @@ }); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, '78983b5596afa4a7844e0fb16ba8adcdaecfa4fd'); | ||
assert.equal(testStream.digest, '554638f3269bd13d21657da6f1d30e8502405274'); | ||
done(); | ||
@@ -197,5 +202,5 @@ }); | ||
archive.entry(binaryBuffer(20000), { name: 'àáâãäçèéêëìíîïñòóôõöùúûüýÿ.txt', date: testDate, comment: 'àáâãäçèéêëìíîïñòóôõöùúûüýÿ' }, function(err) { | ||
archive.entry(testBuffer, { name: 'àáâãäçèéêëìíîïñòóôõöùúûüýÿ.txt', date: testDate, comment: 'àáâãäçèéêëìíîïñòóôõöùúûüýÿ' }, function(err) { | ||
if (err) throw err; | ||
archive.entry(binaryBuffer(20000), { name: 'ÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ.txt', date: testDate2, comment: 'ÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ' }, function(err) { | ||
archive.entry(testBuffer, { name: 'ÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ.txt', date: testDate2, comment: 'ÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ' }, function(err) { | ||
if (err) throw err; | ||
@@ -208,3 +213,3 @@ archive.finalize(); | ||
it('should append zero length sources', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true | ||
@@ -227,2 +232,3 @@ }); | ||
archive.entry(fs.createReadStream('test/fixtures/empty.txt'), { name: 'stream.txt', date: testDate }, function(err) { | ||
if (err) throw err; | ||
archive.finalize(); | ||
@@ -235,3 +241,3 @@ }); | ||
it('should support setting file mode (permissions)', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true | ||
@@ -243,3 +249,3 @@ }); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, 'a6abe53ecf77cf64ff9c024b55200695656e1bf1'); | ||
assert.equal(testStream.digest, '133dee4946ae133a723a728b56775672729d6246'); | ||
done(); | ||
@@ -250,3 +256,3 @@ }); | ||
archive.entry(binaryBuffer(20000), { name: 'buffer.txt', date: testDate, mode: 0644 }); | ||
archive.entry(testBuffer, { name: 'buffer.txt', date: testDate, mode: 0644 }); | ||
archive.finalize(); | ||
@@ -256,3 +262,3 @@ }); | ||
it('should support creating an empty zip', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true | ||
@@ -274,3 +280,3 @@ }); | ||
it('should support compressing images for Buffer sources', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true | ||
@@ -293,3 +299,3 @@ }); | ||
it('should support compressing images for Stream sources', function(done) { | ||
var archive = new packer({ | ||
var archive = new Packer({ | ||
forceUTC: true | ||
@@ -311,4 +317,70 @@ }); | ||
it('should prevent UInt32 under/overflow of dates', function(done) { | ||
var archive = new Packer({ | ||
forceUTC: true | ||
}); | ||
var testStream = new WriteHashStream('tmp/date-boundaries.zip'); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, '99e71f01a7ec48e8a67344c18065fb06fa08c051'); | ||
done(); | ||
}); | ||
archive.pipe(testStream); | ||
archive.entry(testBuffer, { name: 'date-underflow.txt', date: testDateUnderflow }, function(err) { | ||
if (err) throw err; | ||
archive.entry(testBuffer, { name: 'date-overflow.txt', date: testDateOverflow }, function(err) { | ||
if (err) throw err; | ||
archive.finalize(); | ||
}); | ||
}); | ||
}); | ||
it('should handle data that exceeds its internal buffer size', function(done) { | ||
var archive = new Packer({ | ||
highWaterMark: 1024 * 4, | ||
forceUTC: true | ||
}); | ||
var testStream = new WriteHashStream('tmp/buffer-overflow.zip'); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, '8d5cccddfdd0fe0f31ac435005d1bdc774264f51'); | ||
done(); | ||
}); | ||
archive.pipe(testStream); | ||
archive.entry(binaryBuffer(1024 * 512), { name: 'buffer-overflow.txt', date: testDate }, function(err) { | ||
if (err) throw err; | ||
archive.entry(binaryBuffer(1024 * 1024), { name: 'buffer-overflow-store.txt', date: testDate, store: true }, function(err) { | ||
if (err) throw err; | ||
archive.finalize(); | ||
}); | ||
}); | ||
}); | ||
it('should support directory entries', function(done) { | ||
var archive = new Packer({ | ||
forceUTC: true | ||
}); | ||
var testStream = new WriteHashStream('tmp/type-directory.zip'); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, '8706b64089dfd6406343a1e7329d0a91384aaa74'); | ||
done(); | ||
}); | ||
archive.pipe(testStream); | ||
archive.entry(null, { name: 'directory/', date: testDate }); | ||
archive.finalize(); | ||
}); | ||
}); | ||
}); |
@@ -16,5 +16,10 @@ /*global before,describe,it */ | ||
var testDateDosUTC = 1109619539; | ||
var testTimezoneOffset = testDate.getTimezoneOffset(); | ||
var testDateOverflow = new Date('Jan 1 2044 00:00:00 GMT'); | ||
var testDateOverflowDosUTC = 2141175677; | ||
var testDateUnderflow = new Date('Dec 30 1979 23:59:58 GMT'); | ||
var testDateUnderflowDosUTC = 2162688; | ||
describe('utils', function() { | ||
@@ -54,36 +59,8 @@ | ||
describe('crc32', function() { | ||
describe('convertDateTimeDos(input)', function() { | ||
it('should convert DOS input into an instance of Date', function() { | ||
var actual = helpers.adjustDateByOffset(utils.convertDateTimeDos(testDateDosUTC), testTimezoneOffset); | ||
describe('crc32(data)', function() { | ||
it('should initialize CRC32 instance based on data', function() { | ||
var actual = utils.crc32('testing checksum'); | ||
assert.equal(actual.crc, 943146542); | ||
}); | ||
assert.deepEqual(actual, testDate); | ||
}); | ||
describe('#update(data)', function() { | ||
it('should update CRC32 based on data', function() { | ||
var actual = utils.crc32().update('testing checksum update'); | ||
assert.equal(actual.crc, -2042121681); | ||
}); | ||
}); | ||
describe('#digest()', function() { | ||
it('should return digest of CRC32', function() { | ||
var actual = utils.crc32('testing checksum').digest(); | ||
assert.equal(actual, 3351820753); | ||
}); | ||
}); | ||
describe('#hex()', function() { | ||
it('should return hex digest of CRC32', function() { | ||
var actual = utils.crc32('testing checksum').hex(); | ||
assert.equal(actual, 'C7C8B9D1'); | ||
}); | ||
}); | ||
}); | ||
@@ -124,2 +101,10 @@ | ||
}); | ||
it('should prevent UInt32 underflow', function () { | ||
assert.equal(utils.dosDateTime(testDateUnderflow, true), testDateUnderflowDosUTC); | ||
}); | ||
it('should prevent UInt32 overflow', function () { | ||
assert.equal(utils.dosDateTime(testDateOverflow, true), testDateOverflowDosUTC); | ||
}); | ||
}); | ||
@@ -126,0 +111,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
120
189406
4
28
1133
+ Addedbuffer-crc32@~0.2.1
+ Addedbuffer-crc32@0.2.13(transitive)
+ Addeddebug@0.8.1(transitive)
- Removeddebug@0.7.4(transitive)
Updateddebug@~0.8.0