From 6b205812aa2622d537a0289d79f1f4e4605e09cb Mon Sep 17 00:00:00 2001 From: Josh Wolfe Date: Wed, 15 Jun 2016 17:55:09 -0700 Subject: [PATCH] support Info-ZIP Unicode Path Extra Field (0x7075). closes #33 --- index.js | 29 ++++++++++++++++++ package.json | 3 +- test/success/unicode-path-extra-field.zip | Bin 0 -> 196 bytes .../qi ge fangjian.txt | 0 test/test.js | 1 + test/zip64.js | 4 +-- 6 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 test/success/unicode-path-extra-field.zip create mode 100644 test/success/unicode-path-extra-field/qi ge fangjian.txt diff --git a/index.js b/index.js index 07cf107..4f93f47 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ var fs = require("fs"); var zlib = require("zlib"); var fd_slicer = require("fd-slicer"); +var crc32 = require("buffer-crc32"); var util = require("util"); var EventEmitter = require("events").EventEmitter; var Transform = require("stream").Transform; @@ -341,6 +342,34 @@ ZipFile.prototype.readEntry = function() { // 24 - Disk Start Number 4 bytes } + // 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 < 5) { + // 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 if (entry.compressionMethod === 0) { if (entry.compressedSize !== entry.uncompressedSize) { diff --git a/package.json b/package.json index c930c8c..c8658f5 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ }, "homepage": "https://github.com/thejoshwolfe/yauzl", "dependencies": { - "fd-slicer": "~1.0.1" + "fd-slicer": "~1.0.1", + "buffer-crc32": "~0.2.3" }, "devDependencies": { "bl": "~1.0.0", diff --git a/test/success/unicode-path-extra-field.zip b/test/success/unicode-path-extra-field.zip new file mode 100644 index 0000000000000000000000000000000000000000..1a5f6320584a28598453b1187d782beeccb02965 GIT binary patch literal 196 zcmWIWW@gc4VBlb2P@Qnjg8>N$Fi0~nFfuW-u(GjpaB^|;@bdAO7Kk!1c04+F?#Yhk zCp%U>>)8Kt`WC&Cijn|tcAyam5a7+oWY3JpV5rh9jbH}x*08dHG%x~TIFJTm1_l7^ C04Asa literal 0 HcmV?d00001 diff --git a/test/success/unicode-path-extra-field/qi ge fangjian.txt b/test/success/unicode-path-extra-field/qi ge fangjian.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/test.js b/test/test.js index 014ff27..479f3c7 100644 --- a/test/test.js +++ b/test/test.js @@ -312,6 +312,7 @@ function addUnicodeSupport(name) { // see https://github.com/thejoshwolfe/yauzl/issues/10 name = name.replace(/Turmion Katilot/g, "Turmion Kätilöt"); name = name.replace(/Mista veri pakenee/g, "Mistä veri pakenee"); + name = name.replace(/qi ge fangjian/g, "七个房间"); return name; } diff --git a/test/zip64.js b/test/zip64.js index 2ac0967..0512969 100644 --- a/test/zip64.js +++ b/test/zip64.js @@ -186,7 +186,7 @@ function runTest(cb) { if (expectedContents != null) { readStream.pipe(BufferList(function(err, data) { if (data.toString() !== expectedContents) throw new Error(logPrefix + "expected contents:\n" + expectedContents + "\ngot:\n" + data.toString() + "\n"); - console.log(logPrefix + entry.fileName + ": PASS"); + console.log(logPrefix + entry.fileName + ": pass"); })); } else { // make sure this is the big thing @@ -194,7 +194,7 @@ function runTest(cb) { getPrefixOfStream(readStream, function(actualPrefixBuffer) { readStream.destroy(); if (buffersEqual(expectedPrefixBuffer, actualPrefixBuffer)) { - console.log(logPrefix + entry.fileName + ": PASS"); + console.log(logPrefix + entry.fileName + ": pass"); } else { throw new Error(logPrefix + "large.bin contents read did not return expected stream") }