Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: cthackers/adm-zip
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9d2eb0b81575c0453a883e62480bf1600895705e
Choose a base ref
...
head repository: cthackers/adm-zip
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c5aeed445e4828172fd260ddcc51505d7e993b95
Choose a head ref
Loading
Showing with 717 additions and 487 deletions.
  1. +107 −80 adm-zip.js
  2. +20 −2 headers/entryHeader.js
  3. +247 −0 history.md
  4. +2 −1 methods/index.js
  5. +77 −0 methods/zipcrypto.js
  6. +179 −372 package-lock.json
  7. +7 −7 package.json
  8. +40 −19 test/mocha.js
  9. +24 −0 test/multibyte/test.js
  10. BIN test/multibyte/じっぷ.zip
  11. +1 −0 test/multibyte/じっぷ/じっぷ.txt
  12. +2 −2 util/fattr.js
  13. +1 −1 util/fileSystem.js
  14. +8 −1 zipEntry.js
  15. +2 −2 zipFile.js
187 changes: 107 additions & 80 deletions adm-zip.js
Original file line number Diff line number Diff line change
@@ -9,6 +9,10 @@ var ZipEntry = require("./zipEntry"),

var isWin = /^win/.test(process.platform);

function canonical(p) {
var safeSuffix = pth.normalize(p).replace(/^(\.\.(\/|\\|$))+/, '');
return pth.join('./', safeSuffix);
}

