Skip to content

Commit 86bae22

Browse files
committed
add temporary folders into list
1 parent f9d1a3a commit 86bae22

File tree

3 files changed

+85
-22
lines changed

3 files changed

+85
-22
lines changed

test/assets/maximum3.zip

3.54 KB
Binary file not shown.

test/methods/methods.test.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ describe("adm-zip.js - methods handling local files", () => {
121121
});
122122

123123
describe(".extractEntryTo() - sync", () => {
124+
// each entry one by one
124125
it("zip.extractEntryTo(entry, destination, false, true)", () => {
125126
const zip = new Zip("./test/assets/ultra.zip");
126127
var zipEntries = zip.getEntries();
@@ -132,6 +133,7 @@ describe("adm-zip.js - methods handling local files", () => {
132133
expect(files.sort()).to.deep.equal(ultrazip.sort());
133134
});
134135

136+
// each entry one by one
135137
it("zip.extractEntryTo(entry, destination, true, true)", () => {
136138
const zip = new Zip("./test/assets/ultra.zip");
137139
var zipEntries = zip.getEntries();
@@ -149,6 +151,58 @@ describe("adm-zip.js - methods handling local files", () => {
149151

150152
expect(files.sort()).to.deep.equal(ultrazip.sort());
151153
});
154+
155+
it("zip.extractEntryTo(entry, destination, false, true) - [ extract folder from file where folders exists ]", () => {
156+
const zip = new Zip("./test/assets/maximum.zip");
157+
158+
zip.extractEntryTo("./attributes_test/New folder/", destination, false, true);
159+
160+
const files = walk(destination);
161+
const maximumzip = ["hidden.txt", "hidden_readonly.txt", "readonly.txt", "somefile.txt"].map(wrapList);
162+
163+
expect(files.sort()).to.deep.equal(maximumzip.sort());
164+
});
165+
166+
it("zip.extractEntryTo(entry, destination, false, true) - [ extract folder from file where folders does not exists ]", () => {
167+
const zip = new Zip("./test/assets/maximum3.zip");
168+
169+
zip.extractEntryTo("./attributes_test/New folder/", destination, false, true);
170+
171+
const files = walk(destination);
172+
const maximumzip = ["hidden.txt", "hidden_readonly.txt", "readonly.txt", "somefile.txt"].map(wrapList);
173+
174+
expect(files.sort()).to.deep.equal(maximumzip.sort());
175+
});
176+
177+
it("zip.extractEntryTo(entry, destination, true, true) - [ extract folder from file where folders exists ]", () => {
178+
const zip = new Zip("./test/assets/maximum.zip");
179+
180+
zip.extractEntryTo("./attributes_test/New folder/", destination, true, true);
181+
182+
const files = walk(destination);
183+
const maximumzip = [
184+
"./attributes_test/New folder/hidden.txt",
185+
"./attributes_test/New folder/hidden_readonly.txt",
186+
"./attributes_test/New folder/readonly.txt",
187+
"./attributes_test/New folder/somefile.txt"
188+
].map(wrapList);
189+
expect(files.sort()).to.deep.equal(maximumzip.sort());
190+
});
191+
192+
it("zip.extractEntryTo(entry, destination, true, true) - [ extract folder from file where folders does not exists ]", () => {
193+
const zip = new Zip("./test/assets/maximum3.zip");
194+
195+
zip.extractEntryTo("./attributes_test/New folder/", destination, true, true);
196+
197+
const files = walk(destination);
198+
const maximumzip = [
199+
"./attributes_test/New folder/hidden.txt",
200+
"./attributes_test/New folder/hidden_readonly.txt",
201+
"./attributes_test/New folder/readonly.txt",
202+
"./attributes_test/New folder/somefile.txt"
203+
].map(wrapList);
204+
expect(files.sort()).to.deep.equal(maximumzip.sort());
205+
});
152206
});
153207

154208
describe(".addLocalFolder() - sync", () => {

zipFile.js

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
99
mainHeader = new Headers.MainHeader(),
1010
loadedEntries = false;
1111
var password = null;
12+
const temporary = new Set();
1213

1314
// assign options
1415
const opts = options;
@@ -23,20 +24,31 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
2324
loadedEntries = true;
2425
}
2526

26-
function iterateEntries(callback) {
27-
const totalEntries = mainHeader.diskEntries; // total number of entries
28-
let index = mainHeader.offset; // offset of first CEN header
29-
30-
for (let i = 0; i < totalEntries; i++) {
31-
let tmp = index;
32-
const entry = new ZipEntry(opts, inBuffer);
33-
34-
entry.header = inBuffer.slice(tmp, (tmp += Utils.Constants.CENHDR));
35-
entry.entryName = inBuffer.slice(tmp, (tmp += entry.header.fileNameLength));
36-
37-
index += entry.header.centralHeaderSize;
27+
function makeTemporaryFolders() {
28+
const foldersList = new Set();
29+
30+
// Make list of all folders in file
31+
for (const elem of Object.keys(entryTable)) {
32+
const elements = elem.split("/");
33+
elements.pop(); // filename
34+
if (!elements.length) continue; // no folders
35+
for (let i = 0; i < elements.length; i++) {
36+
const sub = elements.slice(0, i + 1).join("/") + "/";
37+
foldersList.add(sub);
38+
}
39+
}
3840

39-
callback(entry);
41+
// create missing folders as temporary
42+
for (const elem of foldersList) {
43+
if (!(elem in entryTable)) {
44+
const tempfolder = new ZipEntry(opts);
45+
tempfolder.entryName = elem;
46+
tempfolder.attr = 0x10;
47+
tempfolder.temporary = true;
48+
entryList.push(tempfolder);
49+
entryTable[tempfolder.entryName] = tempfolder;
50+
temporary.add(tempfolder);
51+
}
4052
}
4153
}
4254

@@ -66,6 +78,8 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
6678
entryList[i] = entry;
6779
entryTable[entry.entryName] = entry;
6880
}
81+
temporary.clear();
82+
makeTemporaryFolders();
6983
}
7084

7185
function readMainHeader(/*Boolean*/ readNow) {
@@ -130,7 +144,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
130144
if (!loadedEntries) {
131145
readEntries();
132146
}
133-
return entryList;
147+
return entryList.filter((e) => !temporary.has(e));
134148
},
135149

136150
/**
@@ -154,12 +168,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
154168
},
155169

156170
forEach: function (callback) {
157-
if (!loadedEntries) {
158-
iterateEntries(callback);
159-
return;
160-
}
161-
162-
entryList.forEach(callback);
171+
this.entries.forEach(callback);
163172
},
164173

165174
/**
@@ -289,7 +298,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
289298
mainHeader.offset = 0;
290299
totalEntries = 0;
291300

292-
for (const entry of entryList) {
301+
for (const entry of this.entries) {
293302
// compress data and set local and entry header accordingly. Reason why is called first
294303
const compressedData = entry.getCompressedData();
295304
entry.header.offset = dindex;
@@ -430,7 +439,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
430439
}
431440
};
432441

433-
compress2Buffer(Array.from(entryList));
442+
compress2Buffer(Array.from(this.entries));
434443
} catch (e) {
435444
onFail(e);
436445
}

0 commit comments

Comments
 (0)