Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wait for data to be drained before writing new central file header #92

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 32 additions & 25 deletions lib/archivers/zip/zip-archive-output-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var inherits = require('util').inherits;
var crc32 = require('buffer-crc32');
var {CRC32Stream} = require('crc32-stream');
var {DeflateCRC32Stream} = require('crc32-stream');
var { once } = require('events');

var ArchiveOutputStream = require('../archive-output-stream');
var ZipArchiveEntry = require('./zip-archive-entry');
Expand Down Expand Up @@ -120,12 +121,12 @@ ZipArchiveOutputStream.prototype._defaults = function(o) {
return o;
};

ZipArchiveOutputStream.prototype._finish = function() {
ZipArchiveOutputStream.prototype._finish = async function() {
this._archive.centralOffset = this.offset;

this._entries.forEach(function(ae) {
this._writeCentralFileHeader(ae);
}.bind(this));
for (const ae of this._entries) {
await this._writeCentralFileHeader(ae);
}

this._archive.centralLength = this.offset - this._archive.centralOffset;

Expand Down Expand Up @@ -260,14 +261,16 @@ ZipArchiveOutputStream.prototype._writeCentralDirectoryZip64 = function() {
this.write(zipUtil.getLongBytes(1));
};

ZipArchiveOutputStream.prototype._writeCentralFileHeader = function(ae) {
ZipArchiveOutputStream.prototype._writeCentralFileHeader = async function(ae) {
var gpb = ae.getGeneralPurposeBit();
var method = ae.getMethod();
var offsets = ae._offsets;

var size = ae.getSize();
var compressedSize = ae.getCompressedSize();

var continueWriting = true;

if (ae.isZip64() || offsets.file > constants.ZIP64_MAGIC) {
size = constants.ZIP64_MAGIC;
compressedSize = constants.ZIP64_MAGIC;
Expand All @@ -286,27 +289,27 @@ ZipArchiveOutputStream.prototype._writeCentralFileHeader = function(ae) {
}

// signature
this.write(zipUtil.getLongBytes(constants.SIG_CFH));
if (this.write(zipUtil.getLongBytes(constants.SIG_CFH)) === false) continueWriting = false;

// version made by
this.write(zipUtil.getShortBytes((ae.getPlatform() << 8) | constants.VERSION_MADEBY));
if (this.write(zipUtil.getShortBytes((ae.getPlatform() << 8) | constants.VERSION_MADEBY)) === false) continueWriting = false;

// version to extract and general bit flag
this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract()));
this.write(gpb.encode());
if (this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract())) === false) continueWriting = false;
if (this.write(gpb.encode()) === false) continueWriting = false;

// compression method
this.write(zipUtil.getShortBytes(method));
if (this.write(zipUtil.getShortBytes(method)) === false) continueWriting = false;

// datetime
this.write(zipUtil.getLongBytes(ae.getTimeDos()));
if (this.write(zipUtil.getLongBytes(ae.getTimeDos())) === false) continueWriting = false;

// crc32 checksum
this.write(zipUtil.getLongBytes(ae.getCrc()));
if (this.write(zipUtil.getLongBytes(ae.getCrc())) === false) continueWriting = false;

// sizes
this.write(zipUtil.getLongBytes(compressedSize));
this.write(zipUtil.getLongBytes(size));
if (this.write(zipUtil.getLongBytes(compressedSize)) === false) continueWriting = false;
if (this.write(zipUtil.getLongBytes(size)) === false) continueWriting = false;

var name = ae.getName();
var comment = ae.getComment();
Expand All @@ -318,38 +321,42 @@ ZipArchiveOutputStream.prototype._writeCentralFileHeader = function(ae) {
}

// name length
this.write(zipUtil.getShortBytes(name.length));
if (this.write(zipUtil.getShortBytes(name.length)) === false) continueWriting = false;

// extra length
this.write(zipUtil.getShortBytes(extra.length));
if (this.write(zipUtil.getShortBytes(extra.length)) === false) continueWriting = false;

// comments length
this.write(zipUtil.getShortBytes(comment.length));
if (this.write(zipUtil.getShortBytes(comment.length)) === false) continueWriting = false;;

// disk number start
this.write(constants.SHORT_ZERO);
if (this.write(constants.SHORT_ZERO) === false) continueWriting = false;;

// internal attributes
this.write(zipUtil.getShortBytes(ae.getInternalAttributes()));
if (this.write(zipUtil.getShortBytes(ae.getInternalAttributes())) === false) continueWriting = false;

// external attributes
this.write(zipUtil.getLongBytes(ae.getExternalAttributes()));
if (this.write(zipUtil.getLongBytes(ae.getExternalAttributes())) === false) continueWriting = false;

// relative offset of LFH
if (offsets.file > constants.ZIP64_MAGIC) {
this.write(zipUtil.getLongBytes(constants.ZIP64_MAGIC));
if (this.write(zipUtil.getLongBytes(constants.ZIP64_MAGIC)) === false) continueWriting = false;
} else {
this.write(zipUtil.getLongBytes(offsets.file));
if (this.write(zipUtil.getLongBytes(offsets.file)) === false) continueWriting = false;
}

// name
this.write(name);
if (this.write(name) === false) continueWriting = false;

// extra
this.write(extra);
if (this.write(extra) === false) continueWriting = false;

// comment
this.write(comment);
if (this.write(comment) === false) continueWriting = false;

if (continueWriting === false) {
await once(this, "drain");
}
};

ZipArchiveOutputStream.prototype._writeDataDescriptor = function(ae) {
Expand Down