1
0
Fork 0
mirror of https://github.com/codedread/bitjs synced 2025-10-03 09:39:16 +02:00

Move over to posting UnarchiveInfoEvents. Post UnarchiveStartEvent

This commit is contained in:
codedread 2011-09-16 15:52:36 -04:00
parent 386a068447
commit ad9b98dd61
5 changed files with 126 additions and 66 deletions

View file

@ -65,19 +65,10 @@ bitjs.inherits = function(childCtor, parentCtor) {
bitjs.archive.UnarchiveEvent = function(type) {
/**
* The event type.
*
* @type {string}
* @private
*/
this.type_ = type;
};
/**
* Returns the event type.
*
* @return {string} the event type.
*/
bitjs.archive.UnarchiveEvent.prototype.getType = function() {
return this.type_;
this.type = type;
};
/**
@ -88,9 +79,47 @@ bitjs.archive.UnarchiveEvent.Type = {
PROGRESS: 'progress',
EXTRACT: 'extract',
FINISH: 'finish',
INFO: 'info',
ERROR: 'error'
};
/**
* Useful for passing info up to the client (for debugging).
*
* @param {string} msg The info message.
*/
bitjs.archive.UnarchiveInfoEvent = function(msg) {
bitjs.base(this, bitjs.archive.UnarchiveEvent.Type.INFO);
/**
* The information message.
*
* @type {string}
*/
this.msg = msg;
};
bitjs.inherits(bitjs.archive.UnarchiveInfoEvent, bitjs.archive.UnarchiveEvent);
/**
* Start event.
*
* @param {string} msg The info message.
*/
bitjs.archive.UnarchiveStartEvent = function() {
bitjs.base(this, bitjs.archive.UnarchiveEvent.Type.START);
};
bitjs.inherits(bitjs.archive.UnarchiveStartEvent, bitjs.archive.UnarchiveEvent);
/**
* Finish event.
*
* @param {string} msg The info message.
*/
bitjs.archive.UnarchiveFinishEvent = function() {
bitjs.base(this, bitjs.archive.UnarchiveEvent.Type.FINISH);
};
bitjs.inherits(bitjs.archive.UnarchiveFinishEvent, bitjs.archive.UnarchiveEvent);
/**
* All extracted files returned by an Unarchiver will implement
* the following interface:
@ -139,7 +168,7 @@ bitjs.archive.Unarchiver.prototype.worker_ = null;
* @protected.
*/
bitjs.archive.Unarchiver.prototype.getScriptFileName = function() {
throw "Subclasses of AbstractUnarchiver must overload getScriptFileName()";
throw 'Subclasses of AbstractUnarchiver must overload getScriptFileName()';
};
/**
@ -179,7 +208,7 @@ bitjs.archive.Unarchiver.prototype.removeEventListener = function(type, listener
*/
bitjs.archive.Unarchiver.prototype.handleWorkerEvent_ = function(e) {
if (e instanceof bitjs.archive.UnarchiveEvent) {
var listeners = this.listeners_[e.getType()];
var listeners = this.listeners_[e.type];
if (listeners instanceof Array) {
listeners.forEach(function (listener) { listener(e) });
}
@ -192,17 +221,23 @@ bitjs.archive.Unarchiver.prototype.handleWorkerEvent_ = function(e) {
* Starts the unarchive in a separate Web Worker thread and returns immediately.
*/
bitjs.archive.Unarchiver.prototype.start = function() {
var me = this;
var scriptFileName = this.getScriptFileName();
if (scriptFileName) {
this.worker_ = new Worker(scriptFileName);
this.worker_.onerror = function(e) {
alert("Worker error: " + e.message);
console.log('Worker error: message = ' + e.message);
throw e;
};
this.worker_.onmessage = function(e) {
alert("Worker onmessage: " + e);
if (e instanceof bitjs.archive.UnarchiveEvent) {
me.handleWorkerEvent_(e.data);
} else if (typeof e.data == 'string') {
// Just log any strings the workers pump our way.
console.log(e.data);
}
};
this.worker_.postMessage({file: this.ab});
@ -218,7 +253,7 @@ bitjs.archive.Unzipper = function(arrayBuffer) {
bitjs.base(this, arrayBuffer);
};
bitjs.inherits(bitjs.archive.Unzipper, bitjs.archive.Unarchiver);
bitjs.archive.Unzipper.prototype.getScriptFileName = function() { return "unzip.js" };
bitjs.archive.Unzipper.prototype.getScriptFileName = function() { return 'unzip.js' };
})();

View file

@ -48,6 +48,7 @@
// unit tests
// testAddRemoveEventListeners();
// testAbstractUnarchiveThrows();
// var uz = new bitjs.archive.Unzipper(null);
document.body.querySelector("#filechooser").addEventListener("change",
function(evt) {
@ -58,12 +59,14 @@
var fr = new FileReader();
fr.onload = function() {
var ua = new bitjs.archive.Unzipper(fr.result);
ua.addEventListener(bitjs.archive.UnarchiveEvent.Type.INFO, function(e) {
console.log("handler: " + e.msg);
})
ua.start();
};
fr.readAsArrayBuffer(blob);
}
}, false);
var uz = new bitjs.archive.Unzipper(null);
</script>
</html>

View file

@ -11,6 +11,12 @@
// This file expects to be invoked as a Worker (see onmessage below).
importScripts('binary.js');
importScripts('archive.js');
// Helper function.
var info = function(str) {
postMessage(new bitjs.archive.UnarchiveInfoEvent(str));
};
// Volume Types
var MARK_HEAD = 0x72,
@ -31,17 +37,17 @@ var RarVolumeHeader = function(bstream, bDebug) {
var headPos = bstream.bytePtr;
// byte 1,2
postMessage("Rar Volume Header @"+bstream.bytePtr);
info("Rar Volume Header @"+bstream.bytePtr);
this.crc = bstream.readBits(16);
//console.log(this.crc);
if (bDebug)
postMessage(" crc=" + this.crc);
info(" crc=" + this.crc);
// byte 3
this.headType = bstream.readBits(8);
if (bDebug)
postMessage(" headType=" + this.headType);
info(" headType=" + this.headType);
// Get flags
// bytes 4,5
@ -49,7 +55,7 @@ var RarVolumeHeader = function(bstream, bDebug) {
this.flags.value = bstream.peekBits(16);
if (bDebug)
postMessage(" flags=" + twoByteValueToHexString(this.flags.value));
info(" flags=" + twoByteValueToHexString(this.flags.value));
switch (this.headType) {
case MAIN_HEAD:
this.flags.MHD_VOLUME = !!bstream.readBits(1);
@ -80,7 +86,7 @@ var RarVolumeHeader = function(bstream, bDebug) {
this.flags.LHD_EXTFLAGS = !!bstream.readBits(1); // 0x2000
bstream.readBits(2); // unused
if (bDebug)
postMessage(" LHD_SPLIT_BEFORE = " + this.flags.LHD_SPLIT_BEFORE);
info(" LHD_SPLIT_BEFORE = " + this.flags.LHD_SPLIT_BEFORE);
break;
default:
bstream.readBits(16);
@ -89,7 +95,7 @@ var RarVolumeHeader = function(bstream, bDebug) {
// byte 6,7
this.headSize = bstream.readBits(16);
if (bDebug)
postMessage(" headSize=" + this.headSize);
info(" headSize=" + this.headSize);
switch (this.headType) {
case MAIN_HEAD:
this.highPosAv = bstream.readBits(16);
@ -97,7 +103,7 @@ var RarVolumeHeader = function(bstream, bDebug) {
if (this.flags.MHD_ENCRYPTVER)
this.encryptVer = bstream.readBits(8);
if (this.debug)
postMessage("Found MAIN_HEAD with highPosAv=" + this.highPosAv + ", posAv=" + this.posAv);
info("Found MAIN_HEAD with highPosAv=" + this.highPosAv + ", posAv=" + this.posAv);
break;
case FILE_HEAD:
this.packSize = bstream.readBits(32);
@ -111,7 +117,7 @@ var RarVolumeHeader = function(bstream, bDebug) {
this.fileAttr = bstream.readBits(32);
if (this.flags.LHD_LARGE) {
postMessage("Warning: Reading in LHD_LARGE 64-bit size values");
info("Warning: Reading in LHD_LARGE 64-bit size values");
this.HighPackSize = bstream.readBits(32);
this.HighUnpSize = bstream.readBits(32);
} else {
@ -138,7 +144,7 @@ var RarVolumeHeader = function(bstream, bDebug) {
this.filename = _s;
if (this.flags.LHD_SALT) {
postMessage("Warning: Reading in 64-bit salt value");
info("Warning: Reading in 64-bit salt value");
this.salt = bstream.readBits(64); // 8 bytes
}
@ -160,19 +166,19 @@ var RarVolumeHeader = function(bstream, bDebug) {
}
if (this.flags.LHD_COMMENT) {
postMessage("Found a LHD_COMMENT");
info("Found a LHD_COMMENT");
}
while(headPos + this.headSize > bstream.bytePtr) bstream.readBits(1);
if (this.debug)
postMessage("Found FILE_HEAD with packSize=" + this.packSize + ", unpackedSize= " + this.unpackedSize + ", hostOS=" + this.hostOS + ", unpVer=" + this.unpVer + ", method=" + this.method + ", filename=" + this.filename);
info("Found FILE_HEAD with packSize=" + this.packSize + ", unpackedSize= " + this.unpackedSize + ", hostOS=" + this.hostOS + ", unpVer=" + this.unpVer + ", method=" + this.method + ", filename=" + this.filename);
break;
default:
if (this.debug)
postMessage("Found a header of type 0x" + byteValueToHexString(this.headType));
info("Found a header of type 0x" + byteValueToHexString(this.headType));
// skip the rest of the header bytes (for now)
bstream.readBytes( this.headSize - 7 );
break;
@ -247,7 +253,7 @@ function RarReadTables(bstream) {
bstream.readBits( (8 - bstream.bitPtr) & 0x7 );
if (bstream.readBits(1)) {
postMessage("Error! PPM not implemented yet");
info("Error! PPM not implemented yet");
return;
}
@ -373,7 +379,7 @@ function RarMakeDecodeTables(BitLength, offset, dec, size) {
// TODO: implement
function Unpack15(bstream, Solid) {
postMessage("ERROR! RAR 1.5 compression not supported");
info("ERROR! RAR 1.5 compression not supported");
}
function Unpack20(bstream, Solid) {
@ -677,7 +683,7 @@ function RarReadVMCode(bstream) {
function RarAddVMCode(firstByte, vmCode, length) {
//console.log(vmCode);
if (vmCode.length > 0) {
postMessage("Error! RarVM not supported yet!");
info("Error! RarVM not supported yet!");
}
return true;
}
@ -723,7 +729,7 @@ function unpack(v) {
rBuffer = new bitjs.io.ByteBuffer(v.header.unpackedSize);
postMessage("Unpacking "+v.filename+" RAR v"+Ver);
info("Unpacking "+v.filename+" RAR v"+Ver);
switch(Ver) {
case 15: // rar 1.5 compression
@ -753,7 +759,7 @@ var RarLocalFile = function(bstream, bDebug) {
if (this.header.headType != FILE_HEAD && this.header.headType != ENDARC_HEAD) {
this.isValid = false;
//progress.isValid = false;
postMessage("Error! RAR Volume did not include a FILE_HEAD header ");
info("Error! RAR Volume did not include a FILE_HEAD header ");
}
else {
// read in the compressed data
@ -770,7 +776,7 @@ RarLocalFile.prototype.unrar = function() {
if (!this.header.flags.LHD_SPLIT_BEFORE) {
// unstore file
if (this.header.method == 0x30) {
postMessage("Unstore "+this.filename);
info("Unstore "+this.filename);
this.isValid = true;
progress.currentFileBytesUnzipped += this.fileData.length;
@ -787,6 +793,7 @@ RarLocalFile.prototype.unrar = function() {
}
var unrar = function(arrayBuffer, bDebug) {
postMessage(new bitjs.archive.UnarchiveStartEvent());
var bstream = new bitjs.io.BitStream(arrayBuffer, false /* rtl */);
var header = new RarVolumeHeader(bstream, bDebug);
@ -795,12 +802,12 @@ var unrar = function(arrayBuffer, bDebug) {
header.flags.value == 0x1A21 &&
header.headSize == 7) {
if (bDebug)
postMessage("Found RAR signature");
info("Found RAR signature");
var mhead = new RarVolumeHeader(bstream, bDebug);
if (mhead.headType != MAIN_HEAD) {
progress.isValid = false;
postMessage("Error! RAR did not include a MAIN_HEAD header");
info("Error! RAR did not include a MAIN_HEAD header");
}
else {
var localFiles = [],
@ -809,7 +816,7 @@ var unrar = function(arrayBuffer, bDebug) {
try {
localFile = new RarLocalFile(bstream, bDebug);
if (bDebug)
postMessage("RAR localFile isValid=" + localFile.isValid + ", volume packSize=" + localFile.header.packSize);
info("RAR localFile isValid=" + localFile.isValid + ", volume packSize=" + localFile.header.packSize);
if (localFile && localFile.isValid && localFile.header.packSize > 0) {
progress.totalSizeInBytes += localFile.header.unpackedSize;
progress.isValid = true;
@ -821,7 +828,7 @@ var unrar = function(arrayBuffer, bDebug) {
} catch(err) {
break;
}
//postMessage("bstream" + bstream.bytePtr+"/"+bstream.bytes.length);
//info("bstream" + bstream.bytePtr+"/"+bstream.bytes.length);
} while( localFile.isValid );
progress.totalNumFilesInZip = localFiles.length;
@ -849,7 +856,7 @@ var unrar = function(arrayBuffer, bDebug) {
return bnum - anum;*/
});
postMessage(localFiles.map(function(a){return a.filename}).join(', '));
info(localFiles.map(function(a){return a.filename}).join(', '));
for (var i = 0; i < localFiles.length; ++i) {
var localfile = localFiles[i];

View file

@ -10,6 +10,12 @@
// This file expects to be invoked as a Worker (see onmessage below).
importScripts('binary.js');
importScripts('archive.js');
// Helper function.
var info = function(str) {
postMessage(new bitjs.archive.UnarchiveInfoEvent(str));
};
// Removes all characters from the first zero-byte in the string onwards.
var readCleanString = function(bstr, numBytes) {
@ -56,14 +62,14 @@ var TarLocalFile = function(bstream, bDebug) {
this.fileData = null;
if (this.debug) {
postMessage("Untarring file '" + this.filename + "'");
postMessage(" size = " + this.size);
postMessage(" typeflag = " + this.typeflag);
info("Untarring file '" + this.filename + "'");
info(" size = " + this.size);
info(" typeflag = " + this.typeflag);
}
// A regular file.
if (this.typeflag == 0) {
postMessage(" This is a regular file.");
info(" This is a regular file.");
var sizeInBytes = parseInt(this.size);
this.fileData = new Uint8Array(bstream.bytes.buffer, bstream.ptr, this.size);
if (this.name.length > 0 && this.size > 0 && this.fileData && this.fileData.buffer) {
@ -80,7 +86,7 @@ var TarLocalFile = function(bstream, bDebug) {
}
} else if (this.typeflag == 5) {
if (this.debug) {
postMessage(" This is a directory.")
info(" This is a directory.")
}
}
};
@ -89,6 +95,7 @@ var TarLocalFile = function(bstream, bDebug) {
// returns null on error
// returns an array of DecompressedFile objects on success
var untar = function(arrayBuffer, bDebug) {
postMessage(new bitjs.archive.UnarchiveStartEvent());
var bstream = new bitjs.io.ByteStream(arrayBuffer);
var localFiles = [];
@ -134,7 +141,7 @@ var untar = function(arrayBuffer, bDebug) {
// now do the shipping of each file
for (var i = 0; i < localFiles.length; ++i) {
var localfile = localFiles[i];
postMessage("Sending file '" + localfile.filename + "' up");
info("Sending file '" + localfile.filename + "' up");
// update progress
progress.currentFilename = localfile.filename;

View file

@ -12,7 +12,13 @@
// This file expects to be invoked as a Worker (see onmessage below).
importScripts('binary.js');
importScripts('archive.js');
// Helper function.
var info = function(str) {
postMessage(new bitjs.archive.UnarchiveInfoEvent(str));
};
var zLocalFileHeaderSignature = 0x04034b50;
var zArchiveExtraDataSignature = 0x08064b50;
var zCentralFileHeaderSignature = 0x02014b50;
@ -46,25 +52,25 @@ var ZipLocalFile = function(bstream, bDebug) {
}
if (this.debug) {
postMessage("Zip Local File Header:");
postMessage(" version=" + this.version);
postMessage(" general purpose=" + this.generalPurpose);
postMessage(" compression method=" + this.compressionMethod);
postMessage(" last mod file time=" + this.lastModFileTime);
postMessage(" last mod file date=" + this.lastModFileDate);
postMessage(" crc32=" + this.crc32);
postMessage(" compressed size=" + this.compressedSize);
postMessage(" uncompressed size=" + this.uncompressedSize);
postMessage(" file name length=" + this.fileNameLength);
postMessage(" extra field length=" + this.extraFieldLength);
postMessage(" filename = '" + this.filename + "'");
info(new bitjs.archive.UnarchiveInfoEvent("Zip Local File Header:"));
info(" version=" + this.version);
info(" general purpose=" + this.generalPurpose);
info(" compression method=" + this.compressionMethod);
info(" last mod file time=" + this.lastModFileTime);
info(" last mod file date=" + this.lastModFileDate);
info(" crc32=" + this.crc32);
info(" compressed size=" + this.compressedSize);
info(" uncompressed size=" + this.uncompressedSize);
info(" file name length=" + this.fileNameLength);
info(" extra field length=" + this.extraFieldLength);
info(" filename = '" + this.filename + "'");
}
this.extraField = null;
if (this.extraFieldLength > 0) {
this.extraField = bstream.readString(this.extraFieldLength);
if (this.debug) {
postMessage(" extra field=" + this.extraField);
info(" extra field=" + this.extraField);
}
}
@ -93,7 +99,7 @@ ZipLocalFile.prototype.unzip = function() {
// Zip Version 1.0, no compression (store only)
if (this.compressionMethod == 0 ) {
if (this.debug)
postMessage("ZIP v"+this.version+", store only: " + this.filename + " (" + this.compressedSize + " bytes)");
info("ZIP v"+this.version+", store only: " + this.filename + " (" + this.compressedSize + " bytes)");
progress.currentFileBytesUnzipped = this.compressedSize;
progress.totalBytesUnzipped += this.compressedSize;
this.isValid = true;
@ -101,12 +107,12 @@ ZipLocalFile.prototype.unzip = function() {
// version == 20, compression method == 8 (DEFLATE)
else if (this.compressionMethod == 8) {
if (this.debug)
postMessage("ZIP v2.0, DEFLATE: " + this.filename + " (" + this.compressedSize + " bytes)");
info("ZIP v2.0, DEFLATE: " + this.filename + " (" + this.compressedSize + " bytes)");
this.fileData = inflate(this.fileData, this.uncompressedSize);
this.isValid = true;
}
else {
postMessage("UNSUPPORTED VERSION/FORMAT: ZIP v" + this.version + ", compression method=" + this.compressionMethod + ": " + this.filename + " (" + this.compressedSize + " bytes)");
info("UNSUPPORTED VERSION/FORMAT: ZIP v" + this.version + ", compression method=" + this.compressionMethod + ": " + this.filename + " (" + this.compressedSize + " bytes)");
this.isValid = false;
this.fileData = null;
}
@ -122,6 +128,8 @@ ZipLocalFile.prototype.unzip = function() {
// returns null on error
// returns an array of DecompressedFile objects on success
var unzip = function(arrayBuffer, bDebug) {
postMessage(new bitjs.archive.UnarchiveStartEvent());
var bstream = new bitjs.io.ByteStream(arrayBuffer);
// detect local file header signature or return null
if (bstream.peekNumber(4) == zLocalFileHeaderSignature) {
@ -162,7 +170,7 @@ var unzip = function(arrayBuffer, bDebug) {
// archive extra data record
if (bstream.peekNumber(4) == zArchiveExtraDataSignature) {
if (gDebug) {
postMessage(" Found an Archive Extra Data Signature");
info(" Found an Archive Extra Data Signature");
}
// skipping this record for now
bstream.readNumber(4);
@ -174,7 +182,7 @@ var unzip = function(arrayBuffer, bDebug) {
// TODO: handle the rest of the structures (Zip64 stuff)
if (bstream.peekNumber(4) == zCentralFileHeaderSignature) {
if (gDebug) {
postMessage(" Found a Central File Header");
info(" Found a Central File Header");
}
// read all file headers
while (bstream.peekNumber(4) == zCentralFileHeaderSignature) {
@ -205,7 +213,7 @@ var unzip = function(arrayBuffer, bDebug) {
// digital signature
if (bstream.peekNumber(4) == zDigitalSignatureSignature) {
if (gDebug) {
postMessage(" Found a Digital Signature");
info(" Found a Digital Signature");
}
bstream.readNumber(4);
var sizeOfSignature = bstream.readNumber(2);