From 86bae22bdcfe2b61f5be86c17d7e9559941ea0ca Mon Sep 17 00:00:00 2001 From: 5saviahv <5saviahv@users.noreply.github.com> Date: Tue, 25 Jun 2024 19:52:35 +0300 Subject: [PATCH] add temporary folders into list --- test/assets/maximum3.zip | Bin 0 -> 3624 bytes test/methods/methods.test.js | 54 +++++++++++++++++++++++++++++++++++ zipFile.js | 53 ++++++++++++++++++++-------------- 3 files changed, 85 insertions(+), 22 deletions(-) create mode 100644 test/assets/maximum3.zip diff --git a/test/assets/maximum3.zip b/test/assets/maximum3.zip new file mode 100644 index 0000000000000000000000000000000000000000..a38233807185a7b459590013a1c004aa168236ca GIT binary patch literal 3624 zcmWIWW@h1HVBi3v#!LqWB%ldoCzg~HWhRxDq!z~mafyCnaf-fQYPmv4YDI~HOMY@` zZfahMUP(ns0Nj|L4XDP*VKF8tCowNuAuTf}6{c4N?1VpPdS!9z&Cf|mEz$>B3)0HL zAO>{(ktV)2J0=E(f6NRFdRVlAT%HEen30*1lA0G^l$w~5pO;e!az;p?ch(UDp1Z$A zlEQRZcD>i+ddn&k-4`mO9Z_`n&c012dCq7#`oCANPrU8fvV(~;C1=OI#O!@q$5?}$ zS^NYxL#%aMl9PFQ#u}^fqzj4*| zhtpRqI50b{<@WcZJNEid?$~Fs%3uRKi+bj>br%A*1WHJ82k{~v6e!Tsk-?!OoYU{r5sZWlxwHFGB%yCzJ zz~%b%SR+%+hF$x5Hf(myWc%lAc$;w(!!zbMi*~^mTQ#n7En?1BHLUFYJSXbGo9BR0o3+nsV80jWv-PmqCCgn$I)!f=@^MGMJL4)Mz_se*9U-kL%Urc8YYK9n?OCz> zg4@k?^In-Qn9aRHF!)s6pY+S*YaE6TC>Sl+RTCNp4Gn^tzH= zM>MTe_LZ|&FNu3q`6AzJ+M8qxyV<*B4!XQeyu0%f$BLNWPGVDYWtK#id$gCtFPmJn zPHLW>Qq`-lmy9hAGvWs7g#q98G|u36NF^P#u2)94!M!%RpL}fdrCZ zaei(ptTixN4UbmClvKlvO!f@88ni0Fk`M$Gz$6LHTP~;;Mg|Fnf^OCgU;mzARB8Xv zz1Hw7oDT3tSdG~TMz-1=Xgzw%8nsD`Y~O)*r3*mzF6&Yiz@;QwCbK4~up9o8HLwI~+WC0A&BF;BVmIh0*xz zS7m_NuLQK)1K9jW4_*xWK@Bc!)*3r~1zQWF@mZ@5w^k8o?MYU=)*@H4*eq5|{SLMm wMiXbT0?=X~VCM~we~}AUY!*BH{Ry@hMhAGavH?wHU { }); describe(".extractEntryTo() - sync", () => { + // each entry one by one it("zip.extractEntryTo(entry, destination, false, true)", () => { const zip = new Zip("./test/assets/ultra.zip"); var zipEntries = zip.getEntries(); @@ -132,6 +133,7 @@ describe("adm-zip.js - methods handling local files", () => { expect(files.sort()).to.deep.equal(ultrazip.sort()); }); + // each entry one by one it("zip.extractEntryTo(entry, destination, true, true)", () => { const zip = new Zip("./test/assets/ultra.zip"); var zipEntries = zip.getEntries(); @@ -149,6 +151,58 @@ describe("adm-zip.js - methods handling local files", () => { expect(files.sort()).to.deep.equal(ultrazip.sort()); }); + + it("zip.extractEntryTo(entry, destination, false, true) - [ extract folder from file where folders exists ]", () => { + const zip = new Zip("./test/assets/maximum.zip"); + + zip.extractEntryTo("./attributes_test/New folder/", destination, false, true); + + const files = walk(destination); + const maximumzip = ["hidden.txt", "hidden_readonly.txt", "readonly.txt", "somefile.txt"].map(wrapList); + + expect(files.sort()).to.deep.equal(maximumzip.sort()); + }); + + it("zip.extractEntryTo(entry, destination, false, true) - [ extract folder from file where folders does not exists ]", () => { + const zip = new Zip("./test/assets/maximum3.zip"); + + zip.extractEntryTo("./attributes_test/New folder/", destination, false, true); + + const files = walk(destination); + const maximumzip = ["hidden.txt", "hidden_readonly.txt", "readonly.txt", "somefile.txt"].map(wrapList); + + expect(files.sort()).to.deep.equal(maximumzip.sort()); + }); + + it("zip.extractEntryTo(entry, destination, true, true) - [ extract folder from file where folders exists ]", () => { + const zip = new Zip("./test/assets/maximum.zip"); + + zip.extractEntryTo("./attributes_test/New folder/", destination, true, true); + + const files = walk(destination); + const maximumzip = [ + "./attributes_test/New folder/hidden.txt", + "./attributes_test/New folder/hidden_readonly.txt", + "./attributes_test/New folder/readonly.txt", + "./attributes_test/New folder/somefile.txt" + ].map(wrapList); + expect(files.sort()).to.deep.equal(maximumzip.sort()); + }); + + it("zip.extractEntryTo(entry, destination, true, true) - [ extract folder from file where folders does not exists ]", () => { + const zip = new Zip("./test/assets/maximum3.zip"); + + zip.extractEntryTo("./attributes_test/New folder/", destination, true, true); + + const files = walk(destination); + const maximumzip = [ + "./attributes_test/New folder/hidden.txt", + "./attributes_test/New folder/hidden_readonly.txt", + "./attributes_test/New folder/readonly.txt", + "./attributes_test/New folder/somefile.txt" + ].map(wrapList); + expect(files.sort()).to.deep.equal(maximumzip.sort()); + }); }); describe(".addLocalFolder() - sync", () => { diff --git a/zipFile.js b/zipFile.js index d269e1c..43e69fe 100644 --- a/zipFile.js +++ b/zipFile.js @@ -9,6 +9,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) { mainHeader = new Headers.MainHeader(), loadedEntries = false; var password = null; + const temporary = new Set(); // assign options const opts = options; @@ -23,20 +24,31 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) { loadedEntries = true; } - function iterateEntries(callback) { - const totalEntries = mainHeader.diskEntries; // total number of entries - let index = mainHeader.offset; // offset of first CEN header - - for (let i = 0; i < totalEntries; i++) { - let tmp = index; - const entry = new ZipEntry(opts, inBuffer); - - entry.header = inBuffer.slice(tmp, (tmp += Utils.Constants.CENHDR)); - entry.entryName = inBuffer.slice(tmp, (tmp += entry.header.fileNameLength)); - - index += entry.header.centralHeaderSize; + function makeTemporaryFolders() { + const foldersList = new Set(); + + // Make list of all folders in file + for (const elem of Object.keys(entryTable)) { + const elements = elem.split("/"); + elements.pop(); // filename + if (!elements.length) continue; // no folders + for (let i = 0; i < elements.length; i++) { + const sub = elements.slice(0, i + 1).join("/") + "/"; + foldersList.add(sub); + } + } - callback(entry); + // create missing folders as temporary + for (const elem of foldersList) { + if (!(elem in entryTable)) { + const tempfolder = new ZipEntry(opts); + tempfolder.entryName = elem; + tempfolder.attr = 0x10; + tempfolder.temporary = true; + entryList.push(tempfolder); + entryTable[tempfolder.entryName] = tempfolder; + temporary.add(tempfolder); + } } } @@ -66,6 +78,8 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) { entryList[i] = entry; entryTable[entry.entryName] = entry; } + temporary.clear(); + makeTemporaryFolders(); } function readMainHeader(/*Boolean*/ readNow) { @@ -130,7 +144,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) { if (!loadedEntries) { readEntries(); } - return entryList; + return entryList.filter((e) => !temporary.has(e)); }, /** @@ -154,12 +168,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) { }, forEach: function (callback) { - if (!loadedEntries) { - iterateEntries(callback); - return; - } - - entryList.forEach(callback); + this.entries.forEach(callback); }, /** @@ -289,7 +298,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) { mainHeader.offset = 0; totalEntries = 0; - for (const entry of entryList) { + for (const entry of this.entries) { // compress data and set local and entry header accordingly. Reason why is called first const compressedData = entry.getCompressedData(); entry.header.offset = dindex; @@ -430,7 +439,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) { } }; - compress2Buffer(Array.from(entryList)); + compress2Buffer(Array.from(this.entries)); } catch (e) { onFail(e); }