From ad5e6c4dc32af8823daf9a4892ae8fc57890f3a7 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 17 Jun 2020 17:02:09 -0700 Subject: [PATCH] Updated 'compressed-stream' to be more configurable Added zip-writer coapability updated zip-reader to show logs when enabled --- microscript/ILibDuktape_CompressedStream.c | 17 +- microscript/ILibDuktape_Polyfills.c | 5 +- modules/zip-reader.js | 78 +++++- modules/zip-writer.js | 306 +++++++++++++++++++++ 4 files changed, 394 insertions(+), 12 deletions(-) create mode 100644 modules/zip-writer.js diff --git a/microscript/ILibDuktape_CompressedStream.c b/microscript/ILibDuktape_CompressedStream.c index 6f6809f..e8ad63e 100644 --- a/microscript/ILibDuktape_CompressedStream.c +++ b/microscript/ILibDuktape_CompressedStream.c @@ -119,8 +119,8 @@ void ILibDuktape_Compressor_End(ILibDuktape_DuplexStream *stream, void *user) avail = sizeof(tmp) - cs->Z.avail_out; if (avail > 0) { - cs->crc = crc32(cs->crc, (unsigned char*)tmp, (unsigned int)avail); - ILibDuktape_DuplexStream_WriteData(cs->ds, tmp, (int)avail); + cs->crc = crc32(cs->crc, tmp, (unsigned int)avail); + ILibDuktape_DuplexStream_WriteData(cs->ds, tmp, (int)avail); } } while (cs->Z.avail_out == 0); ILibDuktape_DuplexStream_WriteEnd(cs->ds); @@ -147,7 +147,7 @@ ILibTransport_DoneState ILibDuktape_Compressor_Write(ILibDuktape_DuplexStream *s avail = sizeof(tmp) - cs->Z.avail_out; if (avail > 0) { - cs->crc = crc32(cs->crc, (unsigned char*)tmp, (unsigned int)avail); + cs->crc = crc32(cs->crc, tmp, (unsigned int)avail); ret = ILibDuktape_DuplexStream_WriteData(cs->ds, tmp, (int)avail); } } while (cs->Z.avail_out == 0); @@ -190,13 +190,12 @@ duk_ret_t ILibDuktape_CompressedStream_compressor(duk_context *ctx) cs->Z.zalloc = Z_NULL; cs->Z.zfree = Z_NULL; cs->Z.opaque = Z_NULL; - if (duk_is_number(ctx, 0)) + if (!duk_is_null_or_undefined(ctx, 0) && duk_is_object(ctx, 0)) { - int maxbit = -MAX_WBITS; - int strat = Z_DEFAULT_STRATEGY; - if (duk_is_number(ctx, 1)) { maxbit = duk_require_int(ctx, 1); } - if (duk_is_number(ctx, 2)) { strat = duk_require_int(ctx, 2); } - if (deflateInit2(&(cs->Z), duk_require_int(ctx, 0), Z_DEFLATED, maxbit, 8, strat) != Z_OK) { return(ILibDuktape_Error(ctx, "zlib error")); } + int maxbit = Duktape_GetIntPropertyValue(ctx, 0, "WBITS", -MAX_WBITS); + int strat = Duktape_GetIntPropertyValue(ctx, 0, "STRATEGY", Z_DEFAULT_STRATEGY); + int level = Duktape_GetIntPropertyValue(ctx, 0, "LEVEL", Z_DEFAULT_COMPRESSION); + if (deflateInit2(&(cs->Z), level, Z_DEFLATED, maxbit, 8, strat) != Z_OK) { return(ILibDuktape_Error(ctx, "zlib error")); } } else { diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index 0cbff55..5ae314c 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -2269,7 +2269,10 @@ void ILibDuktape_Polyfills_JS_Init(duk_context *ctx) duk_peval_string_noresult(ctx, "addCompressedModule('identifiers', Buffer.from('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', 'base64'));"); // zip-reader, refer to modules/zip-reader.js - duk_peval_string_noresult(ctx, "addCompressedModule('zip-reader', Buffer.from('eJzVGtty2zb23TP+h5M8VFQt05Lsuq212q7ry1ZTx85IzmY6aSZDUaBEmya4JFTZzejf9xyAFxAkJWXTfVh1JrIAnPsVBz36dn/vgkcvsT9fCOh3+10YhYIFcMHjiMeO8Hm4v7e/d+O7LEzYDJbhjMUgFgzOI8fFr3SnA/9icYKnoW93waIDr9Ot1+3B/t4LX8KT8wIhF7BMGGLwE/D8gAF7dlkkwA/B5U9R4Duhy2Dli4WkkuKw9/d+SzHwqXDwsIPHI/zl6cfAEcQt4GchRHR2dLRarWxHcmrzeH4UqHPJ0c3o4up2cnWI3BLEuzBgSQIx+/fSj1HM6Qs4ETLjOlNkMXBWwGNw5jHDPcGJ2VXsCz+cdyDhnlg5Mdvfm/mJiP3pUpT0lLGG8uoHUFNOCK/PJzCavIafzyejSWd/7/3o/pe7d/fw/nw8Pr+9H11N4G4MF3e3l6P70d0t/rqG89vf4NfR7WUHGGoJqbDnKCbukUWfNMhmqK4JYyXyHlfsJBFzfc93UahwvnTmDOb8DxaHKAtELH7yE7JigszN9vcC/8kX0gmSqkRI5Nuj/b0/nBiu7i4uxzCEXpf+6393OlDravX4+PT4x/7JD+nizTUtnn5/3D/5/rv+gNRPy1HMkTjDrdQKVitdarVTyNkyCtizfgL1yZynVtu+lFsSmbcMXWIZ0Oju4zUPkO+3jlhYM5aI9v7eZ+UgvgcWEnBRc3YUOAIV9ATDIbRWfnjcb7XhMxAAUqMvO0HFCqt1hLQeuB9ard9/R75grZARd4I/olrK5zcQgJ+AcMAZENKBwlNgmzpSFwqpnSx8T1jZqdUCA8dKtwIWzjFY/g69ttpN5aOPRHIwBGt3RuDAoJkRVTqzXuW69xLUBXtGn04mL6FrEbF2uzis8UGfMtzT48yPCzCNRqpR/FprtmTPInZccYvfVmQY0Y5YOEP/zVSBonXJfJH9CeMCtYa0xTIOS9YKERPqtwCOeJQrWDqbMn5kE4PKi1A3X6RIojH4H3ibi/HIA2b7ocd7VutK6QaFQMpIVvp5SlfELxWvqI2LQa52ecQR7sJiVY+SOn2wShZLtZsjUH/gSRWdUokJX8Yus+dMTOSiRbrJkOBRvhTRUuihLd3ExbOCvcdcy1I4YraD2vICZ56gvKtpC9YVRHboPFH4aBYo9opME1X2OOraDTgmnQ7kzmdV9UD2pBqWIcuERY5deDWE0l4qPG4pGGJuQ6SU8ZK6WxfjC7ggs4HnYOzPWrr+KzbQDEkfPXZ03LnNNfWlUkR+xKxcK7S/LqXWP/0oYrO76QNzEScVySImJYlPam90iVpu4elDRIv+ZuuArYEOILFQxqPvdEeds2fM80P2NuZYoMSLlKEDLeoeEjSTpj10r7Oq2WpUTAGOKkNyHz4Oqlu+sYbRavlU9TVW2+UjBoHUJna0TBaWBvXB/6jMb1BY15kTLPyuy41tXXPkccNCavIySaHisxlSnR06+ZFQ5M6go87DVSegxXAtGalAzEwwhAqlQTmCXtE5yn1iEfMVWC1qDz2OrUaa7cpYUYCBvkYoCINNnSO1QMSezP6NhjdS5y3HTjeHfVUXVjKLrNLew9pqdOoLme6E7mIZPmIyCdAT2tXzNShq+HzrJMnR/SJeqgwvcWbl7gCXpi8CY8HkPvtoboL/HvcznrL1Jjgs98qC5MV3v9Zwv0GCnHAKnbmDjAjJQBNZRRp2ob2FPn2k4q1NtApO5Vky+DIINgCsm7dYkLD/mtUyE/L7y7loWG5mbLv9VId06QhnR+vtLkgNt+tOdQ3zvxPoUfWF4bSjO21ThZSenGOT8Jsd7q83D1oH75MYXfGSfZ2WqUbrSk78P80yt4EjM9ib2ZH3l9wgmnfld5kufPNN2WKl9FGFzC4r7eZc9rUekGfDJt/bAUehp8xL4P8lL7EnupHMYscPGwvNBiYalmsc02iMakqyPV16Hovf8Bk1jL2aA7pv1DV56kzmWJ6D2qk7kYVW44ENhqF9VXO7NTuRs0yYVdPb0adsrMo9unRNylofNjvMhyHq1nTJsj3sXnsNpKQUabdGXwNji1LCxA8f9QYwX7RYHHdU7zHGJfxT2mW37qtvtQiP7GdyFEUzAx+uxmPV7SAVWv+IvX5O2k5Y4Nmf5NEb5gnTSxoPwuGwILcZSLZylpLJTmh0aHU1cds1N8QGuelzdASXPGTwvhgcyoQrR2pyGjENuPtYBczzTiGD0eNuoGpqHXvJy7vbKyABaOR3T3PYGD0lrt4pNc6xT37DYwYUTxuyP8ZLbeGrCf76hNQgAXKQk4d7LrnfLit62BjDhCWk7wKBcipDpR3j2tqki/J4guyXGkfeQ7wZjSaUx5xlJOSvDqjadmYSxmJ30v3xFH5SX9X9ukJdUnrutTtovpRN103BLt1fJhlhHkEXdYJf5F2+khaMva/KDr0s7oind6NQHPdvrqxum1z/5npsimq4+D9ZyGIngLfLOOIJg+vASWdjBtbeKWI9rTQNBjrtighvmFjwWTOyH7Yhu8be55amUzepQzRh6m/lSw7+tuOpsmSaKk2S0ofRnHlJobHT0EQqLdE7aZeu4jXcabEneNpbEo9WA/XmkNgG0DbuwGbBrITsJvkxhnfOS1mkNzGoQr8eNssHf7k2GuhhIPgUp40IpPTc8xJsMA7guNvsls2OVnfPaKJXl7YqKakOtDYz8RDLc9qeNhTmujGrXlRBy+RFDEzwEjSohZQqQLCflS6cAJm1yEhbwvaGZAIlFPxDq0aaBapd7+51p8TPcRf7lML2FUJkILVoqLpkluq4vzSbLA0N03HzeRDo1aFYlSN89fzQMDwclH8XQ7h0cG0V5kUbdfDAgxoiqmqYSAdJBvnCg1x4GJTloBthwQr1Lsl7Xyx2f+HJHm3Sx6Gh9sNOllN66w3n1DJq6+kN9xB6xXNO5sLqmSD1Q8O9tUconY5xKr31mDceevvV5tdycL7poU4Uj2L5bVsCffA/GvcI7dKivTIYY+s6jzFfFKRLR45YFA8Jm20vTU+W/7zV7rnZ5cy58QFTUq8dm6evMFS6QR9RbxMxB0ezV962EuGIgq6dFHlGXS1nFQiOZskhOuZTGSYZ4YQise8+jbHHv/mtraNzZ3GpWcPfmxs0Iyiz55nPeopOBzlpMSimN83ORRao6yfa9Gh2cTmmmCLe8hrxQMPvGHu4qzjmcav6mKszSW8MN+kjcFOJqnnuYd5GIEyhNUBYITZD9eug0nfJ0qXy5LQDJ6f0Xpyz37YFn6j8UW1otPcUMogEO5P/dqBct85qe7c+lQSV/esPnPTpbovtmmYJKjHaM0sFUMrcI8xu7Naj7WHnsDZ0khdRQyMlbdAMwMv/zBXfmIpKDpRYlD1qHizN4qUmPtwMFLnyRaGirtNGEfNLZkwz8hD63QH48DcohdAADg78zTFkKSKm4sqReAh+u23GGVYz+b/r7PJ+WW2cpTY0l2joOhR3hvn77VIrUnuGXKQDJTL4V93NdoqAj82vqLlDrI0sWG0hC8PX7VV0kGbnRtl73a4hZ1oAsOh3uyReQVBL0ZjTsuoheX/isyX2jOw54rFIZKCrO5QcGq0H/wGTxpGo', 'base64'));"); + duk_peval_string_noresult(ctx, "addCompressedModule('zip-reader', Buffer.from('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', 'base64'));"); + + // zip-writer, refer to modules/zip-writer.js + duk_peval_string_noresult(ctx, "addCompressedModule('zip-writer', Buffer.from('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', 'base64'));"); #ifndef _NOHECI diff --git a/modules/zip-reader.js b/modules/zip-reader.js index 4de07a5..4a56a5f 100644 --- a/modules/zip-reader.js +++ b/modules/zip-reader.js @@ -233,7 +233,37 @@ function zippedObject(table) extractNext(ret); return (ret); - } + }; + this._readLocalHeaderSink = function _readLocalHeaderSink(err, bytesRead, buffer) + { + var info = _readLocalHeaderSink.info; + + console.info1('Local File Record -> '); + var filenameLength = buffer.readUInt32LE(26); + console.info1(' General Purpose Flag: ' + buffer.readUInt16LE(6)); + console.info1(' CRC-32 of uncompressed data: ' + buffer.readUInt32LE(14)); + console.info1(' Compression Method: ' + buffer.readUInt16LE(8)); + console.info1(' Compressed Size: ' + buffer.readUInt32LE(18)); + console.info1(' Uncompressed Size: ' + buffer.readUInt32LE(22)); + console.info1(' Last Modification Time: ' + buffer.readUInt16LE(10)); + console.info1(' Last Modification Date: ' + buffer.readUInt16LE(12)); + console.info1(' Extra Field Length: ' + buffer.readUInt16LE(28)); + require('fs').read(info.fd, { buffer: Buffer.alloc(filenameLength) }, function (e, b, f) + { + console.info1(' File Name: ' + f.toString()); + require('fs').read(info.fd, { buffer: Buffer.alloc(10) }, function (e2, b2, f2) + { + console.info1(' Compressed Data Sample: ' + f2.toString('hex')); + }); + }); + }; + this._readLocalHeaderSink.self = this; + this.readLocalHeader = function readLocalHeader(name) + { + var info = this._table[name]; + this._readLocalHeaderSink.info = info; + require('fs').read(info.fd, { buffer: Buffer.alloc(30), position: info.offset }, this._readLocalHeaderSink); + }; } function read(path) @@ -244,6 +274,19 @@ function read(path) ret._rej('File not found'); return (ret); } + ret._tmp = {}; + require('events').EventEmitter.call(ret._tmp); + ret._tmp.on('~', function () { if (this._fd) { require('fs').closeSync(this._fd); } }); + ret.close = function close() + { + if (this._fd) + { + require('fs').closeSync(this._fd); + this._fd = null; + } + } + + ret._len = require('fs').statSync(path).size; ret._fd = require('fs').openSync(path, require('fs').constants.O_RDONLY); ret._cdr = function _cdr(err, bytesRead, buffer) @@ -257,7 +300,30 @@ function read(path) var comLength = buffer.readUInt16LE(32); var name = buffer.slice(46, 46 + nameLength).toString(); - table[name] = { name: name, compressedSize: buffer.readUInt32LE(20), offset: buffer.readUInt32LE(42), fd: _cdr.self._fd, compression: buffer.readUInt16LE(10), crc: buffer.readUInt32LE(16) }; + console.info1('Central Directory Record:'); + console.info1(' Version: ' + buffer.readUInt16LE(4)); + console.info1(' Minimum: ' + buffer.readUInt16LE(6)); + console.info1(' Name: ' + name); + console.info1(' CRC-32 of Uncompressed data: ' + buffer.readUInt32LE(16)); + console.info1(' Uncompressed Size: ' + buffer.readUInt32LE(24)); + console.info1(' Compressed Size: ' + buffer.readUInt32LE(20)); + console.info1(' File Last Modification Time: ' + buffer.readUInt16LE(12)); + console.info1(' File Last Modification Date: ' + buffer.readUInt16LE(14)); + console.info1(' Internal Attributes: ' + buffer.readUInt16LE(36)); + console.info1(' External Attributes: ' + buffer.readUInt32LE(38)); + console.info1(' Local Header at: ' + buffer.readUInt32LE(42)); + + + table[name] = + { + name: name, + compressedSize: buffer.readUInt32LE(20), + uncompressedSize: buffer.readUInt32LE(24), + offset: buffer.readUInt32LE(42), + fd: _cdr.self._fd, + compression: buffer.readUInt16LE(10), + crc: buffer.readUInt32LE(16) + }; buffer = buffer.slice(46 + nameLength + efLength + comLength); } @@ -272,6 +338,14 @@ function read(path) { if ((record = buffer.slice(buffer.length - i)).readUInt32LE() == EOCDR) { + console.info1('Found Start of ECD Record ' + i + ' bytes from end of file'); + console.info1('-------------------------'); + console.info1(' Disk #: ' + record.readUInt16LE(4)); + console.info1(' Number of Central Directory Records on this disc: ' + record.readUInt16LE(8)); + console.info1(' Total number of Central Directory Records: ' + record.readUInt16LE(10)); + console.info1(' Size of Central Directory: ' + record.readUInt32LE(12) + ' bytes'); + console.info1(' Central Directory Records should be at offset: ' + record.readUInt32LE(16)); + require('fs').read(_eocdr.self._fd, { buffer: Buffer.alloc(record.readUInt32LE(12)), position: record.readUInt32LE(16) }, _eocdr.self._cdr); break; } diff --git a/modules/zip-writer.js b/modules/zip-writer.js new file mode 100644 index 0000000..c58c931 --- /dev/null +++ b/modules/zip-writer.js @@ -0,0 +1,306 @@ +/* +Copyright 2020 Intel Corporation + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +var EOCDR = 101010256; +var CDR = 33639248; +var LFR = 67324752; +var DDR = 134695760; + +var duplex = require('stream').Duplex; + +function convertToMSDOSTime(datetimestring) +{ + // '2020-06-17T20:58:29Z'; + + var datepart = datetimestring.split('T')[0].split('-'); + dt = (parseInt(datepart[0]) - 1980) << 9; + dt |= (parseInt(datepart[1]) << 5); + dt |= (parseInt(datepart[2])); + + var timepart = datetimestring.split('T')[1].split(':'); + var tmp = (parseInt(timepart[0]) << 11); + tmp |= (parseInt(timepart[1]) << 5); + tmp |= (parseInt(timepart[2].split('Z')[0]) / 2); + + return ({ date: dt, time: tmp }); +} + +function getBaseFolder(val) +{ + var test = [] + var D = process.platform == 'win32' ? '\\' : '/'; + var base = ''; + var tmp; + var i; + var ok; + + for (i = 0; i < val.length; ++i) + { + test.push(val[i].split(D)); + } + + if (val.length == 1) + { + test[0].pop(); + return (test.join(D) + D); + } + + while (true) + { + ok = true; + for (i = 0; i < val.length; ++i) + { + if (i == 0) + { + tmp = test[i].shift(); + } + else + { + if (tmp != test[i].shift()) + { + ok = false; + break; + } + } + } + if (ok) + { + base += (base == '' ? tmp : (D + tmp)); + } + else + { + break; + } + } + + return (base == '' ? '' : (base + D)); +} + +function finished(options) +{ + console.info1('Writing Central Directory Records...'); + var pos; + var CD; + var namelen; + + this._pendingCDR = []; + this._CDRSize = 0; + + // Write the Central Directory Headers + for(pos in options._localFileTable) + { + namelen = options._localFileTable[pos].readUInt32LE(26); + CD = Buffer.alloc(46 + namelen); + this._CDRSize += (46 + namelen); + + options._localFileTable[pos].copy(CD, 46, 30, 30 + namelen); + options._localFileTable[pos].copy(CD, 16, 14, 14 + 12); + options._localFileTable[pos].copy(CD, 12, 10, 14); + + CD.writeUInt32LE(CDR, 0); // Signature + CD.writeUInt16LE(20, 4); // Version + CD.writeUInt16LE(20, 6); // Minimum + CD.writeUInt16LE(0x08, 8); // General Purpose Bit Flag + CD.writeUInt16LE(8, 10); // Compression Method + + CD.writeUInt16LE(namelen, 28); // File Name Length + + CD.writeUInt16LE(1, 36); // Internal Attributes + CD.writeUInt32LE(32, 38); // External Attributes + + CD.writeUInt32LE(parseInt(pos), 42); // Relative Offset + + console.info1(' Record:'); + console.info1(' FileName: ' + CD.slice(46).toString()); + console.info1(' Compressed Size: ' + CD.readUInt32LE(20)); + console.info1(' Uncompressed Size: ' + CD.readUInt32LE(24)); + console.info1(' Last Modified Time: ' + CD.readUInt16LE(12)); + console.info1(' Last Modified Date: ' + CD.readUInt16LE(14)); + console.info1(' Local Record Offset: ' + CD.readUInt32LE(42)); + + this._pendingCDR.unshift(CD); + } + this._NumberOfCDR = this._pendingCDR.length; + this._CDRPosition = this._currentPosition; + + this.write(this._pendingCDR.pop(), this._writeCDR); +} + +function next(options) +{ + if (!options) { options = this.options; } + + // this = zip-stream + while (options.files.length > 0 && !require('fs').existsSync(options.files.peek())) { options.files.pop(); } + if (options.files.length == 0) { finished.call(this, options); return; } + var fstat = require('fs').statSync(options.files.peek()); + + this._currentFile = options.files.peek(); + this._currentFD = require('fs').openSync(this._currentFile, require('fs').constants.O_RDONLY); + this._currentName = this._currentFile.substring(options._baseFolder.length); + this._currentFileLength = fstat.size; + this._currentCRC = 0; + this._compressedBytes = 0; + this._timestamp = convertToMSDOSTime(fstat.mtime); + if (!this._ubuffer) { this._ubuffer = Buffer.alloc(4096); } + var nameBuffer = Buffer.from(this._currentName); + this._header = Buffer.alloc(30 + nameBuffer.length); + + this._header.writeUInt32LE(LFR, 0); // Signature + this._header.writeUInt16LE(0x08, 6); // General Purpose Bit Flag + this._header.writeUInt16LE(8, 8); // Compression Method + + this._header.writeUInt16LE(this._timestamp.time, 10); // File Last Modification Time + this._header.writeUInt16LE(this._timestamp.date, 12); // File Last Modification Date + + this._header.writeUInt32LE(this._currentFileLength, 22); // Uncompressed size + this._header.writeUInt16LE(nameBuffer.length, 26); // File name length + nameBuffer.copy(this._header, 30); // File name + options._localFileTable[this._currentPosition] = this._header; + + this.write(this._header); + this._compressor = require('compressed-stream').createCompressor({ WBITS: -15 }); + this._compressor.compressedBytes = this._currentPosition; + this._compressor.parent = this; + this._compressor.pipe(this, { end: false }); + require('fs').read(this._currentFD, { buffer: this._ubuffer }, this._uncompressedReadSink); +} + +function write(options) +{ + if (!options.files || options.files.length == 0) { throw ('No file specified'); } + var ret = new duplex( + { + write: function (chunk, flush) + { + this._currentPosition += chunk.length; + if (this._pushOK) + { + this._pushOK = this.push(chunk); + if (this._pushOK) + { + flush(); + this._flush = null; + } + else + { + this._flush = flush; + } + } + else + { + this._pendingData.push(chunk); + this._flush = flush; + } + }, + final: function (flush) + { + if (this._pushOK) + { + this.push(null); + flush(); + } + else + { + this._ended = true; + } + }, + read(size) + { + this._pushOK = true; + while (this._pendingData.length > 0 && (this._pushOK = this.push(this._pendingData.shift()))); + if (this._pushOK) + { + if (this._flush) + { + this._flush(); + this._flush = null; + } + else + { + this.emit('drain'); + } + } + } + }); + ret._currentPosition = 0; + ret._ObjectID = 'zip-writer.duplexStream'; + ret.bufferMode = 1; + ret.options = options; + ret._pendingData = []; + ret._pushOK = false; + ret._ended = false; + ret._flush = null; + ret.pause(); + + options._localFileTable = {}; + options._baseFolder = getBaseFolder(options.files); + + ret._uncompressedReadSink = function _uncompressedReadSink(err, bytesRead, buffer) + { + var self = _uncompressedReadSink.self; + if(bytesRead == 0) + { + // DONE + self._compressor.end(); + self._compressor.unpipe(); + + self._header.writeUInt32LE(self._currentCRC, 14); // Uncompressed CRC + self._header.writeUInt32LE(self._currentPosition - self._compressor.compressedBytes, 18); // Compresed Size + self._header.writeUInt32LE(self._currentFileLength, 22); // Uncompressed Size + require('fs').closeSync(self._currentFD); + self.options.files.pop(); + self.write(self._header.slice(14, 26), next); + return; + } + buffer = buffer.slice(0, bytesRead); + self._currentCRC = crc32(buffer, self._currentCRC); // Update CRC + self._compressor.write(buffer, function () + { + require('fs').read(self._currentFD, { buffer: self._ubuffer }, self._uncompressedReadSink); + }); + }; + ret._uncompressedReadSink.self = ret; + + ret._writeCDR = function _writeCDR(err, bytesRead, buffer) + { + if(this._pendingCDR.length>0) + { + this.write(this._pendingCDR.pop(), this._writeCDR); + return; + } + else + { + console.info1('Write End of Central Directory'); + var ecdr = Buffer.alloc(22); + ecdr.writeUInt32LE(EOCDR, 0); // Signature + ecdr.writeUInt16LE(this._NumberOfCDR, 8); // Number of CD Records on this disk + ecdr.writeUInt16LE(this._NumberOfCDR, 10); // Total number of CD Records + ecdr.writeUInt32LE(this._CDRSize, 12); // Size of CD Records in bytes + ecdr.writeUInt32LE(this._CDRPosition, 16); // Offset start of CDR + this.write(ecdr, function () + { + this.end(); + }); + } + }; + + next.call(ret, options); + return (ret); +} + + +module.exports = { write: write };