14b6202eec
Fixes func in helper,web Fixes for pdf reader fixes for calling from another folder renamed to calibreweb for importing in python caller script
378 lines
12 KiB
JavaScript
378 lines
12 KiB
JavaScript
/**
|
|
* archive.js
|
|
*
|
|
* Provides base functionality for unarchiving.
|
|
*
|
|
* Licensed under the MIT License
|
|
*
|
|
* Copyright(c) 2011 Google Inc.
|
|
*/
|
|
|
|
/* global bitjs, Uint8Array */
|
|
|
|
var bitjs = bitjs || {};
|
|
bitjs.archive = bitjs.archive || {};
|
|
|
|
(function() {
|
|
|
|
// ===========================================================================
|
|
// Stolen from Closure because it's the best way to do Java-like inheritance.
|
|
bitjs.base = function(me, optMethodName, varArgs) {
|
|
var caller = arguments.callee.caller;
|
|
if (caller.superClass_) {
|
|
// This is a constructor. Call the superclass constructor.
|
|
return caller.superClass_.constructor.apply(
|
|
me, Array.prototype.slice.call(arguments, 1));
|
|
}
|
|
|
|
var args = Array.prototype.slice.call(arguments, 2);
|
|
var foundCaller = false;
|
|
for (var ctor = me.constructor; ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
|
|
if (ctor.prototype[optMethodName] === caller) {
|
|
foundCaller = true;
|
|
} else if (foundCaller) {
|
|
return ctor.prototype[optMethodName].apply(me, args);
|
|
}
|
|
}
|
|
|
|
// If we did not find the caller in the prototype chain,
|
|
// then one of two things happened:
|
|
// 1) The caller is an instance method.
|
|
// 2) This method was not called by the right caller.
|
|
if (me[optMethodName] === caller) {
|
|
return me.constructor.prototype[optMethodName].apply(me, args);
|
|
} else {
|
|
throw Error(
|
|
"goog.base called from a method of one name " +
|
|
"to a method of a different name");
|
|
}
|
|
};
|
|
bitjs.inherits = function(childCtor, parentCtor) {
|
|
/** @constructor */
|
|
function TempCtor() {}
|
|
TempCtor.prototype = parentCtor.prototype;
|
|
childCtor.superClass_ = parentCtor.prototype;
|
|
childCtor.prototype = new TempCtor();
|
|
childCtor.prototype.constructor = childCtor;
|
|
};
|
|
// ===========================================================================
|
|
|
|
/**
|
|
* An unarchive event.
|
|
*
|
|
* @param {string} type The event type.
|
|
* @constructor
|
|
*/
|
|
bitjs.archive.UnarchiveEvent = function(type) {
|
|
/**
|
|
* The event type.
|
|
*
|
|
* @type {string}
|
|
*/
|
|
this.type = type;
|
|
};
|
|
|
|
/**
|
|
* The UnarchiveEvent types.
|
|
*/
|
|
bitjs.archive.UnarchiveEvent.Type = {
|
|
START: "start",
|
|
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);
|
|
|
|
/**
|
|
* An unrecoverable error has occured.
|
|
*
|
|
* @param {string} msg The error message.
|
|
*/
|
|
bitjs.archive.UnarchiveErrorEvent = function(msg) {
|
|
bitjs.base(this, bitjs.archive.UnarchiveEvent.Type.ERROR);
|
|
|
|
/**
|
|
* The information message.
|
|
*
|
|
* @type {string}
|
|
*/
|
|
this.msg = msg;
|
|
};
|
|
bitjs.inherits(bitjs.archive.UnarchiveErrorEvent, 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);
|
|
|
|
/**
|
|
* Progress event.
|
|
*/
|
|
bitjs.archive.UnarchiveProgressEvent = function(
|
|
currentFilename,
|
|
currentFileNumber,
|
|
currentBytesUnarchivedInFile,
|
|
currentBytesUnarchived,
|
|
totalUncompressedBytesInArchive,
|
|
totalFilesInArchive) {
|
|
bitjs.base(this, bitjs.archive.UnarchiveEvent.Type.PROGRESS);
|
|
|
|
this.currentFilename = currentFilename;
|
|
this.currentFileNumber = currentFileNumber;
|
|
this.currentBytesUnarchivedInFile = currentBytesUnarchivedInFile;
|
|
this.totalFilesInArchive = totalFilesInArchive;
|
|
this.currentBytesUnarchived = currentBytesUnarchived;
|
|
this.totalUncompressedBytesInArchive = totalUncompressedBytesInArchive;
|
|
};
|
|
bitjs.inherits(bitjs.archive.UnarchiveProgressEvent, bitjs.archive.UnarchiveEvent);
|
|
|
|
/**
|
|
* All extracted files returned by an Unarchiver will implement
|
|
* the following interface:
|
|
*
|
|
* interface UnarchivedFile {
|
|
* string filename
|
|
* TypedArray fileData
|
|
* }
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* Extract event.
|
|
*/
|
|
bitjs.archive.UnarchiveExtractEvent = function(unarchivedFile) {
|
|
bitjs.base(this, bitjs.archive.UnarchiveEvent.Type.EXTRACT);
|
|
|
|
/**
|
|
* @type {UnarchivedFile}
|
|
*/
|
|
this.unarchivedFile = unarchivedFile;
|
|
};
|
|
bitjs.inherits(bitjs.archive.UnarchiveExtractEvent, bitjs.archive.UnarchiveEvent);
|
|
|
|
|
|
/**
|
|
* Base class for all Unarchivers.
|
|
*
|
|
* @param {ArrayBuffer} arrayBuffer The Array Buffer.
|
|
* @param {string} optPathToBitJS Optional string for where the BitJS files are located.
|
|
* @constructor
|
|
*/
|
|
bitjs.archive.Unarchiver = function(arrayBuffer, optPathToBitJS) {
|
|
/**
|
|
* The ArrayBuffer object.
|
|
* @type {ArrayBuffer}
|
|
* @protected
|
|
*/
|
|
this.ab = arrayBuffer;
|
|
|
|
/**
|
|
* The path to the BitJS files.
|
|
* @type {string}
|
|
* @private
|
|
*/
|
|
this.pathToBitJS_ = optPathToBitJS || "/";
|
|
|
|
/**
|
|
* A map from event type to an array of listeners.
|
|
* @type {Map.<string, Array>}
|
|
*/
|
|
this.listeners_ = {};
|
|
for (var type in bitjs.archive.UnarchiveEvent.Type) {
|
|
this.listeners_[bitjs.archive.UnarchiveEvent.Type[type]] = [];
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Private web worker initialized during start().
|
|
* @type {Worker}
|
|
* @private
|
|
*/
|
|
bitjs.archive.Unarchiver.prototype.worker_ = null;
|
|
|
|
/**
|
|
* This method must be overridden by the subclass to return the script filename.
|
|
* @return {string} The script filename.
|
|
* @protected.
|
|
*/
|
|
bitjs.archive.Unarchiver.prototype.getScriptFileName = function() {
|
|
throw "Subclasses of AbstractUnarchiver must overload getScriptFileName()";
|
|
};
|
|
|
|
/**
|
|
* Adds an event listener for UnarchiveEvents.
|
|
*
|
|
* @param {string} Event type.
|
|
* @param {function} An event handler function.
|
|
*/
|
|
bitjs.archive.Unarchiver.prototype.addEventListener = function(type, listener) {
|
|
if (type in this.listeners_) {
|
|
if (this.listeners_[type].indexOf(listener) === -1) {
|
|
this.listeners_[type].push(listener);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Removes an event listener.
|
|
*
|
|
* @param {string} Event type.
|
|
* @param {EventListener|function} An event listener or handler function.
|
|
*/
|
|
bitjs.archive.Unarchiver.prototype.removeEventListener = function(type, listener) {
|
|
if (type in this.listeners_) {
|
|
var index = this.listeners_[type].indexOf(listener);
|
|
if (index !== -1) {
|
|
this.listeners_[type].splice(index, 1);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Receive an event and pass it to the listener functions.
|
|
*
|
|
* @param {bitjs.archive.UnarchiveEvent} e
|
|
* @private
|
|
*/
|
|
bitjs.archive.Unarchiver.prototype.handleWorkerEvent_ = function(e) {
|
|
if ((e instanceof bitjs.archive.UnarchiveEvent || e.type) &&
|
|
this.listeners_[e.type] instanceof Array) {
|
|
this.listeners_[e.type].forEach(function (listener) {
|
|
listener(e);
|
|
});
|
|
if (e.type === bitjs.archive.UnarchiveEvent.Type.FINISH) {
|
|
this.worker_.terminate();
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Starts the unarchive in a separate Web Worker thread and returns immediately.
|
|
*/
|
|
bitjs.archive.Unarchiver.prototype.start = function() {
|
|
var me = this;
|
|
var scriptFileName = this.pathToBitJS_ + this.getScriptFileName();
|
|
if (scriptFileName) {
|
|
this.worker_ = new Worker(scriptFileName);
|
|
|
|
this.worker_.onerror = function(e) {
|
|
throw e;
|
|
};
|
|
|
|
this.worker_.onmessage = function(e) {
|
|
if (typeof e.data !== "string") {
|
|
// Assume that it is an UnarchiveEvent. Some browsers preserve the 'type'
|
|
// so that instanceof UnarchiveEvent returns true, but others do not.
|
|
me.handleWorkerEvent_(e.data);
|
|
}
|
|
};
|
|
|
|
this.worker_.postMessage({file: this.ab});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Terminates the Web Worker for this Unarchiver and returns immediately.
|
|
*/
|
|
bitjs.archive.Unarchiver.prototype.stop = function() {
|
|
if (this.worker_) {
|
|
this.worker_.terminate();
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Unzipper
|
|
* @extends {bitjs.archive.Unarchiver}
|
|
* @constructor
|
|
*/
|
|
bitjs.archive.Unzipper = function(arrayBuffer, optPathToBitJS) {
|
|
bitjs.base(this, arrayBuffer, optPathToBitJS);
|
|
};
|
|
bitjs.inherits(bitjs.archive.Unzipper, bitjs.archive.Unarchiver);
|
|
bitjs.archive.Unzipper.prototype.getScriptFileName = function() {
|
|
return "unzip.js";
|
|
};
|
|
|
|
/**
|
|
* Unrarrer
|
|
* @extends {bitjs.archive.Unarchiver}
|
|
* @constructor
|
|
*/
|
|
bitjs.archive.Unrarrer = function(arrayBuffer, optPathToBitJS) {
|
|
bitjs.base(this, arrayBuffer, optPathToBitJS);
|
|
};
|
|
bitjs.inherits(bitjs.archive.Unrarrer, bitjs.archive.Unarchiver);
|
|
bitjs.archive.Unrarrer.prototype.getScriptFileName = function() {
|
|
return "unrar.js";
|
|
};
|
|
|
|
/**
|
|
* Untarrer
|
|
* @extends {bitjs.archive.Unarchiver}
|
|
* @constructor
|
|
*/
|
|
bitjs.archive.Untarrer = function(arrayBuffer, optPathToBitJS) {
|
|
bitjs.base(this, arrayBuffer, optPathToBitJS);
|
|
};
|
|
bitjs.inherits(bitjs.archive.Untarrer, bitjs.archive.Unarchiver);
|
|
bitjs.archive.Untarrer.prototype.getScriptFileName = function() {
|
|
return "untar.js";
|
|
};
|
|
|
|
/**
|
|
* Factory method that creates an unarchiver based on the byte signature found
|
|
* in the arrayBuffer.
|
|
* @param {ArrayBuffer} ab
|
|
* @param {string=} optPathToBitJS Path to the unarchiver script files.
|
|
* @return {bitjs.archive.Unarchiver}
|
|
*/
|
|
bitjs.archive.GetUnarchiver = function(ab, optPathToBitJS) {
|
|
var unarchiver = null;
|
|
var pathToBitJS = optPathToBitJS || "";
|
|
var h = new Uint8Array(ab, 0, 10);
|
|
|
|
if (h[0] === 0x52 && h[1] === 0x61 && h[2] === 0x72 && h[3] === 0x21) { // Rar!
|
|
unarchiver = new bitjs.archive.Unrarrer(ab, pathToBitJS);
|
|
} else if (h[0] === 80 && h[1] === 75) { // PK (Zip)
|
|
unarchiver = new bitjs.archive.Unzipper(ab, pathToBitJS);
|
|
} else { // Try with tar
|
|
unarchiver = new bitjs.archive.Untarrer(ab, pathToBitJS);
|
|
}
|
|
return unarchiver;
|
|
};
|
|
|
|
})();
|