Skip to content

Commit

Permalink
add Buffer api compatibility for Node 0.10
Browse files Browse the repository at this point in the history
  • Loading branch information
thejoshwolfe committed Dec 1, 2018
1 parent 961beb3 commit bcb1bf1
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 25 deletions.
86 changes: 69 additions & 17 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ ZipFile.prototype.addEmptyDirectory = function(metadataPath, options) {
pumpEntries(self);
};

var eocdrSignatureBuffer = Buffer.from([0x50, 0x4b, 0x05, 0x06]);
var eocdrSignatureBuffer = bufferFrom([0x50, 0x4b, 0x05, 0x06]);

ZipFile.prototype.end = function(options, finalSizeCallback) {
if (typeof options === "function") {
Expand All @@ -129,7 +129,7 @@ ZipFile.prototype.end = function(options, finalSizeCallback) {
}
if (this.comment.length > 0xffff) throw new Error("comment is too large");
// gotta check for this, because the zipfile format is actually ambiguous.
if (this.comment.includes(eocdrSignatureBuffer)) throw new Error("comment contains end of central directory record signature");
if (bufferIncludes(this.comment, eocdrSignatureBuffer)) throw new Error("comment contains end of central directory record signature");
} else {
// no comment.
this.comment = EMPTY_BUFFER;
Expand Down Expand Up @@ -293,7 +293,7 @@ function getEndOfCentralDirectoryRecord(self, actuallyJustTellMeHowLongItWouldBe
}
}

var eocdrBuffer = Buffer.allocUnsafe(END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + self.comment.length);
var eocdrBuffer = bufferAlloc(END_OF_CENTRAL_DIRECTORY_RECORD_SIZE + self.comment.length);
// end of central dir signature 4 bytes (0x06054b50)
eocdrBuffer.writeUInt32LE(0x06054b50, 0);
// number of this disk 2 bytes
Expand All @@ -317,7 +317,7 @@ function getEndOfCentralDirectoryRecord(self, actuallyJustTellMeHowLongItWouldBe

// ZIP64 format
// ZIP64 End of Central Directory Record
var zip64EocdrBuffer = Buffer.allocUnsafe(ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE);
var zip64EocdrBuffer = bufferAlloc(ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIZE);
// zip64 end of central dir signature 4 bytes (0x06064b50)
zip64EocdrBuffer.writeUInt32LE(0x06064b50, 0);
// size of zip64 end of central directory record 8 bytes
Expand All @@ -343,7 +343,7 @@ function getEndOfCentralDirectoryRecord(self, actuallyJustTellMeHowLongItWouldBe


// ZIP64 End of Central Directory Locator
var zip64EocdlBuffer = Buffer.allocUnsafe(ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE);
var zip64EocdlBuffer = bufferAlloc(ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIZE);
// zip64 end of central dir locator signature 4 bytes (0x07064b50)
zip64EocdlBuffer.writeUInt32LE(0x07064b50, 0);
// number of the disk with the start of the zip64 end of central directory 4 bytes
Expand Down Expand Up @@ -376,11 +376,11 @@ function validateMetadataPath(metadataPath, isDirectory) {
return metadataPath;
}

var EMPTY_BUFFER = Buffer.allocUnsafe(0);
var EMPTY_BUFFER = bufferAlloc(0);

// this class is not part of the public API
function Entry(metadataPath, isDirectory, options) {
this.utf8FileName = Buffer.from(metadataPath);
this.utf8FileName = bufferFrom(metadataPath);
if (this.utf8FileName.length > 0xffff) throw new Error("utf8 file name too long. " + utf8FileName.length + " > " + 0xffff);
this.isDirectory = isDirectory;
this.state = Entry.WAITING_FOR_METADATA;
Expand Down Expand Up @@ -412,7 +412,7 @@ function Entry(metadataPath, isDirectory, options) {
this.forceZip64Format = !!options.forceZip64Format;
if (options.fileComment) {
if (typeof options.fileComment === "string") {
this.fileComment = Buffer.from(options.fileComment, "utf-8");
this.fileComment = bufferFrom(options.fileComment, "utf-8");
} else {
// It should be a Buffer
this.fileComment = options.fileComment;
Expand Down Expand Up @@ -467,7 +467,7 @@ Entry.prototype.getLocalFileHeader = function() {
uncompressedSize = this.uncompressedSize;
}

var fixedSizeStuff = Buffer.allocUnsafe(LOCAL_FILE_HEADER_FIXED_SIZE);
var fixedSizeStuff = bufferAlloc(LOCAL_FILE_HEADER_FIXED_SIZE);
var generalPurposeBitFlag = FILE_NAME_IS_UTF8;
if (!this.crcAndFileSizeKnown) generalPurposeBitFlag |= UNKNOWN_CRC32_AND_FILE_SIZES;

Expand Down Expand Up @@ -506,10 +506,10 @@ var ZIP64_DATA_DESCRIPTOR_SIZE = 24;
Entry.prototype.getDataDescriptor = function() {
if (this.crcAndFileSizeKnown) {
// the Mac Archive Utility requires this not be present unless we set general purpose bit 3
return Buffer.allocUnsafe(0);
return EMPTY_BUFFER;
}
if (!this.useZip64Format()) {
var buffer = Buffer.allocUnsafe(DATA_DESCRIPTOR_SIZE);
var buffer = bufferAlloc(DATA_DESCRIPTOR_SIZE);
// optional signature (required according to Archive Utility)
buffer.writeUInt32LE(0x08074b50, 0);
// crc-32 4 bytes
Expand All @@ -521,7 +521,7 @@ Entry.prototype.getDataDescriptor = function() {
return buffer;
} else {
// ZIP64 format
var buffer = Buffer.allocUnsafe(ZIP64_DATA_DESCRIPTOR_SIZE);
var buffer = bufferAlloc(ZIP64_DATA_DESCRIPTOR_SIZE);
// optional signature (unknown if anyone cares about this)
buffer.writeUInt32LE(0x08074b50, 0);
// crc-32 4 bytes
Expand All @@ -536,7 +536,7 @@ Entry.prototype.getDataDescriptor = function() {
var CENTRAL_DIRECTORY_RECORD_FIXED_SIZE = 46;
var ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE = 28;
Entry.prototype.getCentralDirectoryRecord = function() {
var fixedSizeStuff = Buffer.allocUnsafe(CENTRAL_DIRECTORY_RECORD_FIXED_SIZE);
var fixedSizeStuff = bufferAlloc(CENTRAL_DIRECTORY_RECORD_FIXED_SIZE);
var generalPurposeBitFlag = FILE_NAME_IS_UTF8;
if (!this.crcAndFileSizeKnown) generalPurposeBitFlag |= UNKNOWN_CRC32_AND_FILE_SIZES;

Expand All @@ -552,7 +552,7 @@ Entry.prototype.getCentralDirectoryRecord = function() {
versionNeededToExtract = VERSION_NEEDED_TO_EXTRACT_ZIP64;

// ZIP64 extended information extra field
zeiefBuffer = Buffer.allocUnsafe(ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE);
zeiefBuffer = bufferAlloc(ZIP64_EXTENDED_INFORMATION_EXTRA_FIELD_SIZE);
// 0x0001 2 bytes Tag for this "extra" block type
zeiefBuffer.writeUInt16LE(0x0001, 0);
// Size 2 bytes Size of this "extra" block
Expand All @@ -567,7 +567,7 @@ Entry.prototype.getCentralDirectoryRecord = function() {
// (omit)
} else {
versionNeededToExtract = VERSION_NEEDED_TO_EXTRACT_UTF8;
zeiefBuffer = Buffer.allocUnsafe(0);
zeiefBuffer = EMPTY_BUFFER;
}

// central file header signature 4 bytes (0x02014b50)
Expand Down Expand Up @@ -674,7 +674,7 @@ var reverseCp437 = null;
function encodeCp437(string) {
if (/^[\x20-\x7e]*$/.test(string)) {
// CP437, ASCII, and UTF-8 overlap in this range.
return Buffer.from(string, "utf-8");
return bufferFrom(string, "utf-8");
}

// This is the slow path.
Expand All @@ -686,7 +686,7 @@ function encodeCp437(string) {
}
}

var result = Buffer.allocUnsafe(string.length);
var result = bufferAlloc(string.length);
for (var i = 0; i < string.length; i++) {
var b = reverseCp437[string[i]];
if (b == null) throw new Error("character not encodable in CP437: " + JSON.stringify(string[i]));
Expand All @@ -695,3 +695,55 @@ function encodeCp437(string) {

return result;
}

function bufferAlloc(size) {
bufferAlloc = modern;
try {
return bufferAlloc(size);
} catch (e) {
bufferAlloc = legacy;
return bufferAlloc(size);
}
function modern(size) {
return Buffer.allocUnsafe(size);
}
function legacy(size) {
return new Buffer(size);
}
}
function bufferFrom(something, encoding) {
bufferFrom = modern;
try {
return bufferFrom(something, encoding);
} catch (e) {
bufferFrom = legacy;
return bufferFrom(something, encoding);
}
function modern(something, encoding) {
return Buffer.from(something, encoding);
}
function legacy(something, encoding) {
return new Buffer(something, encoding);
}
}
function bufferIncludes(buffer, content) {
bufferIncludes = modern;
try {
return bufferIncludes(buffer, content);
} catch (e) {
bufferIncludes = legacy;
return bufferIncludes(buffer, content);
}
function modern(buffer, content) {
return buffer.includes(content);
}
function legacy(buffer, content) {
for (var i = 0; i <= buffer.length - content.length; i++) {
for (var j = 0;; j++) {
if (j === content.length) return true;
if (buffer[i + j] !== content[j]) break;
}
}
return false;
}
}
32 changes: 24 additions & 8 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ var BufferList = require("bl");
options.forceZip64Format = !!zip64Config[1];
zipfile.addFile(__filename, "fdsa.txt", options);
options.forceZip64Format = !!zip64Config[2];
zipfile.addBuffer(Buffer.from("buffer"), "buffer.txt", options);
zipfile.addBuffer(bufferFrom("buffer"), "buffer.txt", options);
options.forceZip64Format = !!zip64Config[3];
options.size = "stream".length;
zipfile.addReadStream(new BufferList().append("stream"), "stream.txt", options);
Expand All @@ -76,7 +76,7 @@ var BufferList = require("bl");
var zipfile = new yazl.ZipFile();
// all options parameters are optional
zipfile.addFile(__filename, "a.txt");
zipfile.addBuffer(Buffer.from("buffer"), "b.txt");
zipfile.addBuffer(bufferFrom("buffer"), "b.txt");
zipfile.addReadStream(new BufferList().append("stream"), "c.txt");
zipfile.addEmptyDirectory("d/");
zipfile.addEmptyDirectory("e");
Expand Down Expand Up @@ -104,7 +104,7 @@ var BufferList = require("bl");
(function() {
var zipfile = new yazl.ZipFile();
// all options parameters are optional
zipfile.addBuffer(Buffer.from("hello"), "hello.txt", {compress: false});
zipfile.addBuffer(bufferFrom("hello"), "hello.txt", {compress: false});
zipfile.end(function(finalSize) {
if (finalSize === -1) throw new Error("finalSize should be known");
zipfile.outputStream.pipe(new BufferList(function(err, data) {
Expand All @@ -131,7 +131,7 @@ var weirdChars = '\u0000☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕
(function() {
var testCases = [
["Hello World", "Hello World"],
[Buffer.from("Hello"), "Hello"],
[bufferFrom("Hello"), "Hello"],
[weirdChars, weirdChars],
];
testCases.forEach(function(testCase, i) {
Expand Down Expand Up @@ -159,10 +159,10 @@ var weirdChars = '\u0000☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕
var zipfile = new yazl.ZipFile();
try {
zipfile.end({
comment: Buffer.from("\x50\x4b\x05\x06" + "01234567890123456789")
comment: bufferFrom("01234567890123456789" + "\x50\x4b\x05\x06" + "01234567890123456789")
});
} catch (e) {
if (e.toString().indexOf("comment contains end of central directory record signature")) {
if (e.toString().indexOf("comment contains end of central directory record signature") !== -1) {
console.log("block eocdr signature in comment: pass");
return;
}
Expand All @@ -173,13 +173,13 @@ var weirdChars = '\u0000☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕
(function() {
var testCases = [
["Hello World!", "Hello World!"],
[Buffer.from("Hello!"), "Hello!"],
[bufferFrom("Hello!"), "Hello!"],
[weirdChars, weirdChars],
];
testCases.forEach(function(testCase, i) {
var zipfile = new yazl.ZipFile();
// all options parameters are optional
zipfile.addBuffer(Buffer.from("hello"), "hello.txt", {compress: false, fileComment: testCase[0]});
zipfile.addBuffer(bufferFrom("hello"), "hello.txt", {compress: false, fileComment: testCase[0]});
zipfile.end(function(finalSize) {
if (finalSize === -1) throw new Error("finalSize should be known");
zipfile.outputStream.pipe(new BufferList(function(err, data) {
Expand All @@ -202,3 +202,19 @@ var weirdChars = '\u0000☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕
});
});
})();

function bufferFrom(something, encoding) {
bufferFrom = modern;
try {
return bufferFrom(something, encoding);
} catch (e) {
bufferFrom = legacy;
return bufferFrom(something, encoding);
}
function modern(something, encoding) {
return Buffer.from(something, encoding);
}
function legacy(something, encoding) {
return new Buffer(something, encoding);
}
}

0 comments on commit bcb1bf1

Please sign in to comment.