Read ZIP64 extended information

The extra block of a file header can contain a ZIP64 that overrides some
of the fields from the file header with longer values if the fields had
been set to 0xffffffff (or 0xffff for the disk number).

See sections 4.5.2, 4.5.3, 4.4.8, 4.4.9, 4.4.13 and 4.4.16 of the
specification for reference.

Closes cthackers/adm-zip#81 as fixed.
This commit is contained in:
Raphael Schweikert
2014-02-26 18:12:27 +01:00
parent e505927b71
commit 5e4e4f8fca
3 changed files with 86 additions and 3 deletions

View File

@@ -80,5 +80,36 @@ module.exports = {
/* Load type */
FILE : 0,
BUFFER : 1,
NONE : 2
NONE : 2,
/* 4.5 Extensible data fields */
EF_ID : 0,
EF_SIZE : 2,
/* Header IDs */
ID_ZIP64 : 0x0001,
ID_AVINFO : 0x0007,
ID_PFS : 0x0008,
ID_OS2 : 0x0009,
ID_NTFS : 0x000a,
ID_OPENVMS : 0x000c,
ID_UNIX : 0x000d,
ID_FORK : 0x000e,
ID_PATCH : 0x000f,
ID_X509_PKCS7 : 0x0014,
ID_X509_CERTID_F : 0x0015,
ID_X509_CERTID_C : 0x0016,
ID_STRONGENC : 0x0017,
ID_RECORD_MGT : 0x0018,
ID_X509_PKCS7_RL : 0x0019,
ID_IBM1 : 0x0065,
ID_IBM2 : 0x0066,
ID_POSZIP : 0x4690,
EF_ZIP64_OR_32 : 0xffffffff,
EF_ZIP64_OR_16 : 0xffff,
EF_ZIP64_SUNCOMP : 0,
EF_ZIP64_SCOMP : 8,
EF_ZIP64_RHO : 16,
EF_ZIP64_DSN : 24
};

View File

@@ -2,7 +2,7 @@ var fs = require("fs"),
pth = require('path');
fs.existsSync = fs.existsSync || pth.existsSync;
module.exports = (function() {
var crcTable = [],
@@ -81,7 +81,7 @@ module.exports = (function() {
case Constants.DEFLATED:
return 'DEFLATED (' + method + ')';
default:
return 'UNSUPPORTED (' + method + ')'
return 'UNSUPPORTED (' + method + ')';
}
},

View File

@@ -136,6 +136,57 @@ module.exports = function (/*Buffer*/input) {
}
}
function readUInt64LE(buffer, offset) {
return (buffer.readUInt32LE(offset + 4) << 4) + buffer.readUInt32LE(offset);
}
function parseExtra(data) {
var offset = 0;
var signature, size, part;
while(offset<data.length) {
signature = data.readUInt16LE(offset);
offset += 2;
size = data.readUInt16LE(offset);
offset += 2;
part = data.slice(offset, offset+size);
offset += size;
if(Constants.ID_ZIP64 === signature) {
parseZip64ExtendedInformation(part);
}
}
}
//Override header field values with values from the ZIP64 extra field
function parseZip64ExtendedInformation(data) {
var size, compressedSize, offset, diskNumStart;
if(data.length >= Constants.EF_ZIP64_SCOMP) {
size = readUInt64LE(data, Constants.EF_ZIP64_SUNCOMP);
if(_entryHeader.size === Constants.EF_ZIP64_OR_32) {
_entryHeader.size = size;
}
}
if(data.length >= Constants.EF_ZIP64_RHO) {
compressedSize = readUInt64LE(data, Constants.EF_ZIP64_SCOMP);
if(_entryHeader.compressedSize === Constants.EF_ZIP64_OR_32) {
_entryHeader.compressedSize = compressedSize;
}
}
if(data.length >= Constants.EF_ZIP64_DSN) {
offset = readUInt64LE(data, Constants.EF_ZIP64_RHO);
if(_entryHeader.offset === Constants.EF_ZIP64_OR_32) {
_entryHeader.offset = offset;
}
}
if(data.length >= Constants.EF_ZIP64_DSN+4) {
diskNumStart = data.readUInt32LE(Constants.EF_ZIP64_DSN);
if(_entryHeader.diskNumStart === Constants.EF_ZIP64_OR_16) {
_entryHeader.diskNumStart = diskNumStart;
}
}
}
return {
get entryName () { return _entryName.toString(); },
get rawEntryName() { return _entryName; },
@@ -150,6 +201,7 @@ module.exports = function (/*Buffer*/input) {
set extra (val) {
_extra = val;
_entryHeader.extraLength = val.length;
parseExtra(val);
},
get comment () { return _comment.toString(); },