Comparing version 2.5.0 to 2.6.0
89
index.js
var fs = require("fs"); | ||
var zlib = require("zlib"); | ||
var fd_slicer = require("fd-slicer"); | ||
var crc32 = require("buffer-crc32"); | ||
var util = require("util"); | ||
@@ -104,3 +105,5 @@ var EventEmitter = require("events").EventEmitter; | ||
var diskNumber = eocdrBuffer.readUInt16LE(4); | ||
if (diskNumber !== 0) return callback(new Error("multi-disk zip files are not supported: found disk number: " + diskNumber)); | ||
if (diskNumber !== 0) { | ||
return callback(new Error("multi-disk zip files are not supported: found disk number: " + diskNumber)); | ||
} | ||
// 6 - Disk where central directory starts | ||
@@ -137,3 +140,3 @@ // 8 - Number of central directory records on this disk | ||
if (zip64EocdlBuffer.readUInt32LE(0) !== 0x07064b50) { | ||
return callback(new Error("invalid ZIP64 End of Central Directory Locator signature")); | ||
return callback(new Error("invalid zip64 end of central directory locator signature")); | ||
} | ||
@@ -151,3 +154,5 @@ // 4 - number of the disk with the start of the zip64 end of central directory | ||
// 0 - zip64 end of central dir signature 4 bytes (0x06064b50) | ||
if (zip64EocdrBuffer.readUInt32LE(0) !== 0x06064b50) return callback(new Error("invalid ZIP64 end of central directory record signature")); | ||
if (zip64EocdrBuffer.readUInt32LE(0) !== 0x06064b50) { | ||
return callback(new Error("invalid zip64 end of central directory record signature")); | ||
} | ||
// 4 - size of zip64 end of central directory record 8 bytes | ||
@@ -275,7 +280,3 @@ // 12 - version made by 2 bytes | ||
var isUtf8 = entry.generalPurposeBitFlag & 0x800 | ||
try { | ||
entry.fileName = bufferToString(buffer, 0, entry.fileNameLength, isUtf8); | ||
} catch (e) { | ||
return emitErrorAndAutoClose(self, e); | ||
} | ||
entry.fileName = bufferToString(buffer, 0, entry.fileNameLength, isUtf8); | ||
@@ -292,3 +293,3 @@ // 46+n - Extra field | ||
var dataEnd = dataStart + dataSize; | ||
if (dataEnd > extraFieldBuffer.length) return emitErrorAndAutoClose(self, new Error("extra field length exceeds Extra Field buffer size")); | ||
if (dataEnd > extraFieldBuffer.length) return emitErrorAndAutoClose(self, new Error("extra field length exceeds extra field buffer size")); | ||
var dataBuffer = new Buffer(dataSize); | ||
@@ -304,7 +305,3 @@ extraFieldBuffer.copy(dataBuffer, 0, dataStart, dataEnd); | ||
// 46+n+m - File comment | ||
try { | ||
entry.fileComment = bufferToString(buffer, fileCommentStart, fileCommentStart + entry.fileCommentLength, isUtf8); | ||
} catch (e) { | ||
return emitErrorAndAutoClose(self, e); | ||
} | ||
entry.fileComment = bufferToString(buffer, fileCommentStart, fileCommentStart + entry.fileCommentLength, isUtf8); | ||
@@ -327,7 +324,11 @@ self.readEntryCursor += buffer.length; | ||
} | ||
if (zip64EiefBuffer == null) return emitErrorAndAutoClose(self, new Error("expected Zip64 Extended Information Extra Field")); | ||
if (zip64EiefBuffer == null) { | ||
return emitErrorAndAutoClose(self, new Error("expected zip64 extended information extra field")); | ||
} | ||
var index = 0; | ||
// 0 - Original Size 8 bytes | ||
if (entry.uncompressedSize === 0xffffffff) { | ||
if (index + 8 > zip64EiefBuffer.length) return emitErrorAndAutoClose(self, new Error("Zip64 Extended Information Extra Field does not include Original Size")); | ||
if (index + 8 > zip64EiefBuffer.length) { | ||
return emitErrorAndAutoClose(self, new Error("zip64 extended information extra field does not include uncompressed size")); | ||
} | ||
entry.uncompressedSize = readUInt64LE(zip64EiefBuffer, index); | ||
@@ -338,3 +339,5 @@ index += 8; | ||
if (entry.compressedSize === 0xffffffff) { | ||
if (index + 8 > zip64EiefBuffer.length) return emitErrorAndAutoClose(self, new Error("Zip64 Extended Information Extra Field does not include Compressed Size")); | ||
if (index + 8 > zip64EiefBuffer.length) { | ||
return emitErrorAndAutoClose(self, new Error("zip64 extended information extra field does not include compressed size")); | ||
} | ||
entry.compressedSize = readUInt64LE(zip64EiefBuffer, index); | ||
@@ -345,3 +348,5 @@ index += 8; | ||
if (entry.relativeOffsetOfLocalHeader === 0xffffffff) { | ||
if (index + 8 > zip64EiefBuffer.length) return emitErrorAndAutoClose(self, new Error("Zip64 Extended Information Extra Field does not include Relative Header Offset")); | ||
if (index + 8 > zip64EiefBuffer.length) { | ||
return emitErrorAndAutoClose(self, new Error("zip64 extended information extra field does not include relative header offset")); | ||
} | ||
entry.relativeOffsetOfLocalHeader = readUInt64LE(zip64EiefBuffer, index); | ||
@@ -353,2 +358,30 @@ index += 8; | ||
// check for Info-ZIP Unicode Path Extra Field (0x7075) | ||
// see https://github.com/thejoshwolfe/yauzl/issues/33 | ||
for (var i = 0; i < entry.extraFields.length; i++) { | ||
var extraField = entry.extraFields[i]; | ||
if (extraField.id === 0x7075) { | ||
if (extraField.data.length < 6) { | ||
// too short to be meaningful | ||
continue; | ||
} | ||
// Version 1 byte version of this extra field, currently 1 | ||
if (extraField.data.readUInt8(0) !== 1) { | ||
// > Changes may not be backward compatible so this extra | ||
// > field should not be used if the version is not recognized. | ||
continue; | ||
} | ||
// NameCRC32 4 bytes File Name Field CRC32 Checksum | ||
var oldNameCrc32 = extraField.data.readUInt32LE(1); | ||
if (crc32.unsigned(buffer.slice(0, entry.fileNameLength)) !== oldNameCrc32) { | ||
// > If the CRC check fails, this UTF-8 Path Extra Field should be | ||
// > ignored and the File Name field in the header should be used instead. | ||
continue; | ||
} | ||
// UnicodeName Variable UTF-8 version of the entry File Name | ||
entry.fileName = bufferToString(extraField.data, 5, extraField.data.length, true); | ||
break; | ||
} | ||
} | ||
// validate file size | ||
@@ -363,5 +396,11 @@ if (entry.compressionMethod === 0) { | ||
// validate file name | ||
if (entry.fileName.indexOf("\\") !== -1) return emitErrorAndAutoClose(self, new Error("invalid characters in fileName: " + entry.fileName)); | ||
if (/^[a-zA-Z]:/.test(entry.fileName) || /^\//.test(entry.fileName)) return emitErrorAndAutoClose(self, new Error("absolute path: " + entry.fileName)); | ||
if (entry.fileName.split("/").indexOf("..") !== -1) return emitErrorAndAutoClose(self, new Error("invalid relative path: " + entry.fileName)); | ||
if (entry.fileName.indexOf("\\") !== -1) { | ||
return emitErrorAndAutoClose(self, new Error("invalid characters in fileName: " + entry.fileName)); | ||
} | ||
if (/^[a-zA-Z]:/.test(entry.fileName) || /^\//.test(entry.fileName)) { | ||
return emitErrorAndAutoClose(self, new Error("absolute path: " + entry.fileName)); | ||
} | ||
if (entry.fileName.split("/").indexOf("..") !== -1) { | ||
return emitErrorAndAutoClose(self, new Error("invalid relative path: " + entry.fileName)); | ||
} | ||
self.emit("entry", entry); | ||
@@ -385,3 +424,5 @@ | ||
var signature = buffer.readUInt32LE(0); | ||
if (signature !== 0x04034b50) return callback(new Error("invalid local file header signature: 0x" + signature.toString(16))); | ||
if (signature !== 0x04034b50) { | ||
return callback(new Error("invalid local file header signature: 0x" + signature.toString(16))); | ||
} | ||
// all this should be redundant | ||
@@ -485,3 +526,5 @@ // 4 - Version needed to extract (minimum) | ||
if (err) return callback(err); | ||
if (bytesRead < length) return callback(new Error("unexpected EOF")); | ||
if (bytesRead < length) { | ||
return callback(new Error("unexpected EOF")); | ||
} | ||
callback(); | ||
@@ -488,0 +531,0 @@ }); |
{ | ||
"name": "yauzl", | ||
"version": "2.5.0", | ||
"version": "2.6.0", | ||
"description": "yet another unzip library for node", | ||
@@ -29,3 +29,4 @@ "main": "index.js", | ||
"dependencies": { | ||
"fd-slicer": "~1.0.1" | ||
"fd-slicer": "~1.0.1", | ||
"buffer-crc32": "~0.2.3" | ||
}, | ||
@@ -32,0 +33,0 @@ "devDependencies": { |
@@ -21,3 +21,3 @@ # yauzl | ||
Don't let malformed zip files bring down client applications who are trying to catch errors. | ||
* Catch unsafe filenames entries. | ||
* Catch unsafe file names. | ||
A zip file entry throws an error if its file name starts with `"/"` or `/[A-Za-z]:\//` | ||
@@ -272,2 +272,4 @@ or if it contains `".."` path segments or `"\\"` (per the spec). | ||
`UTF-8` if `generalPurposeBitFlag & 0x800`, otherwise with `CP437`. | ||
Alternatively, this field may be populated from the Info-ZIP Unicode Path Extra Field | ||
(see `extraFields`). | ||
@@ -281,9 +283,21 @@ If `fileName` would contain unsafe characters, such as an absolute path or | ||
where `id` is a `Number` and `data` is a `Buffer`. | ||
This library looks for and reads the ZIP64 Extended Information Extra Field (0x0001) | ||
in order to support ZIP64 format zip files. | ||
This library also looks for and reads the Info-ZIP Unicode Path Extra Field (0x7075) | ||
in order to support some zipfiles that use it instead of General Purpose Bit 8 | ||
to convey `UTF-8` file names. | ||
When the field is identified and verified to be reliable (see the zipfile spec), | ||
the the file name in this field is stored in the `fileName` property, | ||
and the file name in the central directory record for this entry is ignored. | ||
None of the other fields are considered significant by this library. | ||
Fields that this library reads are left unalterned in the `extraFields` array. | ||
#### comment | ||
`String` decoded with the same charset as used for `fileName`. | ||
`String` decoded with the the charset indicated by `generalPurposeBitFlag & 0x800` | ||
as with the `fileName`. | ||
(The Info-ZIP Unicode Path Extra Field has no effect on the charset used for this field.) | ||
@@ -445,2 +459,4 @@ #### getLastModDate() | ||
* 2.6.0 | ||
* Support Info-ZIP Unicode Path Extra Field, used by WinRAR for Chinese file names. [issue #33](https://github.com/thejoshwolfe/yauzl/issues/33) | ||
* 2.5.0 | ||
@@ -447,0 +463,0 @@ * Ignore malformed Extra Field that is common in Android .apk files. [issue #31](https://github.com/thejoshwolfe/yauzl/issues/31) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
49742
625
490
2
+ Addedbuffer-crc32@~0.2.3
+ Addedbuffer-crc32@0.2.13(transitive)