Skip to content

Commit

Permalink
Merge pull request #134 from ZJONSSON/open-extract
Browse files Browse the repository at this point in the history
Add `Open.extract` method
  • Loading branch information
ZJONSSON authored Jun 1, 2019
2 parents ee69b43 + 177ea2f commit d3761b7
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,5 +301,16 @@ async function main() {
main();
```

### Open.[method].extract()

The directory object returned from `Open.[method]` provides an `extract` method which extracts all the files to a specified `path`, with an optional `concurrency` (default: 1).

Example (with concurrency of 5):

```js
unzip.Open.file('path/to/archive.zip')
.then(d => d.extract({path: '/extraction/path', concurrency: 5}));
```

## Licenses
See LICENCE
28 changes: 28 additions & 0 deletions lib/Open/directory.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ var Promise = require('bluebird');
var BufferStream = require('../BufferStream');
var parseExtraField = require('../parseExtraField');
var Buffer = require('../Buffer');
var path = require('path');
var Writer = require('fstream').Writer;

var signature = Buffer.alloc(4);
signature.writeUInt32LE(0x06054b50,0);
Expand Down Expand Up @@ -71,6 +73,32 @@ module.exports = function centralDirectory(source, options) {

source.stream(vars.offsetToStartOfCentralDirectory).pipe(records);

vars.extract = function(opts) {
if (!opts || !opts.path) throw new Error('PATH_MISSING');
return vars.files.then(function(files) {
return Promise.map(files, function(entry) {
if (entry.type == 'Directory') return;

// to avoid zip slip (writing outside of the destination), we resolve
// the target path, and make sure it's nested in the intended
// destination, or not extract it otherwise.
var extractPath = path.join(opts.path, entry.path);
if (extractPath.indexOf(opts.path) != 0) {
return;
}
var writer = opts.getWriter ? opts.getWriter({path: extractPath}) : Writer({ path: extractPath });

return new Promise(function(resolve, reject) {
entry.stream(opts.password)
.on('error',reject)
.pipe(writer)
.on('close',resolve)
.on('error',reject);
});
},{concurrency: opts.concurrency || 1});
});
};

vars.files = Promise.mapSeries(Array(vars.numberOfRecords),function() {
return records.pull(46).then(function(data) {
var vars = binary.parse(data)
Expand Down
34 changes: 34 additions & 0 deletions test/open-extract.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict';

var test = require('tap').test;
var path = require('path');
var temp = require('temp');
var dirdiff = require('dirdiff');
var unzip = require('../');


test("extract compressed archive with open.file.extract", function (t) {
var archive = path.join(__dirname, '../testData/compressed-standard/archive.zip');

temp.mkdir('node-unzip-2', function (err, dirPath) {
if (err) {
throw err;
}
unzip.Open.file(archive)
.then(function(d) {
return d.extract({path: dirPath});
})
.then(function() {
dirdiff(path.join(__dirname, '../testData/compressed-standard/inflated'), dirPath, {
fileContents: true
}, function (err, diffs) {
if (err) {
throw err;
}
t.equal(diffs.length, 0, 'extracted directory contents');
t.end();
});
});

});
});

0 comments on commit d3761b7

Please sign in to comment.