Comparing version 0.1.11 to 0.2.0
@@ -5,53 +5,22 @@ 'use strict'; | ||
var Parse = require("../unzip").Parse; | ||
var Writer = require("fstream").Writer; | ||
var Writable = require('readable-stream/writable'); | ||
var Parse = require('./parse'); | ||
var Writer = require('fstream').Writer; | ||
var util = require('util'); | ||
var path = require('path'); | ||
var inherits = require('util').inherits; | ||
inherits(Extract, Writable); | ||
util.inherits(Extract, Parse); | ||
function Extract (opts) { | ||
var self = this; | ||
if (!(this instanceof Extract)) { | ||
if (!(this instanceof Extract)) | ||
return new Extract(opts); | ||
} | ||
Writable.apply(this); | ||
this._opts = opts || { verbose: false }; | ||
Parse.call(this); | ||
this._parser = Parse(this._opts); | ||
this._parser.on('error', function(err) { | ||
self.emit('error', err); | ||
this.on('entry', entry => { | ||
if (entry.type == 'Directory') return; | ||
entry.pipe(Writer({ | ||
path: path.join(opts.path,entry.path) | ||
})) | ||
.on('error',e => this.emit('error',e)); | ||
}); | ||
this.on('finish', function() { | ||
self._parser.end(); | ||
}); | ||
var writer = Writer({ | ||
type: 'Directory', | ||
path: opts.path | ||
}); | ||
writer.on('error', function(err) { | ||
self.emit('error', err); | ||
}); | ||
writer.on('close', function() { | ||
self.emit('close') | ||
}); | ||
this.on('pipe', function(source) { | ||
if (opts.verbose && source.path) { | ||
console.log('Archive: ', source.path); | ||
} | ||
}); | ||
this._parser.pipe(writer); | ||
} | ||
Extract.prototype._write = function (chunk, encoding, callback) { | ||
if (this._parser.write(chunk)) { | ||
return callback(); | ||
} | ||
return this._parser.once('drain', callback); | ||
}; |
250
lib/parse.js
@@ -1,18 +0,16 @@ | ||
'use strict'; | ||
module.exports = Parse.create = Parse; | ||
require("setimmediate"); | ||
var Transform = require('readable-stream/transform'); | ||
var inherits = require('util').inherits; | ||
var util = require('util'); | ||
var zlib = require('zlib'); | ||
var Stream = require('stream'); | ||
var binary = require('binary'); | ||
var PullStream = require('pullstream'); | ||
var MatchStream = require('match-stream'); | ||
var Entry = require('./entry'); | ||
var PullStream = require('./PullStream'); | ||
inherits(Parse, Transform); | ||
function noopStream() { | ||
return Stream.Transform({ | ||
transform: (d,e,cb) => cb() | ||
}); | ||
} | ||
function Parse(opts) { | ||
var self = this; | ||
if (!(this instanceof Parse)) { | ||
@@ -22,40 +20,25 @@ return new Parse(opts); | ||
Transform.call(this, { lowWaterMark: 0 }); | ||
this._opts = opts || { verbose: false }; | ||
this._hasEntryListener = false; | ||
this._pullStream = new PullStream(); | ||
this._pullStream.on("error", function (e) { | ||
self.emit('error', e); | ||
}); | ||
this._pullStream.once("finish", function () { | ||
Transform.prototype.end.call(self); | ||
self.emit('close'); | ||
}); | ||
PullStream.call(this, this._opts); | ||
this.on('finish',() => this.emit('close')) ; | ||
this._readRecord(); | ||
} | ||
util.inherits(Parse, PullStream); | ||
Parse.prototype._readRecord = function () { | ||
var self = this; | ||
this._pullStream.pull(4, function (err, data) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
if (data.length === 0) { | ||
this.pull(4).then(data => { | ||
if (data.length === 0) | ||
return; | ||
} | ||
var signature = data.readUInt32LE(0); | ||
if (signature === 0x04034b50) { | ||
self._readFile(); | ||
} else if (signature === 0x02014b50) { | ||
self._readCentralDirectoryFileHeader(); | ||
} else if (signature === 0x06054b50) { | ||
self._readEndOfCentralDirectoryRecord(); | ||
} else { | ||
err = new Error('invalid signature: 0x' + signature.toString(16)); | ||
self.emit('error', err); | ||
} | ||
if (signature === 0x04034b50) | ||
this._readFile(); | ||
else if (signature === 0x02014b50) | ||
this._readCentralDirectoryFileHeader(); | ||
else if (signature === 0x06054b50) | ||
this._readEndOfCentralDirectoryRecord(); | ||
else | ||
this.emit('error', Error('invalid signature: 0x' + signature.toString(16))); | ||
}); | ||
@@ -65,8 +48,3 @@ }; | ||
Parse.prototype._readFile = function () { | ||
var self = this; | ||
this._pullStream.pull(26, function (err, data) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
this.pull(26).then(data => { | ||
var vars = binary.parse(data) | ||
@@ -85,13 +63,12 @@ .word16lu('versionsNeededToExtract') | ||
return self._pullStream.pull(vars.fileNameLength, function (err, fileName) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
return this.pull(vars.fileNameLength).then(fileName => { | ||
fileName = fileName.toString('utf8'); | ||
var entry = new Entry(); | ||
var entry = Stream.PassThrough(); | ||
entry.autodrain = () => this.pipe(noopStream()); | ||
entry.path = fileName; | ||
entry.props = {}; | ||
entry.props.path = fileName; | ||
entry.type = (vars.compressedSize === 0 && /[\/\\]$/.test(fileName)) ? 'Directory' : 'File'; | ||
if (self._opts.verbose) { | ||
if (this._opts.verbose) { | ||
if (entry.type === 'Directory') { | ||
@@ -108,69 +85,21 @@ console.log(' creating:', fileName); | ||
var hasEntryListener = self._hasEntryListener; | ||
if (hasEntryListener) { | ||
self.emit('entry', entry); | ||
} | ||
this.emit('entry', entry); | ||
this.pull(vars.extraFieldLength).then(extraField => { | ||
var fileSizeKnown = !(vars.flags & 0x08); | ||
self._pullStream.pull(vars.extraFieldLength, function (err, extraField) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
if (vars.compressionMethod === 0) { | ||
self._pullStream.pull(vars.compressedSize, function (err, compressedData) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
var inflater = vars.compressionMethod ? zlib.createInflateRaw() : Stream.PassThrough(); | ||
if (!this.listenerCount('entry')) | ||
inflater = noopStream(); | ||
if (hasEntryListener) { | ||
entry.write(compressedData); | ||
entry.end(); | ||
} | ||
return self._readRecord(); | ||
}); | ||
if (fileSizeKnown) { | ||
entry.size = vars.uncompressedSize; | ||
this.stream(vars.compressedSize) | ||
.pipe(inflater) | ||
.on('error', e => this.emit('error',err)) | ||
.pipe(entry) | ||
.on('finish', () => this._readRecord()); | ||
} else { | ||
var fileSizeKnown = !(vars.flags & 0x08); | ||
var inflater = zlib.createInflateRaw(); | ||
inflater.on('error', function (err) { | ||
self.emit('error', err); | ||
}); | ||
if (fileSizeKnown) { | ||
entry.size = vars.uncompressedSize; | ||
if (hasEntryListener) { | ||
entry.on('finish', self._readRecord.bind(self)); | ||
self._pullStream.pipe(vars.compressedSize, inflater).pipe(entry); | ||
} else { | ||
self._pullStream.drain(vars.compressedSize, function (err) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
self._readRecord(); | ||
}); | ||
} | ||
} else { | ||
var descriptorSig = new Buffer(4); | ||
descriptorSig.writeUInt32LE(0x08074b50, 0); | ||
var matchStream = new MatchStream({ pattern: descriptorSig }, function (buf, matched, extra) { | ||
if (hasEntryListener) { | ||
if (!matched) { | ||
return this.push(buf); | ||
} | ||
this.push(buf); | ||
} | ||
setImmediate(function() { | ||
self._pullStream.unpipe(); | ||
self._pullStream.prepend(extra); | ||
self._processDataDescriptor(entry); | ||
}); | ||
return this.push(null); | ||
}); | ||
self._pullStream.pipe(matchStream); | ||
if (hasEntryListener) { | ||
matchStream.pipe(inflater).pipe(entry); | ||
} | ||
} | ||
// TODO - allow pullstream to match | ||
this.emit('error',new Error('MatchStream not implemented')); | ||
} | ||
@@ -183,8 +112,3 @@ }); | ||
Parse.prototype._processDataDescriptor = function (entry) { | ||
var self = this; | ||
this._pullStream.pull(16, function (err, data) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
this.pull(16).then(data => { | ||
var vars = binary.parse(data) | ||
@@ -198,3 +122,3 @@ .word32lu('dataDescriptorSignature') | ||
entry.size = vars.uncompressedSize; | ||
self._readRecord(); | ||
this._readRecord(); | ||
}); | ||
@@ -204,8 +128,4 @@ }; | ||
Parse.prototype._readCentralDirectoryFileHeader = function () { | ||
var self = this; | ||
this._pullStream.pull(42, function (err, data) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
this.pull(42).then(data => { | ||
var vars = binary.parse(data) | ||
@@ -230,17 +150,9 @@ .word16lu('versionMadeBy') | ||
return self._pullStream.pull(vars.fileNameLength, function (err, fileName) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
return this.pull(vars.fileNameLength).then(fileName => { | ||
fileName = fileName.toString('utf8'); | ||
self._pullStream.pull(vars.extraFieldLength, function (err, extraField) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
self._pullStream.pull(vars.fileCommentLength, function (err, fileComment) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
return self._readRecord(); | ||
this.pull(vars.extraFieldLength).then(extraField => { | ||
this.pull(vars.fileCommentLength).then(fileComment => { | ||
return this._readRecord(); | ||
}); | ||
@@ -253,8 +165,4 @@ }); | ||
Parse.prototype._readEndOfCentralDirectoryRecord = function () { | ||
var self = this; | ||
this._pullStream.pull(18, function (err, data) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
this.pull(18).then(data => { | ||
var vars = binary.parse(data) | ||
@@ -271,14 +179,8 @@ .word16lu('diskNumber') | ||
if (vars.commentLength) { | ||
setImmediate(function() { | ||
self._pullStream.pull(vars.commentLength, function (err, comment) { | ||
if (err) { | ||
return self.emit('error', err); | ||
} | ||
this.pull(vars.commentLength).then(comment => { | ||
comment = comment.toString('utf8'); | ||
return self._pullStream.end(); | ||
return this.end(); | ||
}); | ||
}); | ||
} else { | ||
self._pullStream.end(); | ||
this.end(); | ||
} | ||
@@ -288,32 +190,2 @@ }); | ||
Parse.prototype._transform = function (chunk, encoding, callback) { | ||
if (this._pullStream.write(chunk)) { | ||
return callback(); | ||
} | ||
this._pullStream.once('drain', callback); | ||
}; | ||
Parse.prototype.pipe = function (dest, opts) { | ||
var self = this; | ||
if (typeof dest.add === "function") { | ||
self.on("entry", function (entry) { | ||
dest.add(entry); | ||
}) | ||
} | ||
return Transform.prototype.pipe.apply(this, arguments); | ||
}; | ||
Parse.prototype.end = function(d,e,cb) { | ||
if (typeof cb === 'function') | ||
cb(); | ||
}; | ||
Parse.prototype.addListener = function(type, listener) { | ||
if ('entry' === type) { | ||
this._hasEntryListener = true; | ||
} | ||
return Transform.prototype.addListener.call(this, type, listener); | ||
}; | ||
Parse.prototype.on = Parse.prototype.addListener; | ||
module.exports = Parse; |
{ | ||
"name": "unzipper", | ||
"version": "0.1.11", | ||
"description": "Unzip cross-platform streaming API compatible with fstream and fs.ReadStream", | ||
"version": "0.2.0", | ||
"description": "Unzip cross-platform streaming API ", | ||
"author": "Evan Oxfeld <eoxfeld@gmail.com>", | ||
"maintainers": [ | ||
"contributors": [ | ||
{ | ||
"name": "Ziggy Jonsson", | ||
"email": "ziggy.jonsson.nyc@gmail.com" | ||
}, | ||
{ | ||
"name": "Evan Oxfeld", | ||
@@ -18,12 +22,10 @@ "email": "eoxfeld@gmail.com" | ||
"type": "git", | ||
"url": "https://github.com/ZJONSSON/node-unzip.git" | ||
"url": "https://github.com/ZJONSSON/node-unzipper.git" | ||
}, | ||
"license": "MIT", | ||
"dependencies": { | ||
"fstream": ">= 0.1.30 < 1", | ||
"pullstream": ">= 0.4.1 < 1", | ||
"binary": ">= 0.3.0 < 1", | ||
"readable-stream": "~1.0.31", | ||
"setimmediate": ">= 1.0.1 < 2", | ||
"match-stream": ">= 0.0.2 < 1" | ||
"binary": "~0.3.0", | ||
"bluebird": "^3.4.1", | ||
"fstream": "~1.0.10", | ||
"readable-stream": "~1.0.31" | ||
}, | ||
@@ -30,0 +32,0 @@ "devDependencies": { |
@@ -1,10 +0,11 @@ | ||
# unzip [![Build Status](https://travis-ci.org/EvanOxfeld/node-unzip.png)](https://travis-ci.org/EvanOxfeld/node-unzip) | ||
# unzipper [![Build Status](https://api.travis-ci.org/ZJONSSON/node-unzipper.png)](https://api.travis-ci.org/ZJONSSON/node-unzipper) | ||
### This is a temporary fork of [node-unzip](https://github.com/EvanOxfeld/node-unzip.git) to address `finish` and `close` event of the unzip stream. | ||
This is a fork of [node-unzip](https://github.com/EvanOxfeld/node-pullstream) which has not been maintained in a while. This fork addresses the following issues: | ||
* finish/close events are not always triggered, particular when the input stream is slower than the receivers | ||
* Any files are buffered into memory before passing on to entry | ||
Streaming cross-platform unzip tool written in node.js. | ||
The stucture of this fork is identical to the original, but uses ES6, Promises and inherit guarantees provided by node streams to ensure low memory footprint and guarantee finish/close events at the end of processing. | ||
Unzip provides simple APIs similar to [node-tar](https://github.com/isaacs/node-tar) for parsing and extracting zip files. | ||
There are no added compiled dependencies - inflation is handled by node.js's built in zlib support. Unzip is also an | ||
example use case of [node-pullstream](https://github.com/EvanOxfeld/node-pullstream). | ||
Unzipper provides simple APIs similar to [node-tar](https://github.com/isaacs/node-tar) for parsing and extracting zip files. | ||
There are no added compiled dependencies - inflation is handled by node.js's built in zlib support. | ||
@@ -14,3 +15,3 @@ ## Installation | ||
```bash | ||
$ npm install unzip | ||
$ npm install unzipper | ||
``` | ||
@@ -21,4 +22,5 @@ | ||
### Extract to a directory | ||
```javascript | ||
fs.createReadStream('path/to/archive.zip').pipe(unzip.Extract({ path: 'output/path' })); | ||
```js | ||
fs.createReadStream('path/to/archive.zip') | ||
.pipe(unzipper.Extract({ path: 'output/path' })); | ||
``` | ||
@@ -35,5 +37,5 @@ | ||
```javascript | ||
```js | ||
fs.createReadStream('path/to/archive.zip') | ||
.pipe(unzip.Parse()) | ||
.pipe(unzipper.Parse()) | ||
.on('entry', function (entry) { | ||
@@ -51,5 +53,5 @@ var fileName = entry.path; | ||
Or pipe the output of unzip.Parse() to fstream | ||
Or pipe the output of unzipper.Parse() to fstream | ||
```javascript | ||
```js | ||
var readStream = fs.createReadStream('path/to/archive.zip'); | ||
@@ -59,30 +61,7 @@ var writeStream = fstream.Writer('output/path'); | ||
readStream | ||
.pipe(unzip.Parse()) | ||
.pipe(unzipper.Parse()) | ||
.pipe(writeStream) | ||
``` | ||
## License | ||
(The MIT License) | ||
Copyright (c) 2012 - 2013 Near Infinity Corporation | ||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
## Licenses | ||
See LICENCE |
Sorry, the diff of this file is not supported yet
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
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
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
4
4
31579
25
354
62
1
+ Addedbluebird@^3.4.1
+ Addedbluebird@3.7.2(transitive)
+ Addedfstream@1.0.12(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
- Removedmatch-stream@>= 0.0.2 < 1
- Removedpullstream@>= 0.4.1 < 1
- Removedsetimmediate@>= 1.0.1 < 2
- Removedfstream@0.1.31(transitive)
- Removedgraceful-fs@3.0.12(transitive)
- Removedmatch-stream@0.0.2(transitive)
- Removednatives@1.1.6(transitive)
- Removedover@0.0.5(transitive)
- Removedpullstream@0.4.1(transitive)
- Removedsetimmediate@1.0.5(transitive)
- Removedslice-stream@1.0.0(transitive)
Updatedbinary@~0.3.0
Updatedfstream@~1.0.10