module.exports = function (/**String*/input) {
var _zip = undefined,
@@ -56,16 +60,26 @@ module.exports = function (/**String*/input) {
return null;
}

function fixPath(zipPath){
// convert windows file separators
zipPath = zipPath.split("\\").join("/");
// add separator if it wasnt given
if (zipPath.charAt(zipPath.length - 1) !== "/") {
zipPath += "/";
}
return zipPath;
}

return {
/**
* Extracts the given entry from the archive and returns the content as a Buffer object
* @param entry ZipEntry object or String with the full path of the entry
*
* @return Buffer or Null in case of error
*/
readFile: function (/**Object*/entry) {
readFile: function (/**Object*/entry, /*String, Buffer*/pass) {
var item = getEntry(entry);
return item && item.getData() || null;
return item && item.getData(pass) || null;
},

/**
@@ -208,23 +222,22 @@ module.exports = function (/**String*/input) {
* @param zipPath Optional path inside the zip
* @param zipName Optional name for the file
*/
addLocalFile: function (/**String*/localPath, /**String=*/zipPath, /**String=*/zipName) {
addLocalFile: function (/**String*/localPath, /**String=*/zipPath, /**String=*/zipName, /**String*/comment) {
if (fs.existsSync(localPath)) {
if (zipPath) {
zipPath = zipPath.split("\\").join("/");
if (zipPath.charAt(zipPath.length - 1) !== "/") {
zipPath += "/";
}
} else {
zipPath = "";
}
// fix ZipPath
zipPath = (zipPath) ? fixPath(zipPath) : "";

// p - local file name
var p = localPath.split("\\").join("/").split("/").pop();

if (zipName) {
this.addFile(zipPath + zipName, fs.readFileSync(localPath), "", 0)
} else {
this.addFile(zipPath + p, fs.readFileSync(localPath), "", 0)
}
// add file name into zippath
zipPath += (zipName) ? zipName : p;

// read file attributes
const _attr = fs.statSync(localPath);

// add file into zip file
this.addFile(zipPath, fs.readFileSync(localPath), comment, _attr)
} else {
throw new Error(Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath));
}
@@ -238,54 +251,47 @@ module.exports = function (/**String*/input) {
* @param filter optional RegExp or Function if files match will
* be included.
*/
addLocalFolder: function (/**String*/localPath, /**String=*/zipPath, /**=RegExp|Function*/filter) {
if (filter === undefined) {
filter = function () {
return true;
};
} else if (filter instanceof RegExp) {
filter = function (filter) {
return function (filename) {
return filter.test(filename);
}
}(filter);
}

if (zipPath) {
zipPath = zipPath.split("\\").join("/");
if (zipPath.charAt(zipPath.length - 1) !== "/") {
zipPath += "/";
}
} else {
zipPath = "";
}
// normalize the path first
localPath = pth.normalize(localPath);
localPath = localPath.split("\\").join("/"); //windows fix
if (localPath.charAt(localPath.length - 1) !== "/")
localPath += "/";

if (fs.existsSync(localPath)) {

var items = Utils.findFiles(localPath),
self = this;

if (items.length) {
items.forEach(function (path) {
var p = path.split("\\").join("/").replace(new RegExp(localPath.replace(/(\(|\)|\$)/g, '\\$1'), 'i'), ""); //windows fix
if (filter(p)) {
if (p.charAt(p.length - 1) !== "/") {
self.addFile(zipPath + p, fs.readFileSync(path), "", 0)
} else {
self.addFile(zipPath + p, Buffer.alloc(0), "", 0)
}
}
});
}
} else {
throw new Error(Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath));
}
},
addLocalFolder: function (/**String*/localPath, /**String=*/zipPath, /**=RegExp|Function*/filter) {
// Prepare filter
if (filter instanceof RegExp) { // if filter is RegExp wrap it
filter = (function (rx){
return function (filename) {
return rx.test(filename);
}
})(filter);
} else if ('function' !== typeof filter) { // if filter is not function we will replace it
filter = function () {
return true;
};
}

// fix ZipPath
zipPath = (zipPath) ? fixPath(zipPath) : "";

// normalize the path first
localPath = pth.normalize(localPath);

if (fs.existsSync(localPath)) {

var items = Utils.findFiles(localPath),
self = this;

if (items.length) {
items.forEach(function (filepath) {
var p = pth.relative(localPath, filepath).split("\\").join("/"); //windows fix
if (filter(p)) {
if (filepath.charAt(filepath.length - 1) !== pth.sep) {
self.addFile(zipPath + p, fs.readFileSync(filepath), "", fs.statSync(filepath));
} else {
self.addFile(zipPath + p + '/', Buffer.alloc(0), "", 0);
}
}
});
}
} else {
throw new Error(Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath));
}
},

/**
* Asynchronous addLocalFile
@@ -376,19 +382,38 @@ module.exports = function (/**String*/input) {
* @param attr
*/
addFile: function (/**String*/entryName, /**Buffer*/content, /**String*/comment, /**Number*/attr) {
// prepare new entry
var entry = new ZipEntry();
entry.entryName = entryName;
entry.comment = comment || "";

if (!attr) {
if (entry.isDirectory) {
attr = (0o40755 << 16) | 0x10; // (permissions drwxr-xr-x) + (MS-DOS directory flag)
} else {
attr = 0o644 << 16; // permissions -r-wr--r--
var isStat = ('object' === typeof attr) && (attr instanceof fs.Stats);

// last modification time from file stats
if (isStat){
entry.header.time = attr.mtime;
}

// Set file attribute
var fileattr = (entry.isDirectory) ? 0x10 : 0; // (MS-DOS directory flag)

// extended attributes field for Unix
if('win32' !== process.platform){
// set file type either S_IFDIR / S_IFREG
var unix = (entry.isDirectory) ? 0x4000 : 0x8000;

if (isStat) { // File attributes from file stats
unix |= (0xfff & attr.mode)
}else if ('number' === typeof attr){ // attr from given attr values
unix |= (0xfff & attr);
}else{ // Default values:
unix |= (entry.isDirectory) ? 0o755 : 0o644; // permissions (drwxr-xr-x) or (-r-wr--r--)
}

fileattr = (fileattr | (unix << 16)) >>> 0; // add attributes
}

entry.attr = attr;
entry.attr = fileattr;

entry.setData(content);
_zip.setEntry(entry);
@@ -435,10 +460,11 @@ module.exports = function (/**String*/input) {
* will be created in targetPath as well. Default is TRUE
* @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
* Default is FALSE
* @param outFileName String If set will override the filename of the extracted file (Only works if the entry is a file)
*
* @return Boolean
*/
extractEntryTo: function (/**Object*/entry, /**String*/targetPath, /**Boolean*/maintainEntryPath, /**Boolean*/overwrite) {
extractEntryTo: function (/**Object*/entry, /**String*/targetPath, /**Boolean*/maintainEntryPath, /**Boolean*/overwrite, /**String**/outFileName) {
overwrite = overwrite || false;
maintainEntryPath = typeof maintainEntryPath === "undefined" ? true : maintainEntryPath;

@@ -447,9 +473,9 @@ module.exports = function (/**String*/input) {
throw new Error(Utils.Errors.NO_ENTRY);
}

var entryName = item.entryName;
var entryName = canonical(item.entryName);

var target = sanitize(targetPath, maintainEntryPath ? entryName : pth.basename(entryName));
var target = sanitize(targetPath,outFileName && !item.isDirectory ? outFileName : (maintainEntryPath ? entryName : pth.basename(entryName)));

if (item.isDirectory) {
target = pth.resolve(target, "..");
@@ -460,7 +486,8 @@ module.exports = function (/**String*/input) {
if (!content) {
throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
}
var childName = sanitize(targetPath, maintainEntryPath ? child.entryName : pth.basename(child.entryName));
var name = canonical(child.entryName)
var childName = sanitize(targetPath, maintainEntryPath ? name : pth.basename(name));

Utils.writeFileTo(childName, content, overwrite);
});
@@ -482,7 +509,7 @@ module.exports = function (/**String*/input) {
* Test the archive
*
*/
test: function () {
test: function (pass) {
if (!_zip) {
return false;
}
@@ -492,7 +519,7 @@ module.exports = function (/**String*/input) {
if (entry.isDirectory) {
continue;
}
var content = _zip.entries[entry].getData();
var content = _zip.entries[entry].getData(pass);
if (!content) {
return false;
}
@@ -510,18 +537,18 @@ module.exports = function (/**String*/input) {
* @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
* Default is FALSE
*/
extractAllTo: function (/**String*/targetPath, /**Boolean*/overwrite) {
extractAllTo: function (/**String*/targetPath, /**Boolean*/overwrite, /*String, Buffer*/pass) {
overwrite = overwrite || false;
if (!_zip) {
throw new Error(Utils.Errors.NO_ZIP);
}
_zip.entries.forEach(function (entry) {
var entryName = sanitize(targetPath, entry.entryName.toString());
var entryName = sanitize(targetPath, canonical(entry.entryName.toString()));
if (entry.isDirectory) {
Utils.makeDir(entryName);
return;
}
var content = entry.getData();
var content = entry.getData(pass);
if (!content) {
throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
}
@@ -557,7 +584,7 @@ module.exports = function (/**String*/input) {
entries.forEach(function (entry) {
if (i <= 0) return; // Had an error already

var entryName = pth.normalize(entry.entryName.toString());
var entryName = pth.normalize(canonical(entry.entryName.toString()));

if (entry.isDirectory) {
Utils.makeDir(sanitize(targetPath, entryName));
22 changes: 20 additions & 2 deletions headers/entryHeader.js
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ var Utils = require("../util"),

/* The central directory file header */
module.exports = function () {
var _verMade = 0x0A,
var _verMade = 0x14,
_version = 0x0A,
_flags = 0,
_method = 0,
@@ -20,6 +20,15 @@ module.exports = function () {
_attr = 0,
_offset = 0;

switch(process.platform){
case 'win32':
_verMade |= 0x0A00;
case 'darwin':
_verMade |= 0x1300;
default:
_verMade |= 0x0300;
}

var _dataHeader = {};

function setTime(val) {
@@ -47,7 +56,16 @@ module.exports = function () {
set flags (val) { _flags = val; },

get method () { return _method; },
set method (val) { _method = val; },
set method (val) {
switch (val){
case Constants.STORED:
this.version = 10;
case Constants.DEFLATED:
default:
this.version = 20;
}
_method = val;
},

get time () { return new Date(
((_time >> 25) & 0x7f) + 1980,
Loading