@@ -9,7 +9,8 @@ module.exports = function (/*String|Buffer*/input, /*Number*/inputType) {
9
9
filename = "" ,
10
10
fs = Utils . FileSystem . require ( ) ,
11
11
inBuffer = null ,
12
- mainHeader = new Headers . MainHeader ( ) ;
12
+ mainHeader = new Headers . MainHeader ( ) ,
13
+ loadedEntries = false ;
13
14
14
15
if ( inputType === Utils . Constants . FILE ) {
15
16
// is a filename
@@ -22,9 +23,28 @@ module.exports = function (/*String|Buffer*/input, /*Number*/inputType) {
22
23
readMainHeader ( ) ;
23
24
} else {
24
25
// none. is a new file
26
+ loadedEntries = true ;
27
+ }
28
+
29
+ function iterateEntries ( callback ) {
30
+ const totalEntries = mainHeader . diskEntries ; // total number of entries
31
+ let index = mainHeader . offset ; // offset of first CEN header
32
+
33
+ for ( let i = 0 ; i < totalEntries ; i ++ ) {
34
+ let tmp = index ;
35
+ const entry = new ZipEntry ( inBuffer ) ;
36
+
37
+ entry . header = inBuffer . slice ( tmp , tmp += Utils . Constants . CENHDR ) ;
38
+ entry . entryName = inBuffer . slice ( tmp , tmp += entry . header . fileNameLength ) ;
39
+
40
+ index += entry . header . entryHeaderSize ;
41
+
42
+ callback ( entry ) ;
43
+ }
25
44
}
26
45
27
46
function readEntries ( ) {
47
+ loadedEntries = true ;
28
48
entryTable = { } ;
29
49
entryList = new Array ( mainHeader . diskEntries ) ; // total number of entries
30
50
var index = mainHeader . offset ; // offset of first CEN header
@@ -52,24 +72,45 @@ module.exports = function (/*String|Buffer*/input, /*Number*/inputType) {
52
72
53
73
function readMainHeader ( ) {
54
74
var i = inBuffer . length - Utils . Constants . ENDHDR , // END header size
55
- n = Math . max ( 0 , i - 0xFFFF ) , // 0xFFFF is the max zip file comment length
56
- endOffset = - 1 ; // Start offset of the END header
75
+ max = Math . max ( 0 , i - 0xFFFF ) , // 0xFFFF is the max zip file comment length
76
+ n = max ,
77
+ endStart = inBuffer . length ,
78
+ endOffset = - 1 , // Start offset of the END header
79
+ commentEnd = 0 ;
57
80
58
81
for ( i ; i >= n ; i -- ) {
59
82
if ( inBuffer [ i ] !== 0x50 ) continue ; // quick check that the byte is 'P'
60
83
if ( inBuffer . readUInt32LE ( i ) === Utils . Constants . ENDSIG ) { // "PK\005\006"
61
84
endOffset = i ;
85
+ commentEnd = i ;
86
+ endStart = i + Utils . Constants . ENDHDR ;
87
+ // We already found a regular signature, let's look just a bit further to check if there's any zip64 signature
88
+ n = i - Utils . Constants . END64HDR ;
89
+ continue ;
90
+ }
91
+
92
+ if ( inBuffer . readUInt32LE ( i ) === Utils . Constants . END64SIG ) {
93
+ // Found a zip64 signature, let's continue reading the whole zip64 record
94
+ n = max ;
95
+ continue ;
96
+ }
97
+
98
+ if ( inBuffer . readUInt32LE ( i ) == Utils . Constants . ZIP64SIG ) {
99
+ // Found the zip64 record, let's determine it's size
100
+ endOffset = i ;
101
+ endStart = i + Utils . readBigUInt64LE ( inBuffer , i + Utils . Constants . ZIP64SIZE ) + Utils . Constants . ZIP64LEAD ;
62
102
break ;
63
103
}
64
104
}
105
+
65
106
if ( ! ~ endOffset )
66
107
throw Utils . Errors . INVALID_FORMAT ;
67
108
68
- mainHeader . loadFromBinary ( inBuffer . slice ( endOffset , endOffset + Utils . Constants . ENDHDR ) ) ;
109
+ mainHeader . loadFromBinary ( inBuffer . slice ( endOffset , endStart ) ) ;
69
110
if ( mainHeader . commentLength ) {
70
- _comment = inBuffer . slice ( endOffset + Utils . Constants . ENDHDR ) ;
111
+ _comment = inBuffer . slice ( commentEnd + Utils . Constants . ENDHDR ) ;
71
112
}
72
- readEntries ( ) ;
113
+ // readEntries();
73
114
}
74
115
75
116
return {
@@ -78,6 +119,9 @@ module.exports = function (/*String|Buffer*/input, /*Number*/inputType) {
78
119
* @return Array
79
120
*/
80
121
get entries ( ) {
122
+ if ( ! loadedEntries ) {
123
+ readEntries ( ) ;
124
+ }
81
125
return entryList ;
82
126
} ,
83
127
@@ -93,13 +137,33 @@ module.exports = function (/*String|Buffer*/input, /*Number*/inputType) {
93
137
_comment = val ;
94
138
} ,
95
139
140
+ getEntryCount : function ( ) {
141
+ if ( ! loadedEntries ) {
142
+ return mainHeader . diskEntries ;
143
+ }
144
+
145
+ return entryList . length ;
146
+ } ,
147
+
148
+ forEach : function ( callback ) {
149
+ if ( ! loadedEntries ) {
150
+ iterateEntries ( callback ) ;
151
+ return ;
152
+ }
153
+
154
+ entryList . forEach ( callback ) ;
155
+ } ,
156
+
96
157
/**
97
158
* Returns a reference to the entry with the given name or null if entry is inexistent
98
159
*
99
160
* @param entryName
100
161
* @return ZipEntry
101
162
*/
102
163
getEntry : function ( /*String*/ entryName ) {
164
+ if ( ! loadedEntries ) {
165
+ readEntries ( ) ;
166
+ }
103
167
return entryTable [ entryName ] || null ;
104
168
} ,
105
169
@@ -109,6 +173,9 @@ module.exports = function (/*String|Buffer*/input, /*Number*/inputType) {
109
173
* @param entry
110
174
*/
111
175
setEntry : function ( /*ZipEntry*/ entry ) {
176
+ if ( ! loadedEntries ) {
177
+ readEntries ( ) ;
178
+ }
112
179
entryList . push ( entry ) ;
113
180
entryTable [ entry . entryName ] = entry ;
114
181
mainHeader . totalEntries = entryList . length ;
@@ -121,6 +188,9 @@ module.exports = function (/*String|Buffer*/input, /*Number*/inputType) {
121
188
* @param entryName
122
189
*/
123
190
deleteEntry : function ( /*String*/ entryName ) {
191
+ if ( ! loadedEntries ) {
192
+ readEntries ( ) ;
193
+ }
124
194
var entry = entryTable [ entryName ] ;
125
195
if ( entry && entry . isDirectory ) {
126
196
var _self = this ;
@@ -142,6 +212,9 @@ module.exports = function (/*String|Buffer*/input, /*Number*/inputType) {
142
212
* @return Array
143
213
*/
144
214
getEntryChildren : function ( /*ZipEntry*/ entry ) {
215
+ if ( ! loadedEntries ) {
216
+ readEntries ( ) ;
217
+ }
145
218
if ( entry . isDirectory ) {
146
219
var list = [ ] ,
147
220
name = entry . entryName ,
@@ -163,6 +236,9 @@ module.exports = function (/*String|Buffer*/input, /*Number*/inputType) {
163
236
* @return Buffer
164
237
*/
165
238
compressToBuffer : function ( ) {
239
+ if ( ! loadedEntries ) {
240
+ readEntries ( ) ;
241
+ }
166
242
if ( entryList . length > 1 ) {
167
243
entryList . sort ( function ( a , b ) {
168
244
var nameA = a . entryName . toLowerCase ( ) ;
@@ -237,6 +313,9 @@ module.exports = function (/*String|Buffer*/input, /*Number*/inputType) {
237
313
} ,
238
314
239
315
toAsyncBuffer : function ( /*Function*/ onSuccess , /*Function*/ onFail , /*Function*/ onItemStart , /*Function*/ onItemEnd ) {
316
+ if ( ! loadedEntries ) {
317
+ readEntries ( ) ;
318
+ }
240
319
if ( entryList . length > 1 ) {
241
320
entryList . sort ( function ( a , b ) {
242
321
var nameA = a . entryName . toLowerCase ( ) ;
0 commit comments