All files / node-unzipper/lib extract.js

100% Statements 57/57
100% Branches 14/14
100% Functions 3/3
100% Lines 57/57

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 5828x 28x 28x 28x 28x 28x 28x 28x 28x 14x 14x 14x 14x 14x 14x 14x 14x 40x 40x 30x 30x 30x 30x 30x 30x 30x 40x 2x 2x 28x 40x 40x 40x 40x 40x 14x 14x 14x 14x 1x 14x 14x 14x 14x 14x 12x 14x 14x 14x 2x 2x 2x 2x 14x 14x 14x 14x  
module.exports = Extract;
 
var Parse = require('./parse');
var Writer = require('fstream').Writer;
var path = require('path');
var stream = require('stream');
var duplexer2 = require('duplexer2');
var Promise = require('bluebird');
 
function Extract (opts) {
  // make sure path is normalized before using it
  opts.path = path.resolve(path.normalize(opts.path));
 
  var parser = new Parse(opts);
 
  var outStream = new stream.Writable({objectMode: true});
  outStream._write = function(entry, encoding, cb) {
 
    if (entry.type == 'Directory') return cb();
 
    // 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.
    // NOTE: Need to normalize to forward slashes for UNIX OS's to properly 
    // ignore the zip slipped file entirely
    var extractPath = path.join(opts.path, entry.path.replace(/\\/g, '/'));
    if (extractPath.indexOf(opts.path) != 0) {
      return cb();
    }
 
    const writer = opts.getWriter ? opts.getWriter({path: extractPath}) :  Writer({ path: extractPath });
 
    entry.pipe(writer)
      .on('error', cb)
      .on('close', cb);
  };
 
  var extract = duplexer2(parser,outStream);
  parser.once('crx-header', function(crxHeader) {
    extract.crxHeader = crxHeader;
  });
 
  parser
    .pipe(outStream)
    .on('finish',function() {
      extract.emit('close');
    });
  
  extract.promise = function() {
    return new Promise(function(resolve, reject) {
      extract.on('close', resolve);
      extract.on('error',reject);
    });
  };
 
  return extract;
}