bifocal/node_modules/@tryghost/zip/lib/extract.js

60 lines
1.8 KiB
JavaScript

const errors = require('@tryghost/errors');
const defaultOptions = {};
function throwOnSymlinks(entry) {
// Check if symlink
const mode = (entry.externalFileAttributes >> 16) & 0xFFFF;
// check if it's a symlink or dir (using stat mode constants)
const IFMT = 61440;
const IFLNK = 40960;
const symlink = (mode & IFMT) === IFLNK;
if (symlink) {
throw new errors.UnsupportedMediaTypeError({
message: 'Symlinks are not allowed in the zip folder.'
});
}
}
function throwOnLargeFilenames(entry) {
if (Buffer.byteLength(entry.fileName, 'utf8') >= 254) {
throw new errors.UnsupportedMediaTypeError({
message: 'File names in the zip folder must be shorter than 254 characters.'
});
}
}
/**
* Extract
*
* - Unzip an archive to a folder
*
* @param {String} zipToExtract - full path to zip file that should be extracted
* @param {String} destination - full path of the extraction target
* @param {Object} [options]
* @param {Integer} options.defaultDirMode - Directory Mode (permissions), defaults to 0o755
* @param {Integer} options.defaultFileMode - File Mode (permissions), defaults to 0o644
* @param {Function} options.onEntry - if present, will be called with (entry, zipfile) for every entry in the zip
*/
module.exports = (zipToExtract, destination, options) => {
const opts = Object.assign({}, defaultOptions, options);
const extract = require('extract-zip');
opts.dir = destination;
const originalOnEntry = opts.onEntry;
opts.onEntry = (entry, zipfile) => {
throwOnSymlinks(entry);
throwOnLargeFilenames(entry);
if (originalOnEntry) {
originalOnEntry(entry, zipfile);
}
};
return extract(zipToExtract, opts).then(() => {
return {path: destination};
});
};