var Utils = require("../util"), | |
Constants = Utils.Constants; | |
/* The central directory file header */ | |
module.exports = function () { | |
var _verMade = 0x0A, | |
_version = 0x0A, | |
_flags = 0, | |
_method = 0, | |
_time = 0, | |
_crc = 0, | |
_compressedSize = 0, | |
_size = 0, | |
_fnameLen = 0, | |
_extraLen = 0, | |
_comLen = 0, | |
_diskStart = 0, | |
_inattr = 0, | |
_attr = 0, | |
_offset = 0; | |
var _dataHeader = {}; | |
function setTime(val) { | |
var val = new Date(val); | |
_time = (val.getFullYear() - 1980 & 0x7f) << 25 // b09-16 years from 1980 | |
| (val.getMonth() + 1) << 21 // b05-08 month | |
| val.getDay() << 16 // b00-04 hour | |
// 2 bytes time | |
| val.getHours() << 11 // b11-15 hour | |
| val.getMinutes() << 5 // b05-10 minute | |
| val.getSeconds() >> 1; // b00-04 seconds divided by 2 | |
} | |
setTime(+new Date()); | |
return { | |
get made () { return _verMade; }, | |
set made (val) { _verMade = val; }, | |
get version () { return _version; }, | |
set version (val) { _version = val }, | |
get flags () { return _flags }, | |
set flags (val) { _flags = val; }, | |
get method () { return _method; }, | |
set method (val) { _method = val; }, | |
get time () { return new Date( | |
((_time >> 25) & 0x7f) + 1980, | |
((_time >> 21) & 0x0f) - 1, | |
(_time >> 16) & 0x1f, | |
(_time >> 11) & 0x1f, | |
(_time >> 5) & 0x3f, | |
(_time & 0x1f) << 1 | |
); | |
}, | |
set time (val) { | |
setTime(val); | |
}, | |
get crc () { return _crc; }, | |
set crc (val) { _crc = val; }, | |
get compressedSize () { return _compressedSize; }, | |
set compressedSize (val) { _compressedSize = val; }, | |
get size () { return _size; }, | |
set size (val) { _size = val; }, | |
get fileNameLength () { return _fnameLen; }, | |
set fileNameLength (val) { _fnameLen = val; }, | |
get extraLength () { return _extraLen }, | |
set extraLength (val) { _extraLen = val; }, | |
get commentLength () { return _comLen }, | |
set commentLength (val) { _comLen = val }, | |
get diskNumStart () { return _diskStart }, | |
set diskNumStart (val) { _diskStart = val }, | |
get inAttr () { return _inattr }, | |
set inAttr (val) { _inattr = val }, | |
get attr () { return _attr }, | |
set attr (val) { _attr = val }, | |
get offset () { return _offset }, | |
set offset (val) { _offset = val }, | |
get encripted () { return (_flags & 1) == 1 }, | |
get entryHeaderSize () { | |
return Constants.CENHDR + _fnameLen + _extraLen + _comLen; | |
}, | |
get realDataOffset () { | |
return _offset + Constants.LOCHDR + _dataHeader.fnameLen + _dataHeader.extraLen; | |
}, | |
get dataHeader () { | |
return _dataHeader; | |
}, | |
loadDataHeaderFromBinary : function(/*Buffer*/input) { | |
var data = input.slice(_offset, _offset + Constants.LOCHDR); | |
// 30 bytes and should start with "PK\003\004" | |
if (data.readUInt32LE(0) != Constants.LOCSIG) { | |
throw Utils.Errors.INVALID_LOC; | |
} | |
_dataHeader = { | |
// version needed to extract | |
version : data.readUInt16LE(Constants.LOCVER), | |
// general purpose bit flag | |
flags : data.readUInt16LE(Constants.LOCFLG), | |
// compression method | |
method : data.readUInt16LE(Constants.LOCHOW), | |
// modification time (2 bytes time, 2 bytes date) | |
time : data.readUInt32LE(Constants.LOCTIM), | |
// uncompressed file crc-32 value | |
crc : data.readUInt32LE(Constants.LOCCRC), | |
// compressed size | |
compressedSize : data.readUInt32LE(Constants.LOCSIZ), | |
// uncompressed size | |
size : data.readUInt32LE(Constants.LOCLEN), | |
// filename length | |
fnameLen : data.readUInt16LE(Constants.LOCNAM), | |
// extra field length | |
extraLen : data.readUInt16LE(Constants.LOCEXT) | |
} | |
}, | |
loadFromBinary : function(/*Buffer*/data) { | |
// data should be 46 bytes and start with "PK 01 02" | |
if (data.length != Constants.CENHDR || data.readUInt32LE(0) != Constants.CENSIG) { | |
throw Utils.Errors.INVALID_CEN; | |
} | |
// version made by | |
_verMade = data.readUInt16LE(Constants.CENVEM); | |
// version needed to extract | |
_version = data.readUInt16LE(Constants.CENVER); | |
// encrypt, decrypt flags | |
_flags = data.readUInt16LE(Constants.CENFLG); | |
// compression method | |
_method = data.readUInt16LE(Constants.CENHOW); | |
// modification time (2 bytes time, 2 bytes date) | |
_time = data.readUInt32LE(Constants.CENTIM); | |
// uncompressed file crc-32 value | |
_crc = data.readUInt32LE(Constants.CENCRC); | |
// compressed size | |
_compressedSize = data.readUInt32LE(Constants.CENSIZ); | |
// uncompressed size | |
_size = data.readUInt32LE(Constants.CENLEN); | |
// filename length | |
_fnameLen = data.readUInt16LE(Constants.CENNAM); | |
// extra field length | |
_extraLen = data.readUInt16LE(Constants.CENEXT); | |
// file comment length | |
_comLen = data.readUInt16LE(Constants.CENCOM); | |
// volume number start | |
_diskStart = data.readUInt16LE(Constants.CENDSK); | |
// internal file attributes | |
_inattr = data.readUInt16LE(Constants.CENATT); | |
// external file attributes | |
_attr = data.readUInt32LE(Constants.CENATX); | |
// LOC header offset | |
_offset = data.readUInt32LE(Constants.CENOFF); | |
}, | |
dataHeaderToBinary : function() { | |
// LOC header size (30 bytes) | |
var data = new Buffer(Constants.LOCHDR); | |
// "PK\003\004" | |
data.writeUInt32LE(Constants.LOCSIG, 0); | |
// version needed to extract | |
data.writeUInt16LE(_version, Constants.LOCVER); | |
// general purpose bit flag | |
data.writeUInt16LE(_flags, Constants.LOCFLG); | |
// compression method | |
data.writeUInt16LE(_method, Constants.LOCHOW); | |
// modification time (2 bytes time, 2 bytes date) | |
data.writeUInt32LE(_time, Constants.LOCTIM); | |
// uncompressed file crc-32 value | |
data.writeUInt32LE(_crc, Constants.LOCCRC); | |
// compressed size | |
data.writeUInt32LE(_compressedSize, Constants.LOCSIZ); | |
// uncompressed size | |
data.writeUInt32LE(_size, Constants.LOCLEN); | |
// filename length | |
data.writeUInt16LE(_fnameLen, Constants.LOCNAM); | |
// extra field length | |
data.writeUInt16LE(_extraLen, Constants.LOCEXT); | |
return data; | |
}, | |
entryHeaderToBinary : function() { | |
// CEN header size (46 bytes) | |
var data = new Buffer(Constants.CENHDR + _fnameLen + _extraLen + _comLen); | |
// "PK\001\002" | |
data.writeUInt32LE(Constants.CENSIG, 0); | |
// version made by | |
data.writeUInt16LE(_verMade, Constants.CENVEM); | |
// version needed to extract | |
data.writeUInt16LE(_version, Constants.CENVER); | |
// encrypt, decrypt flags | |
data.writeUInt16LE(_flags, Constants.CENFLG); | |
// compression method | |
data.writeUInt16LE(_method, Constants.CENHOW); | |
// modification time (2 bytes time, 2 bytes date) | |
data.writeUInt32LE(_time, Constants.CENTIM); | |
// uncompressed file crc-32 value | |
data.writeInt32LE(_crc, Constants.CENCRC, true); | |
// compressed size | |
data.writeUInt32LE(_compressedSize, Constants.CENSIZ); | |
// uncompressed size | |
data.writeUInt32LE(_size, Constants.CENLEN); | |
// filename length | |
data.writeUInt16LE(_fnameLen, Constants.CENNAM); | |
// extra field length | |
data.writeUInt16LE(_extraLen, Constants.CENEXT); | |
// file comment length | |
data.writeUInt16LE(_comLen, Constants.CENCOM); | |
// volume number start | |
data.writeUInt16LE(_diskStart, Constants.CENDSK); | |
// internal file attributes | |
data.writeUInt16LE(_inattr, Constants.CENATT); | |
// external file attributes | |
data.writeUInt32LE(_attr, Constants.CENATX); | |
// LOC header offset | |
data.writeUInt32LE(_offset, Constants.CENOFF); | |
// fill all with | |
data.fill(0x00, Constants.CENHDR); | |
return data; | |
}, | |
toString : function() { | |
return '{\n' + | |
'\t"made" : ' + _verMade + ",\n" + | |
'\t"version" : ' + _version + ",\n" + | |
'\t"flags" : ' + _flags + ",\n" + | |
'\t"method" : ' + Utils.methodToString(_method) + ",\n" + | |
'\t"time" : ' + _time + ",\n" + | |
'\t"crc" : 0x' + _crc.toString(16).toUpperCase() + ",\n" + | |
'\t"compressedSize" : ' + _compressedSize + " bytes,\n" + | |
'\t"size" : ' + _size + " bytes,\n" + | |
'\t"fileNameLength" : ' + _fnameLen + ",\n" + | |
'\t"extraLength" : ' + _extraLen + " bytes,\n" + | |
'\t"commentLength" : ' + _comLen + " bytes,\n" + | |
'\t"diskNumStart" : ' + _diskStart + ",\n" + | |
'\t"inAttr" : ' + _inattr + ",\n" + | |
'\t"attr" : ' + _attr + ",\n" + | |
'\t"offset" : ' + _offset + ",\n" + | |
'\t"entryHeaderSize" : ' + (Constants.CENHDR + _fnameLen + _extraLen + _comLen) + " bytes\n" + | |
'}'; | |
} | |
} | |
}; |