UNPKG

10.9 kBJavaScriptView Raw
1var Utils = require("../util"),
2 Constants = Utils.Constants;
3
4/* The central directory file header */
5module.exports = function () {
6 var _verMade = 0x14,
7 _version = 0x0A,
8 _flags = 0,
9 _method = 0,
10 _time = 0,
11 _crc = 0,
12 _compressedSize = 0,
13 _size = 0,
14 _fnameLen = 0,
15 _extraLen = 0,
16
17 _comLen = 0,
18 _diskStart = 0,
19 _inattr = 0,
20 _attr = 0,
21 _offset = 0;
22
23 switch(process.platform){
24 case 'win32':
25 _verMade |= 0x0A00;
26 default:
27 _verMade |= 0x0300;
28 }
29
30 var _dataHeader = {};
31
32 function setTime(val) {
33 val = new Date(val);
34 _time = (val.getFullYear() - 1980 & 0x7f) << 25 // b09-16 years from 1980
35 | (val.getMonth() + 1) << 21 // b05-08 month
36 | val.getDate() << 16 // b00-04 hour
37
38 // 2 bytes time
39 | val.getHours() << 11 // b11-15 hour
40 | val.getMinutes() << 5 // b05-10 minute
41 | val.getSeconds() >> 1; // b00-04 seconds divided by 2
42 }
43
44 setTime(+new Date());
45
46 return {
47 get made () { return _verMade; },
48 set made (val) { _verMade = val; },
49
50 get version () { return _version; },
51 set version (val) { _version = val },
52
53 get flags () { return _flags },
54 set flags (val) { _flags = val; },
55
56 get method () { return _method; },
57 set method (val) {
58 switch (val){
59 case Constants.STORED:
60 this.version = 10;
61 case Constants.DEFLATED:
62 default:
63 this.version = 20;
64 }
65 _method = val;
66 },
67
68 get time () { return new Date(
69 ((_time >> 25) & 0x7f) + 1980,
70 ((_time >> 21) & 0x0f) - 1,
71 (_time >> 16) & 0x1f,
72 (_time >> 11) & 0x1f,
73 (_time >> 5) & 0x3f,
74 (_time & 0x1f) << 1
75 );
76 },
77 set time (val) {
78 setTime(val);
79 },
80
81 get crc () { return _crc; },
82 set crc (val) { _crc = val; },
83
84 get compressedSize () { return _compressedSize; },
85 set compressedSize (val) { _compressedSize = val; },
86
87 get size () { return _size; },
88 set size (val) { _size = val; },
89
90 get fileNameLength () { return _fnameLen; },
91 set fileNameLength (val) { _fnameLen = val; },
92
93 get extraLength () { return _extraLen },
94 set extraLength (val) { _extraLen = val; },
95
96 get commentLength () { return _comLen },
97 set commentLength (val) { _comLen = val },
98
99 get diskNumStart () { return _diskStart },
100 set diskNumStart (val) { _diskStart = val },
101
102 get inAttr () { return _inattr },
103 set inAttr (val) { _inattr = val },
104
105 get attr () { return _attr },
106 set attr (val) { _attr = val },
107
108 get offset () { return _offset },
109 set offset (val) { _offset = val },
110
111 get encripted () { return (_flags & 1) === 1 },
112
113 get entryHeaderSize () {
114 return Constants.CENHDR + _fnameLen + _extraLen + _comLen;
115 },
116
117 get realDataOffset () {
118 return _offset + Constants.LOCHDR + _dataHeader.fnameLen + _dataHeader.extraLen;
119 },
120
121 get dataHeader () {
122 return _dataHeader;
123 },
124
125 loadDataHeaderFromBinary : function(/*Buffer*/input) {
126 var data = input.slice(_offset, _offset + Constants.LOCHDR);
127 // 30 bytes and should start with "PK\003\004"
128 if (data.readUInt32LE(0) !== Constants.LOCSIG) {
129 throw new Error(Utils.Errors.INVALID_LOC);
130 }
131 _dataHeader = {
132 // version needed to extract
133 version : data.readUInt16LE(Constants.LOCVER),
134 // general purpose bit flag
135 flags : data.readUInt16LE(Constants.LOCFLG),
136 // compression method
137 method : data.readUInt16LE(Constants.LOCHOW),
138 // modification time (2 bytes time, 2 bytes date)
139 time : data.readUInt32LE(Constants.LOCTIM),
140 // uncompressed file crc-32 value
141 crc : data.readUInt32LE(Constants.LOCCRC),
142 // compressed size
143 compressedSize : data.readUInt32LE(Constants.LOCSIZ),
144 // uncompressed size
145 size : data.readUInt32LE(Constants.LOCLEN),
146 // filename length
147 fnameLen : data.readUInt16LE(Constants.LOCNAM),
148 // extra field length
149 extraLen : data.readUInt16LE(Constants.LOCEXT)
150 }
151 },
152
153 loadFromBinary : function(/*Buffer*/data) {
154 // data should be 46 bytes and start with "PK 01 02"
155 if (data.length !== Constants.CENHDR || data.readUInt32LE(0) !== Constants.CENSIG) {
156 throw new Error(Utils.Errors.INVALID_CEN);
157 }
158 // version made by
159 _verMade = data.readUInt16LE(Constants.CENVEM);
160 // version needed to extract
161 _version = data.readUInt16LE(Constants.CENVER);
162 // encrypt, decrypt flags
163 _flags = data.readUInt16LE(Constants.CENFLG);
164 // compression method
165 _method = data.readUInt16LE(Constants.CENHOW);
166 // modification time (2 bytes time, 2 bytes date)
167 _time = data.readUInt32LE(Constants.CENTIM);
168 // uncompressed file crc-32 value
169 _crc = data.readUInt32LE(Constants.CENCRC);
170 // compressed size
171 _compressedSize = data.readUInt32LE(Constants.CENSIZ);
172 // uncompressed size
173 _size = data.readUInt32LE(Constants.CENLEN);
174 // filename length
175 _fnameLen = data.readUInt16LE(Constants.CENNAM);
176 // extra field length
177 _extraLen = data.readUInt16LE(Constants.CENEXT);
178 // file comment length
179 _comLen = data.readUInt16LE(Constants.CENCOM);
180 // volume number start
181 _diskStart = data.readUInt16LE(Constants.CENDSK);
182 // internal file attributes
183 _inattr = data.readUInt16LE(Constants.CENATT);
184 // external file attributes
185 _attr = data.readUInt32LE(Constants.CENATX);
186 // LOC header offset
187 _offset = data.readUInt32LE(Constants.CENOFF);
188 },
189
190 dataHeaderToBinary : function() {
191 // LOC header size (30 bytes)
192 var data = Buffer.alloc(Constants.LOCHDR);
193 // "PK\003\004"
194 data.writeUInt32LE(Constants.LOCSIG, 0);
195 // version needed to extract
196 data.writeUInt16LE(_version, Constants.LOCVER);
197 // general purpose bit flag
198 data.writeUInt16LE(_flags, Constants.LOCFLG);
199 // compression method
200 data.writeUInt16LE(_method, Constants.LOCHOW);
201 // modification time (2 bytes time, 2 bytes date)
202 data.writeUInt32LE(_time, Constants.LOCTIM);
203 // uncompressed file crc-32 value
204 data.writeUInt32LE(_crc, Constants.LOCCRC);
205 // compressed size
206 data.writeUInt32LE(_compressedSize, Constants.LOCSIZ);
207 // uncompressed size
208 data.writeUInt32LE(_size, Constants.LOCLEN);
209 // filename length
210 data.writeUInt16LE(_fnameLen, Constants.LOCNAM);
211 // extra field length
212 data.writeUInt16LE(_extraLen, Constants.LOCEXT);
213 return data;
214 },
215
216 entryHeaderToBinary : function() {
217 // CEN header size (46 bytes)
218 var data = Buffer.alloc(Constants.CENHDR + _fnameLen + _extraLen + _comLen);
219 // "PK\001\002"
220 data.writeUInt32LE(Constants.CENSIG, 0);
221 // version made by
222 data.writeUInt16LE(_verMade, Constants.CENVEM);
223 // version needed to extract
224 data.writeUInt16LE(_version, Constants.CENVER);
225 // encrypt, decrypt flags
226 data.writeUInt16LE(_flags, Constants.CENFLG);
227 // compression method
228 data.writeUInt16LE(_method, Constants.CENHOW);
229 // modification time (2 bytes time, 2 bytes date)
230 data.writeUInt32LE(_time, Constants.CENTIM);
231 // uncompressed file crc-32 value
232 data.writeUInt32LE(_crc, Constants.CENCRC);
233 // compressed size
234 data.writeUInt32LE(_compressedSize, Constants.CENSIZ);
235 // uncompressed size
236 data.writeUInt32LE(_size, Constants.CENLEN);
237 // filename length
238 data.writeUInt16LE(_fnameLen, Constants.CENNAM);
239 // extra field length
240 data.writeUInt16LE(_extraLen, Constants.CENEXT);
241 // file comment length
242 data.writeUInt16LE(_comLen, Constants.CENCOM);
243 // volume number start
244 data.writeUInt16LE(_diskStart, Constants.CENDSK);
245 // internal file attributes
246 data.writeUInt16LE(_inattr, Constants.CENATT);
247 // external file attributes
248 data.writeUInt32LE(_attr, Constants.CENATX);
249 // LOC header offset
250 data.writeUInt32LE(_offset, Constants.CENOFF);
251 // fill all with
252 data.fill(0x00, Constants.CENHDR);
253 return data;
254 },
255
256 toString : function() {
257 return '{\n' +
258 '\t"made" : ' + _verMade + ",\n" +
259 '\t"version" : ' + _version + ",\n" +
260 '\t"flags" : ' + _flags + ",\n" +
261 '\t"method" : ' + Utils.methodToString(_method) + ",\n" +
262 '\t"time" : ' + this.time + ",\n" +
263 '\t"crc" : 0x' + _crc.toString(16).toUpperCase() + ",\n" +
264 '\t"compressedSize" : ' + _compressedSize + " bytes,\n" +
265 '\t"size" : ' + _size + " bytes,\n" +
266 '\t"fileNameLength" : ' + _fnameLen + ",\n" +
267 '\t"extraLength" : ' + _extraLen + " bytes,\n" +
268 '\t"commentLength" : ' + _comLen + " bytes,\n" +
269 '\t"diskNumStart" : ' + _diskStart + ",\n" +
270 '\t"inAttr" : ' + _inattr + ",\n" +
271 '\t"attr" : ' + _attr + ",\n" +
272 '\t"offset" : ' + _offset + ",\n" +
273 '\t"entryHeaderSize" : ' + (Constants.CENHDR + _fnameLen + _extraLen + _comLen) + " bytes\n" +
274 '}';
275 }
276 }
277};