From b63788e0020d582a4efa47ead6aa97710c72795d Mon Sep 17 00:00:00 2001 From: 5saviahv <5saviahv@users.noreply.github.com> Date: Mon, 24 Jun 2024 16:22:59 +0300 Subject: [PATCH 1/6] test asset seems to be faulty --- test/assets/ultra.zip | Bin 4086 -> 4446 bytes test/methods/methods.test.js | 129 +++++++++++------------------------ util/utils.js | 22 +++--- 3 files changed, 50 insertions(+), 101 deletions(-) diff --git a/test/assets/ultra.zip b/test/assets/ultra.zip index 726d7ab89ba79fb1ec2f5b326a599993b72298ae..3b7cb84c4ccff3e585e13d44c379b824f547a3be 100644 GIT binary patch delta 465 zcmew+e@{s^z?+#xgn@yBfgvh(odW|B5MWT5JeAvA8kf8XQ2sl&HBg=lte>MX6Ggu! zP(GF?051Qt0aad(L1hx7#N-b=x^OH0ped0BDUq9;#;XQbg6>Lbpe^-mGLtX!sAAY;pse^kfG2U6~j;CO=>nVT7ogz{oavFP|YyqL3e?R(h2yvqo nP@<4uhD{L|Cr#{NiP>yCP?t)AB^8)7xh7BMk7c{S1By5RHzHh0 delta 494 zcmcbo^iAG7z?+#xgaHJiV%Ir<8Bjt1NbBk8!%=E+i9T-CKr<%hi*kSzZ~-+=+#tdT z5}0^PR2C-2!0@vn(*bHan37{)m~6l(4^{zj#2+*jvOpCR80C;upgU6(o9+PkJIssM5 z@+mMaXP9iy=L_WY0y&QvCa>r70doHEDKN_cX`l}#Tl4DzS(*F_%;8`WrOE5~4S}o& zK#?2FAT_~U0p4&27;=eCelNhrt_ZX(i49`Jd;v?K28aw7(^HPgzXf91GPr>%7yx7N BVod-5 diff --git a/test/methods/methods.test.js b/test/methods/methods.test.js index d3f15ca..dc4405a 100644 --- a/test/methods/methods.test.js +++ b/test/methods/methods.test.js @@ -7,6 +7,7 @@ const rimraf = require("rimraf"); const Utils = require("../../util/utils"); describe("adm-zip.js - methods handling local files", () => { + const wrapList = (c) => pth.normalize(pth.join(destination, c)); const destination = "./test/xxx"; const testFileFolderList = [ { name: "subfolder1/subfolder2/zipEntry1.txt", content: "zipEntry1" }, @@ -28,21 +29,21 @@ describe("adm-zip.js - methods handling local files", () => { afterEach((done) => rimraf(destination, done)); describe(".extractAllTo() - sync", () => { + const ultrazip = [ + "./attributes_test/asd/New Text Document.txt", + "./attributes_test/blank file.txt", + "./attributes_test/New folder/hidden.txt", + "./attributes_test/New folder/hidden_readonly.txt", + "./attributes_test/New folder/readonly.txt", + "./utes_test/New folder/somefile.txt" + ].map(wrapList); + it("zip.extractAllTo(destination)", () => { const zip = new Zip("./test/assets/ultra.zip"); zip.extractAllTo(destination); const files = walk(destination); - expect(files.sort()).to.deep.equal( - [ - pth.normalize("./test/xxx/attributes_test/asd/New Text Document.txt"), - pth.normalize("./test/xxx/attributes_test/blank file.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden_readonly.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/readonly.txt"), - pth.normalize("./test/xxx/utes_test/New folder/somefile.txt") - ].sort() - ); + expect(files.sort()).to.deep.equal(ultrazip.sort()); }); it("zip.extractAllTo(destination) - streamed file", () => { @@ -55,20 +56,20 @@ describe("adm-zip.js - methods handling local files", () => { }); describe(".extractAllToAsync - sync", () => { + const ultrazip = [ + "./attributes_test/asd/New Text Document.txt", + "./attributes_test/blank file.txt", + "./attributes_test/New folder/hidden.txt", + "./attributes_test/New folder/hidden_readonly.txt", + "./attributes_test/New folder/readonly.txt", + "./utes_test/New folder/somefile.txt" + ].map(wrapList); + it("zip.extractAllToAsync(destination)", (done) => { const zip = new Zip("./test/assets/ultra.zip"); zip.extractAllToAsync(destination, (error) => { const files = walk(destination); - expect(files.sort()).to.deep.equal( - [ - pth.normalize("./test/xxx/attributes_test/asd/New Text Document.txt"), - pth.normalize("./test/xxx/attributes_test/blank file.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden_readonly.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/readonly.txt"), - pth.normalize("./test/xxx/utes_test/New folder/somefile.txt") - ].sort() - ); + expect(files.sort()).to.deep.equal(ultrazip.sort()); done(); }); }); @@ -78,16 +79,7 @@ describe("adm-zip.js - methods handling local files", () => { // note the return return zip.extractAllToAsync(destination).then(function (data) { const files = walk(destination); - expect(files.sort()).to.deep.equal( - [ - pth.normalize("./test/xxx/attributes_test/asd/New Text Document.txt"), - pth.normalize("./test/xxx/attributes_test/blank file.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden_readonly.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/readonly.txt"), - pth.normalize("./test/xxx/utes_test/New folder/somefile.txt") - ].sort() - ); + expect(files.sort()).to.deep.equal(ultrazip.sort()); }); // no catch, it'll figure it out since the promise is rejected }); @@ -95,16 +87,7 @@ describe("adm-zip.js - methods handling local files", () => { const zip = new Zip("./test/assets/ultra.zip"); zip.extractAllToAsync(destination, false, false, (error) => { const files = walk(destination); - expect(files.sort()).to.deep.equal( - [ - pth.normalize("./test/xxx/attributes_test/asd/New Text Document.txt"), - pth.normalize("./test/xxx/attributes_test/blank file.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden_readonly.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/readonly.txt"), - pth.normalize("./test/xxx/utes_test/New folder/somefile.txt") - ].sort() - ); + expect(files.sort()).to.deep.equal(ultrazip.sort()); done(); }); }); @@ -114,16 +97,7 @@ describe("adm-zip.js - methods handling local files", () => { // note the return return zip.extractAllToAsync(destination, false, false).then(function (data) { const files = walk(destination); - expect(files.sort()).to.deep.equal( - [ - pth.normalize("./test/xxx/attributes_test/asd/New Text Document.txt"), - pth.normalize("./test/xxx/attributes_test/blank file.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden_readonly.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/readonly.txt"), - pth.normalize("./test/xxx/utes_test/New folder/somefile.txt") - ].sort() - ); + expect(files.sort()).to.deep.equal(ultrazip.sort()); }); // no catch, it'll figure it out since the promise is rejected }); @@ -131,16 +105,7 @@ describe("adm-zip.js - methods handling local files", () => { const zip = new Zip("./test/assets/ultra.zip"); zip.extractAllToAsync(destination, false, (error) => { const files = walk(destination); - expect(files.sort()).to.deep.equal( - [ - pth.normalize("./test/xxx/attributes_test/asd/New Text Document.txt"), - pth.normalize("./test/xxx/attributes_test/blank file.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden_readonly.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/readonly.txt"), - pth.normalize("./test/xxx/utes_test/New folder/somefile.txt") - ].sort() - ); + expect(files.sort()).to.deep.equal(ultrazip.sort()); done(); }); }); @@ -150,16 +115,7 @@ describe("adm-zip.js - methods handling local files", () => { // note the return return zip.extractAllToAsync(destination, false).then(function (data) { const files = walk(destination); - expect(files.sort()).to.deep.equal( - [ - pth.normalize("./test/xxx/attributes_test/asd/New Text Document.txt"), - pth.normalize("./test/xxx/attributes_test/blank file.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden_readonly.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/readonly.txt"), - pth.normalize("./test/xxx/utes_test/New folder/somefile.txt") - ].sort() - ); + expect(files.sort()).to.deep.equal(ultrazip.sort()); }); // no catch, it'll figure it out since the promise is rejected }); }); @@ -171,16 +127,9 @@ describe("adm-zip.js - methods handling local files", () => { zipEntries.forEach((e) => zip.extractEntryTo(e, destination, false, true)); const files = walk(destination); - expect(files.sort()).to.deep.equal( - [ - pth.normalize("./test/xxx/blank file.txt"), - pth.normalize("./test/xxx/hidden.txt"), - pth.normalize("./test/xxx/hidden_readonly.txt"), - pth.normalize("./test/xxx/New Text Document.txt"), - pth.normalize("./test/xxx/readonly.txt"), - pth.normalize("./test/xxx/somefile.txt") - ].sort() - ); + const ultrazip = ["blank file.txt", "hidden.txt", "hidden_readonly.txt", "New Text Document.txt", "readonly.txt", "somefile.txt"].map(wrapList); + + expect(files.sort()).to.deep.equal(ultrazip.sort()); }); it("zip.extractEntryTo(entry, destination, true, true)", () => { @@ -189,16 +138,16 @@ describe("adm-zip.js - methods handling local files", () => { zipEntries.forEach((e) => zip.extractEntryTo(e, destination, true, true)); const files = walk(destination); - expect(files.sort()).to.deep.equal( - [ - pth.normalize("./test/xxx/attributes_test/asd/New Text Document.txt"), - pth.normalize("./test/xxx/attributes_test/blank file.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/hidden_readonly.txt"), - pth.normalize("./test/xxx/attributes_test/New folder/readonly.txt"), - pth.normalize("./test/xxx/utes_test/New folder/somefile.txt") - ].sort() - ); + const ultrazip = [ + "./attributes_test/asd/New Text Document.txt", + "./attributes_test/blank file.txt", + "./attributes_test/New folder/hidden.txt", + "./attributes_test/New folder/hidden_readonly.txt", + "./attributes_test/New folder/readonly.txt", + "./utes_test/New folder/somefile.txt" + ].map(wrapList); + + expect(files.sort()).to.deep.equal(ultrazip.sort()); }); }); diff --git a/util/utils.js b/util/utils.js index 8433641..aee00f0 100644 --- a/util/utils.js +++ b/util/utils.js @@ -34,7 +34,7 @@ function Utils(opts) { module.exports = Utils; -// INSTANCED functions +// INSTANTIABLE functions Utils.prototype.makeDir = function (/*String*/ folder) { const self = this; @@ -75,10 +75,10 @@ Utils.prototype.writeFileTo = function (/*String*/ path, /*Buffer*/ content, /*B var fd; try { - fd = self.fs.openSync(path, "w", 438); // 0666 + fd = self.fs.openSync(path, "w", 0o666); // 0666 } catch (e) { - self.fs.chmodSync(path, 438); - fd = self.fs.openSync(path, "w", 438); + self.fs.chmodSync(path, 0o666); + fd = self.fs.openSync(path, "w", 0o666); } if (fd) { try { @@ -87,7 +87,7 @@ Utils.prototype.writeFileTo = function (/*String*/ path, /*Buffer*/ content, /*B self.fs.closeSync(fd); } } - self.fs.chmodSync(path, attr || 438); + self.fs.chmodSync(path, attr || 0o666); return true; }; @@ -111,13 +111,13 @@ Utils.prototype.writeFileToAsync = function (/*String*/ path, /*Buffer*/ content self.fs.exists(folder, function (exists) { if (!exists) self.makeDir(folder); - self.fs.open(path, "w", 438, function (err, fd) { + self.fs.open(path, "w", 0o666, function (err, fd) { if (err) { - self.fs.chmod(path, 438, function () { - self.fs.open(path, "w", 438, function (err, fd) { + self.fs.chmod(path, 0o666, function () { + self.fs.open(path, "w", 0o666, function (err, fd) { self.fs.write(fd, content, 0, content.length, 0, function () { self.fs.close(fd, function () { - self.fs.chmod(path, attr || 438, function () { + self.fs.chmod(path, attr || 0o666, function () { callback(true); }); }); @@ -127,13 +127,13 @@ Utils.prototype.writeFileToAsync = function (/*String*/ path, /*Buffer*/ content } else if (fd) { self.fs.write(fd, content, 0, content.length, 0, function () { self.fs.close(fd, function () { - self.fs.chmod(path, attr || 438, function () { + self.fs.chmod(path, attr || 0o666, function () { callback(true); }); }); }); } else { - self.fs.chmod(path, attr || 438, function () { + self.fs.chmod(path, attr || 0o666, function () { callback(true); }); } From 0666e3102336d33e2dfdcd306cedb32503039963 Mon Sep 17 00:00:00 2001 From: 5saviahv <5saviahv@users.noreply.github.com> Date: Mon, 24 Jun 2024 19:58:32 +0300 Subject: [PATCH 2/6] more JSDoc like comments --- adm-zip.js | 149 ++++++++++++++++++++++++++------------------------ util/utils.js | 6 +- 2 files changed, 83 insertions(+), 72 deletions(-) diff --git a/adm-zip.js b/adm-zip.js index c3bebf3..ad02398 100644 --- a/adm-zip.js +++ b/adm-zip.js @@ -113,23 +113,23 @@ module.exports = function (/**String*/ input, /** object */ options) { 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 - * + * @param {ZipEntry|string} entry ZipEntry object or String with the full path of the entry + * @param {Buffer|string} [pass] - password * @return Buffer or Null in case of error */ - readFile: function (/**Object*/ entry, /*String, Buffer*/ pass) { + readFile: function (entry, pass) { var item = getEntry(entry); return (item && item.getData(pass)) || null; }, /** * Asynchronous readFile - * @param entry ZipEntry object or String with the full path of the entry - * @param callback + * @param {ZipEntry|string} entry ZipEntry object or String with the full path of the entry + * @param {callback} callback * * @return Buffer or Null in case of error */ - readFileAsync: function (/**Object*/ entry, /**Function*/ callback) { + readFileAsync: function (entry, callback) { var item = getEntry(entry); if (item) { item.getDataAsync(callback); @@ -140,12 +140,12 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Extracts the given entry from the archive and returns the content as plain text in the given encoding - * @param entry ZipEntry object or String with the full path of the entry - * @param encoding Optional. If no encoding is specified utf8 is used + * @param {ZipEntry|string} entry - ZipEntry object or String with the full path of the entry + * @param {string} encoding - Optional. If no encoding is specified utf8 is used * * @return String */ - readAsText: function (/**Object*/ entry, /**String=*/ encoding) { + readAsText: function (entry, encoding) { var item = getEntry(entry); if (item) { var data = item.getData(); @@ -158,13 +158,13 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Asynchronous readAsText - * @param entry ZipEntry object or String with the full path of the entry - * @param callback - * @param encoding Optional. If no encoding is specified utf8 is used + * @param {ZipEntry|string} entry ZipEntry object or String with the full path of the entry + * @param {callback} callback + * @param {string} [encoding] - Optional. If no encoding is specified utf8 is used * * @return String */ - readAsTextAsync: function (/**Object*/ entry, /**Function*/ callback, /**String=*/ encoding) { + readAsTextAsync: function (entry, callback, encoding) { var item = getEntry(entry); if (item) { item.getDataAsync(function (data, err) { @@ -187,9 +187,9 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Remove the entry from the file or the entry and all it's nested directories and files if the given entry is a directory * - * @param entry + * @param {ZipEntry} entry */ - deleteFile: function (/**Object*/ entry) { + deleteFile: function (entry) { // @TODO: test deleteFile var item = getEntry(entry); if (item) { @@ -200,9 +200,9 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Adds a comment to the zip. The zip must be rewritten after adding the comment. * - * @param comment + * @param {string} comment */ - addZipComment: function (/**String*/ comment) { + addZipComment: function (comment) { // @TODO: test addZipComment _zip.comment = comment; }, @@ -220,10 +220,10 @@ module.exports = function (/**String*/ input, /** object */ options) { * Adds a comment to a specified zipEntry. The zip must be rewritten after adding the comment * The comment cannot exceed 65535 characters in length * - * @param entry - * @param comment + * @param {ZipEntry} entry + * @param {string} comment */ - addZipEntryComment: function (/**Object*/ entry, /**String*/ comment) { + addZipEntryComment: function (entry, comment) { var item = getEntry(entry); if (item) { item.comment = comment; @@ -233,10 +233,10 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Returns the comment of the specified entry * - * @param entry + * @param {ZipEntry} entry * @return String */ - getZipEntryComment: function (/**Object*/ entry) { + getZipEntryComment: function (entry) { var item = getEntry(entry); if (item) { return item.comment || ""; @@ -247,10 +247,10 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Updates the content of an existing entry inside the archive. The zip must be rewritten after updating the content * - * @param entry - * @param content + * @param {ZipEntry} entry + * @param {Buffer} content */ - updateFile: function (/**Object*/ entry, /**Buffer*/ content) { + updateFile: function (entry, content) { var item = getEntry(entry); if (item) { item.setData(content); @@ -376,13 +376,13 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Asynchronous addLocalFolder - * @param localPath - * @param callback - * @param zipPath optional path inside zip - * @param filter optional RegExp or Function if files match will + * @param {string} localPath + * @param {callback} callback + * @param {string} [zipPath] optional path inside zip + * @param {RegExp|function} [filter] optional RegExp or Function if files match will * be included. */ - addLocalFolderAsync: function (/*String*/ localPath, /*Function*/ callback, /*String*/ zipPath, /*RegExp|Function*/ filter) { + addLocalFolderAsync: function (localPath, callback, zipPath, filter) { // Prepare filter filter = filenameFilter(filter); @@ -454,7 +454,7 @@ module.exports = function (/**String*/ input, /** object */ options) { * @param {doneCallback} callback - The callback that handles the response. * */ - addLocalFolderAsync2: function (/*String*/ options, /*Function*/ callback) { + addLocalFolderAsync2: function (options, callback) { const self = this; options = typeof options === "object" ? options : { localPath: options }; localPath = pth.resolve(fixPath(options.localPath)); @@ -531,7 +531,7 @@ module.exports = function (/**String*/ input, /** object */ options) { * @param {RegExp|function} [props.filter] - optional RegExp or Function if files match will be included. * @param {function|string} [props.namefix] - optional function to help fix filename */ - addLocalFolderPromise: function (/*String*/ localPath, /* object */ props) { + addLocalFolderPromise: function (localPath, props) { return new Promise((resolve, reject) => { this.addLocalFolderAsync2(Object.assign({ localPath }, props), (err, done) => { if (err) reject(err); @@ -547,10 +547,10 @@ module.exports = function (/**String*/ input, /** object */ options) { * * @param {string} entryName * @param {Buffer | string} content - file content as buffer or utf8 coded string - * @param {string} comment - file comment - * @param {number | object} attr - number as unix file permissions, object as filesystem Stats object + * @param {string} [comment] - file comment + * @param {number | object} [attr] - number as unix file permissions, object as filesystem Stats object */ - addFile: function (/**String*/ entryName, /**Buffer*/ content, /**String*/ comment, /**Number*/ attr) { + addFile: function (entryName, content, comment, attr) { entryName = Utils.canonical(entryName); let entry = getEntry(entryName); const update = entry != null; @@ -600,9 +600,10 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Returns an array of ZipEntry objects representing the files and folders inside the archive * - * @return Array + * @param {string} [password] + * @returns Array */ - getEntries: function (/**String*/ password) { + getEntries: function (password) { _zip.password = password; return _zip ? _zip.entries : []; }, @@ -610,7 +611,7 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Returns a ZipEntry object representing the file or folder specified by ``name``. * - * @param name + * @param {string} name * @return ZipEntry */ getEntry: function (/**String*/ name) { @@ -629,26 +630,16 @@ module.exports = function (/**String*/ input, /** object */ options) { * Extracts the given entry to the given targetPath * If the entry is a directory inside the archive, the entire directory and it's subdirectories will be extracted * - * @param entry ZipEntry object or String with the full path of the entry - * @param targetPath Target folder where to write the file - * @param maintainEntryPath If maintainEntryPath is true and the entry is inside a folder, the entry folder - * 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 keepOriginalPermission The file will be set as the permission from the entry 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) + * @param {string|ZipEntry} entry - ZipEntry object or String with the full path of the entry + * @param {string} targetPath - Target folder where to write the file + * @param {boolean} [maintainEntryPath=true] - If maintainEntryPath is true and the entry is inside a folder, the entry folder will be created in targetPath as well. Default is TRUE + * @param {boolean} [overwrite=false] - If the file already exists at the target path, the file will be overwriten if this is true. + * @param {boolean} [keepOriginalPermission=false] - The file will be set as the permission from the entry if this is true. + * @param {string} [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, - /**Boolean*/ keepOriginalPermission, - /**String**/ outFileName - ) { + extractEntryTo: function (entry, targetPath, maintainEntryPath, overwrite, keepOriginalPermission, outFileName) { overwrite = get_Bool(overwrite, false); keepOriginalPermission = get_Bool(keepOriginalPermission, false); maintainEntryPath = get_Bool(maintainEntryPath, true); @@ -695,7 +686,7 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Test the archive - * + * @param {string} [pass] */ test: function (pass) { if (!_zip) { @@ -721,13 +712,14 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Extracts the entire archive to the given location * - * @param targetPath Target location - * @param overwrite If the file already exists at the target path, the file will be overwriten if this is true. + * @param {string} targetPath Target location + * @param {boolean} [overwrite=false] If the file already exists at the target path, the file will be overwriten if this is true. * Default is FALSE - * @param keepOriginalPermission The file will be set as the permission from the entry if this is true. + * @param {boolean} [keepOriginalPermission=false] The file will be set as the permission from the entry if this is true. * Default is FALSE + * @param {string|Buffer} [pass] password */ - extractAllTo: function (/**String*/ targetPath, /**Boolean*/ overwrite, /**Boolean*/ keepOriginalPermission, /*String, Buffer*/ pass) { + extractAllTo: function (targetPath, overwrite, keepOriginalPermission, pass) { overwrite = get_Bool(overwrite, false); pass = get_Str(keepOriginalPermission, pass); keepOriginalPermission = get_Bool(keepOriginalPermission, false); @@ -758,14 +750,14 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Asynchronous extractAllTo * - * @param targetPath Target location - * @param overwrite If the file already exists at the target path, the file will be overwriten if this is true. + * @param {string} targetPath Target location + * @param {boolean} [overwrite=false] If the file already exists at the target path, the file will be overwriten if this is true. * Default is FALSE - * @param keepOriginalPermission The file will be set as the permission from the entry if this is true. + * @param {boolean} [keepOriginalPermission=false] The file will be set as the permission from the entry if this is true. * Default is FALSE - * @param callback The callback will be executed when all entries are extracted successfully or any error is thrown. + * @param {function} callback The callback will be executed when all entries are extracted successfully or any error is thrown. */ - extractAllToAsync: function (/**String*/ targetPath, /**Boolean*/ overwrite, /**Boolean*/ keepOriginalPermission, /**Function*/ callback) { + extractAllToAsync: function (targetPath, overwrite, keepOriginalPermission, callback) { if (typeof overwrite === "function" && !callback) callback = overwrite; overwrite = get_Bool(overwrite, false); if (typeof keepOriginalPermission === "function" && !callback) callback = keepOriginalPermission; @@ -855,10 +847,10 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Writes the newly created zip file to disk at the specified location or if a zip was opened and no ``targetFileName`` is provided, it will overwrite the opened zip * - * @param targetFileName - * @param callback + * @param {string} targetFileName + * @param {function} callback */ - writeZip: function (/**String*/ targetFileName, /**Function*/ callback) { + writeZip: function (targetFileName, callback) { if (arguments.length === 1) { if (typeof targetFileName === "function") { callback = targetFileName; @@ -878,6 +870,15 @@ module.exports = function (/**String*/ input, /** object */ options) { } }, + /** + * + * @param {string} targetFileName + * @param {object} [props] + * @param {boolean} [props.overwrite=true] If the file already exists at the target path, the file will be overwriten if this is true. + * @param {boolean} [props.perm] The file will be set as the permission from the entry if this is true. + + * @returns {Promise} + */ writeZipPromise: function (/**String*/ targetFileName, /* object */ props) { const { overwrite, perm } = Object.assign({ overwrite: true }, props); @@ -893,6 +894,9 @@ module.exports = function (/**String*/ input, /** object */ options) { }); }, + /** + * @returns {Promise} A promise to the Buffer. + */ toBufferPromise: function () { return new Promise((resolve, reject) => { _zip.toAsyncBuffer(resolve, reject); @@ -902,10 +906,13 @@ module.exports = function (/**String*/ input, /** object */ options) { /** * Returns the content of the entire zip file as a Buffer object * - * @return Buffer + * @prop {function} [onSuccess] + * @prop {function} [onFail] + * @prop {function} [onItemStart] + * @prop {function} [onItemEnd] + * @returns {Buffer} */ - toBuffer: function (/**Function=*/ onSuccess, /**Function=*/ onFail, /**Function=*/ onItemStart, /**Function=*/ onItemEnd) { - this.valueOf = 2; + toBuffer: function (onSuccess, onFail, onItemStart, onItemEnd) { if (typeof onSuccess === "function") { _zip.toAsyncBuffer(onSuccess, onFail, onItemStart, onItemEnd); return null; diff --git a/util/utils.js b/util/utils.js index aee00f0..4002729 100644 --- a/util/utils.js +++ b/util/utils.js @@ -245,7 +245,11 @@ Utils.methodToString = function (/*Number*/ method) { } }; -// removes ".." style path elements +/** + * removes ".." style path elements + * @param {string} path - fixable path + * @returns string - fixed filepath + */ Utils.canonical = function (/*string*/ path) { if (!path) return ""; // trick normalize think path is absolute From d954ff57b1adc91b54f4ef9268fe9c97d109dd24 Mon Sep 17 00:00:00 2001 From: 5saviahv <5saviahv@users.noreply.github.com> Date: Mon, 24 Jun 2024 20:01:49 +0300 Subject: [PATCH 3/6] update helpers --- adm-zip.js | 24 ++++++++++++------------ util/utils.js | 20 +++++++++++++++++++- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/adm-zip.js b/adm-zip.js index ad02398..527067b 100644 --- a/adm-zip.js +++ b/adm-zip.js @@ -3,8 +3,9 @@ const pth = require("path"); const ZipEntry = require("./zipEntry"); const ZipFile = require("./zipFile"); -const get_Bool = (val, def) => (typeof val === "boolean" ? val : def); -const get_Str = (val, def) => (typeof val === "string" ? val : def); +const get_Bool = (...val) => Utils.findLast(val, (c) => typeof c === "boolean"); +const get_Str = (...val) => Utils.findLast(val, (c) => typeof c === "string"); +const get_Fun = (...val) => Utils.findLast(val, (c) => typeof c === "function"); const defaultOptions = { // option "noSort" : if true it disables files sorting @@ -640,10 +641,10 @@ module.exports = function (/**String*/ input, /** object */ options) { * @return Boolean */ extractEntryTo: function (entry, targetPath, maintainEntryPath, overwrite, keepOriginalPermission, outFileName) { - overwrite = get_Bool(overwrite, false); - keepOriginalPermission = get_Bool(keepOriginalPermission, false); - maintainEntryPath = get_Bool(maintainEntryPath, true); - outFileName = get_Str(outFileName, get_Str(keepOriginalPermission, undefined)); + overwrite = get_Bool(false, overwrite); + keepOriginalPermission = get_Bool(false, keepOriginalPermission); + maintainEntryPath = get_Bool(true, maintainEntryPath); + outFileName = get_Str(keepOriginalPermission, outFileName); var item = getEntry(entry); if (!item) { @@ -720,9 +721,9 @@ module.exports = function (/**String*/ input, /** object */ options) { * @param {string|Buffer} [pass] password */ extractAllTo: function (targetPath, overwrite, keepOriginalPermission, pass) { - overwrite = get_Bool(overwrite, false); + keepOriginalPermission = get_Bool(false, keepOriginalPermission); pass = get_Str(keepOriginalPermission, pass); - keepOriginalPermission = get_Bool(keepOriginalPermission, false); + overwrite = get_Bool(false, overwrite); if (!_zip) { throw new Error(Utils.Errors.NO_ZIP); } @@ -758,10 +759,9 @@ module.exports = function (/**String*/ input, /** object */ options) { * @param {function} callback The callback will be executed when all entries are extracted successfully or any error is thrown. */ extractAllToAsync: function (targetPath, overwrite, keepOriginalPermission, callback) { - if (typeof overwrite === "function" && !callback) callback = overwrite; - overwrite = get_Bool(overwrite, false); - if (typeof keepOriginalPermission === "function" && !callback) callback = keepOriginalPermission; - keepOriginalPermission = get_Bool(keepOriginalPermission, false); + callback = get_Fun(overwrite, keepOriginalPermission, callback); + keepOriginalPermission = get_Bool(false, keepOriginalPermission); + overwrite = get_Bool(false, overwrite); if (!callback) { return new Promise((resolve, reject) => { this.extractAllToAsync(targetPath, overwrite, keepOriginalPermission, function (err) { diff --git a/util/utils.js b/util/utils.js index 4002729..ff7bbaa 100644 --- a/util/utils.js +++ b/util/utils.js @@ -4,7 +4,7 @@ const Constants = require("./constants"); const Errors = require("./errors"); const isWin = typeof process === "object" && "win32" === process.platform; -const is_Obj = (obj) => obj && typeof obj === "object"; +const is_Obj = (obj) => typeof obj === "object" && obj !== null; // generate CRC32 lookup table const crcTable = new Uint32Array(256).map((t, c) => { @@ -257,6 +257,24 @@ Utils.canonical = function (/*string*/ path) { return pth.posix.join(".", safeSuffix); }; +/** + * + * @param {Array} arr + * @param {function} callback + * @returns + */ +Utils.findLast = function (arr, callback) { + if (!Array.isArray(arr)) throw new TypeError("arr is not array"); + + const len = arr.length >>> 0; + for (let i = len - 1; i >= 0; i--) { + if (callback(arr[i], i, arr)) { + return arr[i]; + } + } + return void 0; +}; + // make abolute paths taking prefix as root folder Utils.sanitize = function (/*string*/ prefix, /*string*/ name) { prefix = pth.resolve(pth.normalize(prefix)); From a2a87a706bc47614d3fc79ded8c398781cb02419 Mon Sep 17 00:00:00 2001 From: 5saviahv <5saviahv@users.noreply.github.com> Date: Mon, 24 Jun 2024 20:06:00 +0300 Subject: [PATCH 4/6] added helper function --- adm-zip.js | 4 ++-- util/utils.js | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/adm-zip.js b/adm-zip.js index 527067b..087ffeb 100644 --- a/adm-zip.js +++ b/adm-zip.js @@ -66,7 +66,7 @@ module.exports = function (/**String*/ input, /** object */ options) { // create variable const _zip = new ZipFile(inBuffer, opts); - const { canonical, sanitize } = Utils; + const { canonical, sanitize, zipnamefix } = Utils; function getEntry(/**Object*/ entry) { if (entry && _zip) { @@ -552,7 +552,7 @@ module.exports = function (/**String*/ input, /** object */ options) { * @param {number | object} [attr] - number as unix file permissions, object as filesystem Stats object */ addFile: function (entryName, content, comment, attr) { - entryName = Utils.canonical(entryName); + entryName = zipnamefix(entryName); let entry = getEntry(entryName); const update = entry != null; diff --git a/util/utils.js b/util/utils.js index ff7bbaa..368ca7c 100644 --- a/util/utils.js +++ b/util/utils.js @@ -224,8 +224,6 @@ Utils.crc32 = function (buf) { if (typeof buf === "string") { buf = Buffer.from(buf, "utf8"); } - // Generate crcTable - if (!crcTable.length) genCRCTable(); let len = buf.length; let crc = ~0; @@ -253,7 +251,20 @@ Utils.methodToString = function (/*Number*/ method) { Utils.canonical = function (/*string*/ path) { if (!path) return ""; // trick normalize think path is absolute - var safeSuffix = pth.posix.normalize("/" + path.split("\\").join("/")); + const safeSuffix = pth.posix.normalize("/" + path.split("\\").join("/")); + return pth.join(".", safeSuffix); +}; + +/** + * fix file names in achive + * @param {string} path - fixable path + * @returns string - fixed filepath + */ + +Utils.zipnamefix = function (path) { + if (!path) return ""; + // trick normalize think path is absolute + const safeSuffix = pth.posix.normalize("/" + path.split("\\").join("/")); return pth.posix.join(".", safeSuffix); }; From 3c7f4a9f54e4fec75edae5492608107bd0d3bd20 Mon Sep 17 00:00:00 2001 From: 5saviahv <5saviahv@users.noreply.github.com> Date: Mon, 24 Jun 2024 20:17:43 +0300 Subject: [PATCH 5/6] allow "./" in get entry --- adm-zip.js | 2 +- test/mbcs/mbcs.test.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/adm-zip.js b/adm-zip.js index 087ffeb..a445dae 100644 --- a/adm-zip.js +++ b/adm-zip.js @@ -72,7 +72,7 @@ module.exports = function (/**String*/ input, /** object */ options) { if (entry && _zip) { var item; // If entry was given as a file name - if (typeof entry === "string") item = _zip.getEntry(entry); + if (typeof entry === "string") item = _zip.getEntry(pth.posix.normalize(entry)); // if entry was given as a ZipEntry object if (typeof entry === "object" && typeof entry.entryName !== "undefined" && typeof entry.header !== "undefined") item = _zip.getEntry(entry.entryName); diff --git a/test/mbcs/mbcs.test.js b/test/mbcs/mbcs.test.js index b94c6fa..db9b8fa 100644 --- a/test/mbcs/mbcs.test.js +++ b/test/mbcs/mbcs.test.js @@ -166,7 +166,7 @@ describe("Multibyte Character Sets in Filename", () => { const zip2 = new Zip(pth.join(destination, "06-jp_name.zip")); const text1 = zip2.readAsText(file); assert(text1 === content, text1); - const entry2 = zip2.getEntry("test/" + file); + const entry2 = zip2.getEntry("./test/" + file); const text2 = zip2.readAsText(entry2); assert(text2 === content, text2); assert(entry2.header.flags_efs); @@ -192,7 +192,7 @@ describe("Multibyte Character Sets in Filename", () => { let entry1 = zip2.getEntry(file); let bufdata1 = zip2.readFile(entry1); assert(bufdata1.equals(content)); - let entry2 = zip2.getEntry("test/" + file); + let entry2 = zip2.getEntry("./test/" + file); let bufdata2 = zip2.readFile(entry2); assert(bufdata2.equals(content)); assert(entry1.header.flags_efs === false); @@ -237,7 +237,7 @@ describe("Multibyte Character Sets in Filename", () => { const zip2 = new Zip(pth.join(destination, "09-heb_name.zip")); const text1 = zip2.readAsText(file); assert(text1 === content, text1); - const entry2 = zip2.getEntry("test/" + file); + const entry2 = zip2.getEntry("./test/" + file); const text2 = zip2.readAsText(entry2); assert(text2 === content, text2); assert(entry2.header.flags_efs); @@ -289,7 +289,7 @@ describe("Multibyte Character Sets in Filename", () => { let entry1 = zip2.getEntry(file); let text1 = zip2.readAsText(entry1, "utf16le"); assert(text1 === content, text1); - let entry2 = zip2.getEntry("test/" + file); + let entry2 = zip2.getEntry("./test/" + file); let text2 = zip2.readAsText(entry2, "utf16le"); assert(text2 === content, text2); assert(entry1.header.flags_efs === false); @@ -312,7 +312,7 @@ describe("Multibyte Character Sets in Filename", () => { let entry1 = zip2.getEntry(file); let text1 = zip2.readAsText(entry1, "utf16le"); assert(text1 === content, text1); - let entry2 = zip2.getEntry("test/" + file); + let entry2 = zip2.getEntry("./test/" + file); let text2 = zip2.readAsText(entry2, "utf16le"); assert(text2 === content, text2); assert(entry1.header.flags_efs); From 1eecf552d900b4912d94fffe7c3196c1e794caf9 Mon Sep 17 00:00:00 2001 From: 5saviahv <5saviahv@users.noreply.github.com> Date: Mon, 24 Jun 2024 20:24:59 +0300 Subject: [PATCH 6/6] test for zipnamefix --- test/utils.test.js | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/test/utils.test.js b/test/utils.test.js index d195e16..ed3b32d 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -1,6 +1,6 @@ "use strict"; const { expect } = require("chai"); -const { crc32, canonical, sanitize } = require("../util/utils"); +const { crc32, canonical, sanitize, zipnamefix } = require("../util/utils"); const pth = require("path"); describe("utils", () => { @@ -70,6 +70,31 @@ describe("utils", () => { }); it("function canonical()", () => { + const tests = [ + // no name + { file: "", result: "" }, + // file has name + { file: "file", result: "file" }, + { file: "../file", result: "file" }, + { file: "../../../file", result: "file" }, + { file: "./../file", result: "file" }, + { file: "../../file", result: "file" }, + { file: "../../file1/../file2", result: "file2" }, + { file: "../subfolder/file2", result: pth.normalize("subfolder/file2") }, + { file: "../subfolder2/file2", result: pth.normalize("subfolder2/file2") }, + { file: "../subfolder/file2", result: pth.normalize("subfolder/file2") }, + { file: "../../subfolder2/file2", result: pth.normalize("subfolder2/file2") } + ]; + + for (const { file, result } of Array.from(tests)) { + tests.push({ result, file: file.split("/").join("\\") }); + } + + for (let test of tests) { + expect(canonical(test.file)).to.equal(test.result); + } + }); + it("function zipnamefix()", () => { const tests = [ // no name { file: "", result: "" }, @@ -91,7 +116,7 @@ describe("utils", () => { } for (let test of tests) { - expect(canonical(test.file)).to.equal(test.result); + expect(zipnamefix(test.file)).to.equal(test.result); } }); });