diff --git a/pandora/document/cbr.py b/pandora/document/cbr.py deleted file mode 100644 index f895e934..00000000 --- a/pandora/document/cbr.py +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: utf-8 -*- -import logging -import os -import zipfile - -import ox - -logger = logging.getLogger(__name__) -IMAGE_EXTENSIONS = ['.jpg', '.png', '.gif'] - - -def filter_images(files): - return [f for f in files if os.path.splitext(f)[-1].lower() in IMAGE_EXTENSIONS] - -def filter_folders(files): - out = [] - for path in files: - if not [f for f in files if f.startswith(path + '/')]: - out.append(path) - return out - -def detect_format(path): - with open(path, 'rb') as fd: - head = fd.read(10) - if head[:2] == b'PK': - return 'cbz' - if head[:3] == b'Rar': - return 'cbr' - logger.debug('unknown cbr/cbz file %s - %s', head, path) - return 'unknown' - -def cover(path): - format = detect_format(path) - if format == 'cbz': - cover = cover_cbz(path) - elif format == 'cbr': - cover = cover_cbr(path) - else: - cover = None - return cover - -def cover_cbr(path): - data = None - try: - from unrardll import names, extract_member - except: - logger.error('to extract covers from cbr files you have to install python3-unrardll: apt install python3-unrardll') - return data - try: - files = list(names(path)) - files = filter_folders(files) - files = filter_images(files) - if files: - cover = ox.sorted_strings(files)[0] - filename, data = extract_member(path, lambda h: h['filename'] == cover) - except: - logger.debug('invalid cbr file %s', path) - data = None - return data - -def cover_cbz(path): - data = None - logger.debug('cover %s', path) - data = None - try: - z = zipfile.ZipFile(path) - except zipfile.BadZipFile: - logger.debug('invalid cbz file %s', path) - return data - files = [f.filename for f in z.filelist] - files = filter_images(files) - if files: - cover = ox.sorted_strings(files)[0] - try: - data = z.read(cover) - except: - data = None - return data - -def get_pages(path): - files = [] - format = detect_format(path) - if format == 'cbz': - try: - z = zipfile.ZipFile(path) - except zipfile.BadZipFile: - logger.debug('invalid cbz file %s', path) - return data - files = [f.filename for f in z.filelist] - elif format == 'cbr': - try: - from unrar import rarfile - rar = rarfile.RarFile(path) - files = rar.namelist() - except: - pass - files = filter_images(files) - return len(files) - - -def info(path): - data = {} - data['title'] = os.path.splitext(os.path.basename(path))[0] - data['pages'] = get_pages(path) - return data - diff --git a/pandora/document/models.py b/pandora/document/models.py index ef664df6..0795b765 100644 --- a/pandora/document/models.py +++ b/pandora/document/models.py @@ -27,12 +27,11 @@ from archive.chunk import save_chunk from user.models import Group from user.utils import update_groups -from . import cbr -from . import epub from . import managers -from . import tasks -from . import txt from . import utils +from . import tasks +from . import epub +from . import txt from .fulltext import FulltextMixin, FulltextPageMixin User = get_user_model() @@ -183,9 +182,6 @@ class Document(models.Model, FulltextMixin): elif self.extension == 'txt': prefix = 4 value = self.pages - elif self.extension in ('cbr', 'cbz'): - prefix = 5 - value = self.pages elif self.extension == 'html': prefix = 1 value = self.dimensions @@ -401,13 +397,7 @@ class Document(models.Model, FulltextMixin): @property def dimensions(self): - if self.extension in ( - 'cbr', - 'cbz', - 'epub', - 'pdf', - 'txt', - ): + if self.extension in ('pdf', 'epub', 'txt'): return self.pages elif self.extension == 'html': return len(self.data.get('text', '').split(' ')) @@ -581,15 +571,6 @@ class Document(models.Model, FulltextMixin): path = os.path.join(folder, '%dp%d,%s.jpg' % (size, page, ','.join(map(str, crop)))) if not os.path.exists(path): resize_image(src, path, size=size) - elif self.extension in ('cbr', 'cbz'): - path = os.path.join(folder, '1024.jpg') - if os.path.exists(src) and not os.path.exists(path): - data = cbr.cover(src) - if data: - with open(path, "wb") as fd: - fd.write(data) - else: - return os.path.join(settings.STATIC_ROOT, 'png/document.png') elif self.extension == 'epub': path = os.path.join(folder, '1024.jpg') if os.path.exists(src) and not os.path.exists(path): @@ -597,14 +578,10 @@ class Document(models.Model, FulltextMixin): if data: with open(path, "wb") as fd: fd.write(data) - else: - return os.path.join(settings.STATIC_ROOT, 'png/document.png') elif self.extension == 'txt': path = os.path.join(folder, '1024.jpg') if os.path.exists(src) and not os.path.exists(path): txt.render(src, path) - if not os.path.exists(path): - return os.path.join(settings.STATIC_ROOT, 'png/document.png') elif self.extension in ('jpg', 'png', 'gif', 'webp', 'heic', 'heif', 'cr2'): if os.path.exists(src): if size and page: @@ -648,12 +625,6 @@ class Document(models.Model, FulltextMixin): self.width = -1 self.height = -1 self.pages = utils.pdfpages(self.file.path) - elif self.extension in ('cbr', 'cbz'): - from . import cbr - thumb = self.thumbnail(1024) - if thumb: - self.width, self.height = open_image_rgb(thumb).size - self.pages = cbr.get_pages(self.file.path) elif self.extension == 'epub': thumb = self.thumbnail(1024) if thumb: diff --git a/static/cbr.js/bitjs/archive.js b/static/cbr.js/bitjs/archive.js deleted file mode 100644 index 1596b74b..00000000 --- a/static/cbr.js/bitjs/archive.js +++ /dev/null @@ -1,353 +0,0 @@ -/** - * archive.js - * - * Provides base functionality for unarchiving. - * - * Licensed under the MIT License - * - * Copyright(c) 2011 Google Inc. - */ - -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, opt_methodName, var_args) { - 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[opt_methodName] === caller) { - foundCaller = true; - } else if (foundCaller) { - return ctor.prototype[opt_methodName].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[opt_methodName] === caller) { - return me.constructor.prototype[opt_methodName].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} opt_pathToBitJS Optional string for where the BitJS files are located. - * @constructor - */ -bitjs.archive.Unarchiver = function(arrayBuffer, opt_pathToBitJS) { - /** - * The ArrayBuffer object. - * @type {ArrayBuffer} - * @protected - */ - this.ab = arrayBuffer; - - /** - * The path to the BitJS files. - * @type {string} - * @private - */ - this.pathToBitJS_ = opt_pathToBitJS || ''; - - /** - * A map from event type to an array of listeners. - * @type {Map.} - */ - 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(); - } - } else { - console.log(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.pathToBitJS_ + this.getScriptFileName(); - if (scriptFileName) { - this.worker_ = new Worker(scriptFileName); - - this.worker_.onerror = function(e) { - console.log('Worker error: message = ' + e.message); - throw e; - }; - - this.worker_.onmessage = function(e) { - if (typeof e.data == 'string') { - // Just log any strings the workers pump our way. - console.log(e.data); - } else { - // 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, opt_pathToBitJS) { - bitjs.base(this, arrayBuffer, opt_pathToBitJS); -}; -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, opt_pathToBitJS) { - bitjs.base(this, arrayBuffer, opt_pathToBitJS); -}; -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, opt_pathToBitJS) { - bitjs.base(this, arrayBuffer, opt_pathToBitJS); -}; -bitjs.inherits(bitjs.archive.Untarrer, bitjs.archive.Unarchiver); -bitjs.archive.Untarrer.prototype.getScriptFileName = function() { return 'untar.js' }; - -})(); \ No newline at end of file diff --git a/static/cbr.js/bitjs/io.js b/static/cbr.js/bitjs/io.js deleted file mode 100644 index 6eabfe9a..00000000 --- a/static/cbr.js/bitjs/io.js +++ /dev/null @@ -1,483 +0,0 @@ -/* - * io.js - * - * Provides readers for bit/byte streams (reading) and a byte buffer (writing). - * - * Licensed under the MIT License - * - * Copyright(c) 2011 Google Inc. - * Copyright(c) 2011 antimatter15 - */ - -var bitjs = bitjs || {}; -bitjs.io = bitjs.io || {}; - -(function() { - -// mask for getting the Nth bit (zero-based) -bitjs.BIT = [ 0x01, 0x02, 0x04, 0x08, - 0x10, 0x20, 0x40, 0x80, - 0x100, 0x200, 0x400, 0x800, - 0x1000, 0x2000, 0x4000, 0x8000]; - -// mask for getting N number of bits (0-8) -var BITMASK = [0, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF ]; - - -/** - * This bit stream peeks and consumes bits out of a binary stream. - * - * @param {ArrayBuffer} ab An ArrayBuffer object or a Uint8Array. - * @param {boolean} rtl Whether the stream reads bits from the byte starting - * from bit 7 to 0 (true) or bit 0 to 7 (false). - * @param {Number} opt_offset The offset into the ArrayBuffer - * @param {Number} opt_length The length of this BitStream - */ -bitjs.io.BitStream = function(ab, rtl, opt_offset, opt_length) { - if (!ab || !ab.toString || ab.toString() !== "[object ArrayBuffer]") { - throw "Error! BitArray constructed with an invalid ArrayBuffer object"; - } - - var offset = opt_offset || 0; - var length = opt_length || ab.byteLength; - this.bytes = new Uint8Array(ab, offset, length); - this.bytePtr = 0; // tracks which byte we are on - this.bitPtr = 0; // tracks which bit we are on (can have values 0 through 7) - this.peekBits = rtl ? this.peekBits_rtl : this.peekBits_ltr; -}; - - -/** - * byte0 byte1 byte2 byte3 - * 7......0 | 7......0 | 7......0 | 7......0 - * - * The bit pointer starts at bit0 of byte0 and moves left until it reaches - * bit7 of byte0, then jumps to bit0 of byte1, etc. - * @param {number} n The number of bits to peek. - * @param {boolean=} movePointers Whether to move the pointer, defaults false. - * @return {number} The peeked bits, as an unsigned number. - */ -bitjs.io.BitStream.prototype.peekBits_ltr = function(n, movePointers) { - if (n <= 0 || typeof n != typeof 1) { - return 0; - } - - var movePointers = movePointers || false, - bytePtr = this.bytePtr, - bitPtr = this.bitPtr, - result = 0, - bitsIn = 0, - bytes = this.bytes; - - // keep going until we have no more bits left to peek at - // TODO: Consider putting all bits from bytes we will need into a variable and then - // shifting/masking it to just extract the bits we want. - // This could be considerably faster when reading more than 3 or 4 bits at a time. - while (n > 0) { - if (bytePtr >= bytes.length) { - throw "Error! Overflowed the bit stream! n=" + n + ", bytePtr=" + bytePtr + ", bytes.length=" + - bytes.length + ", bitPtr=" + bitPtr; - return -1; - } - - var numBitsLeftInThisByte = (8 - bitPtr); - if (n >= numBitsLeftInThisByte) { - var mask = (BITMASK[numBitsLeftInThisByte] << bitPtr); - result |= (((bytes[bytePtr] & mask) >> bitPtr) << bitsIn); - - bytePtr++; - bitPtr = 0; - bitsIn += numBitsLeftInThisByte; - n -= numBitsLeftInThisByte; - } - else { - var mask = (BITMASK[n] << bitPtr); - result |= (((bytes[bytePtr] & mask) >> bitPtr) << bitsIn); - - bitPtr += n; - bitsIn += n; - n = 0; - } - } - - if (movePointers) { - this.bitPtr = bitPtr; - this.bytePtr = bytePtr; - } - - return result; -}; - - -/** - * byte0 byte1 byte2 byte3 - * 7......0 | 7......0 | 7......0 | 7......0 - * - * The bit pointer starts at bit7 of byte0 and moves right until it reaches - * bit0 of byte0, then goes to bit7 of byte1, etc. - * @param {number} n The number of bits to peek. - * @param {boolean=} movePointers Whether to move the pointer, defaults false. - * @return {number} The peeked bits, as an unsigned number. - */ -bitjs.io.BitStream.prototype.peekBits_rtl = function(n, movePointers) { - if (n <= 0 || typeof n != typeof 1) { - return 0; - } - - var movePointers = movePointers || false, - bytePtr = this.bytePtr, - bitPtr = this.bitPtr, - result = 0, - bytes = this.bytes; - - // keep going until we have no more bits left to peek at - // TODO: Consider putting all bits from bytes we will need into a variable and then - // shifting/masking it to just extract the bits we want. - // This could be considerably faster when reading more than 3 or 4 bits at a time. - while (n > 0) { - - if (bytePtr >= bytes.length) { - throw "Error! Overflowed the bit stream! n=" + n + ", bytePtr=" + bytePtr + ", bytes.length=" + - bytes.length + ", bitPtr=" + bitPtr; - return -1; - } - - var numBitsLeftInThisByte = (8 - bitPtr); - if (n >= numBitsLeftInThisByte) { - result <<= numBitsLeftInThisByte; - result |= (BITMASK[numBitsLeftInThisByte] & bytes[bytePtr]); - bytePtr++; - bitPtr = 0; - n -= numBitsLeftInThisByte; - } - else { - result <<= n; - result |= ((bytes[bytePtr] & (BITMASK[n] << (8 - n - bitPtr))) >> (8 - n - bitPtr)); - - bitPtr += n; - n = 0; - } - } - - if (movePointers) { - this.bitPtr = bitPtr; - this.bytePtr = bytePtr; - } - - return result; -}; - - -/** - * Some voodoo magic. - */ -bitjs.io.BitStream.prototype.getBits = function() { - return (((((this.bytes[this.bytePtr] & 0xff) << 16) + - ((this.bytes[this.bytePtr+1] & 0xff) << 8) + - ((this.bytes[this.bytePtr+2] & 0xff))) >>> (8-this.bitPtr)) & 0xffff); -}; - - -/** - * Reads n bits out of the stream, consuming them (moving the bit pointer). - * @param {number} n The number of bits to read. - * @return {number} The read bits, as an unsigned number. - */ -bitjs.io.BitStream.prototype.readBits = function(n) { - return this.peekBits(n, true); -}; - - -/** - * This returns n bytes as a sub-array, advancing the pointer if movePointers - * is true. Only use this for uncompressed blocks as this throws away remaining - * bits in the current byte. - * @param {number} n The number of bytes to peek. - * @param {boolean=} movePointers Whether to move the pointer, defaults false. - * @return {Uint8Array} The subarray. - */ -bitjs.io.BitStream.prototype.peekBytes = function(n, movePointers) { - if (n <= 0 || typeof n != typeof 1) { - return 0; - } - - // from http://tools.ietf.org/html/rfc1951#page-11 - // "Any bits of input up to the next byte boundary are ignored." - while (this.bitPtr != 0) { - this.readBits(1); - } - - var movePointers = movePointers || false; - var bytePtr = this.bytePtr, - bitPtr = this.bitPtr; - - var result = this.bytes.subarray(bytePtr, bytePtr + n); - - if (movePointers) { - this.bytePtr += n; - } - - return result; -}; - - -/** - * @param {number} n The number of bytes to read. - * @return {Uint8Array} The subarray. - */ -bitjs.io.BitStream.prototype.readBytes = function(n) { - return this.peekBytes(n, true); -}; - - -/** - * This object allows you to peek and consume bytes as numbers and strings - * out of an ArrayBuffer. In this buffer, everything must be byte-aligned. - * - * @param {ArrayBuffer} ab The ArrayBuffer object. - * @param {number=} opt_offset The offset into the ArrayBuffer - * @param {number=} opt_length The length of this BitStream - * @constructor - */ -bitjs.io.ByteStream = function(ab, opt_offset, opt_length) { - var offset = opt_offset || 0; - var length = opt_length || ab.byteLength; - this.bytes = new Uint8Array(ab, offset, length); - this.ptr = 0; -}; - - -/** - * Peeks at the next n bytes as an unsigned number but does not advance the - * pointer - * TODO: This apparently cannot read more than 4 bytes as a number? - * @param {number} n The number of bytes to peek at. - * @return {number} The n bytes interpreted as an unsigned number. - */ -bitjs.io.ByteStream.prototype.peekNumber = function(n) { - // TODO: return error if n would go past the end of the stream? - if (n <= 0 || typeof n != typeof 1) - return -1; - - var result = 0; - // read from last byte to first byte and roll them in - var curByte = this.ptr + n - 1; - while (curByte >= this.ptr) { - result <<= 8; - result |= this.bytes[curByte]; - --curByte; - } - return result; -}; - - -/** - * Returns the next n bytes as an unsigned number (or -1 on error) - * and advances the stream pointer n bytes. - * @param {number} n The number of bytes to read. - * @return {number} The n bytes interpreted as an unsigned number. - */ -bitjs.io.ByteStream.prototype.readNumber = function(n) { - var num = this.peekNumber( n ); - this.ptr += n; - return num; -}; - - -/** - * Returns the next n bytes as a signed number but does not advance the - * pointer. - * @param {number} n The number of bytes to read. - * @return {number} The bytes interpreted as a signed number. - */ -bitjs.io.ByteStream.prototype.peekSignedNumber = function(n) { - var num = this.peekNumber(n); - var HALF = Math.pow(2, (n * 8) - 1); - var FULL = HALF * 2; - - if (num >= HALF) num -= FULL; - - return num; -}; - - -/** - * Returns the next n bytes as a signed number and advances the stream pointer. - * @param {number} n The number of bytes to read. - * @return {number} The bytes interpreted as a signed number. - */ -bitjs.io.ByteStream.prototype.readSignedNumber = function(n) { - var num = this.peekSignedNumber(n); - this.ptr += n; - return num; -}; - - -/** - * This returns n bytes as a sub-array, advancing the pointer if movePointers - * is true. - * @param {number} n The number of bytes to read. - * @param {boolean} movePointers Whether to move the pointers. - * @return {Uint8Array} The subarray. - */ -bitjs.io.ByteStream.prototype.peekBytes = function(n, movePointers) { - if (n <= 0 || typeof n != typeof 1) { - return null; - } - - var result = this.bytes.subarray(this.ptr, this.ptr + n); - - if (movePointers) { - this.ptr += n; - } - - return result; -}; - - -/** - * Reads the next n bytes as a sub-array. - * @param {number} n The number of bytes to read. - * @return {Uint8Array} The subarray. - */ -bitjs.io.ByteStream.prototype.readBytes = function(n) { - return this.peekBytes(n, true); -}; - - -/** - * Peeks at the next n bytes as a string but does not advance the pointer. - * @param {number} n The number of bytes to peek at. - * @return {string} The next n bytes as a string. - */ -bitjs.io.ByteStream.prototype.peekString = function(n) { - if (n <= 0 || typeof n != typeof 1) { - return ""; - } - - var result = ""; - for (var p = this.ptr, end = this.ptr + n; p < end; ++p) { - result += String.fromCharCode(this.bytes[p]); - } - return result; -}; - - -/** - * Returns the next n bytes as an ASCII string and advances the stream pointer - * n bytes. - * @param {number} n The number of bytes to read. - * @return {string} The next n bytes as a string. - */ -bitjs.io.ByteStream.prototype.readString = function(n) { - var strToReturn = this.peekString(n); - this.ptr += n; - return strToReturn; -}; - - -/** - * A write-only Byte buffer which uses a Uint8 Typed Array as a backing store. - * @param {number} numBytes The number of bytes to allocate. - * @constructor - */ -bitjs.io.ByteBuffer = function(numBytes) { - if (typeof numBytes != typeof 1 || numBytes <= 0) { - throw "Error! ByteBuffer initialized with '" + numBytes + "'"; - } - this.data = new Uint8Array(numBytes); - this.ptr = 0; -}; - - -/** - * @param {number} b The byte to insert. - */ -bitjs.io.ByteBuffer.prototype.insertByte = function(b) { - // TODO: throw if byte is invalid? - this.data[this.ptr++] = b; -}; - - -/** - * @param {Array.|Uint8Array|Int8Array} bytes The bytes to insert. - */ -bitjs.io.ByteBuffer.prototype.insertBytes = function(bytes) { - // TODO: throw if bytes is invalid? - this.data.set(bytes, this.ptr); - this.ptr += bytes.length; -}; - - -/** - * Writes an unsigned number into the next n bytes. If the number is too large - * to fit into n bytes or is negative, an error is thrown. - * @param {number} num The unsigned number to write. - * @param {number} numBytes The number of bytes to write the number into. - */ -bitjs.io.ByteBuffer.prototype.writeNumber = function(num, numBytes) { - if (numBytes < 1) { - throw 'Trying to write into too few bytes: ' + numBytes; - } - if (num < 0) { - throw 'Trying to write a negative number (' + num + - ') as an unsigned number to an ArrayBuffer'; - } - if (num > (Math.pow(2, numBytes * 8) - 1)) { - throw 'Trying to write ' + num + ' into only ' + numBytes + ' bytes'; - } - - // Roll 8-bits at a time into an array of bytes. - var bytes = []; - while (numBytes-- > 0) { - var eightBits = num & 255; - bytes.push(eightBits); - num >>= 8; - } - - this.insertBytes(bytes); -}; - - -/** - * Writes a signed number into the next n bytes. If the number is too large - * to fit into n bytes, an error is thrown. - * @param {number} num The signed number to write. - * @param {number} numBytes The number of bytes to write the number into. - */ -bitjs.io.ByteBuffer.prototype.writeSignedNumber = function(num, numBytes) { - if (numBytes < 1) { - throw 'Trying to write into too few bytes: ' + numBytes; - } - - var HALF = Math.pow(2, (numBytes * 8) - 1); - if (num >= HALF || num < -HALF) { - throw 'Trying to write ' + num + ' into only ' + numBytes + ' bytes'; - } - - // Roll 8-bits at a time into an array of bytes. - var bytes = []; - while (numBytes-- > 0) { - var eightBits = num & 255; - bytes.push(eightBits); - num >>= 8; - } - - this.insertBytes(bytes); -}; - - -/** - * @param {string} str The ASCII string to write. - */ -bitjs.io.ByteBuffer.prototype.writeASCIIString = function(str) { - for (var i = 0; i < str.length; ++i) { - var curByte = str.charCodeAt(i); - if (curByte < 0 || curByte > 255) { - throw 'Trying to write a non-ASCII string!'; - } - this.insertByte(curByte); - } -}; - -})(); diff --git a/static/cbr.js/bitjs/unrar.js b/static/cbr.js/bitjs/unrar.js deleted file mode 100644 index 15273cd8..00000000 --- a/static/cbr.js/bitjs/unrar.js +++ /dev/null @@ -1,913 +0,0 @@ -/** - * unrar.js - * - * Copyright(c) 2011 Google Inc. - * Copyright(c) 2011 antimatter15 - * - * Reference Documentation: - * - * http://kthoom.googlecode.com/hg/docs/unrar.html - */ - -// This file expects to be invoked as a Worker (see onmessage below). -importScripts('io.js'); -importScripts('archive.js'); - -// Progress variables. -var currentFilename = ""; -var currentFileNumber = 0; -var currentBytesUnarchivedInFile = 0; -var currentBytesUnarchived = 0; -var totalUncompressedBytesInArchive = 0; -var totalFilesInArchive = 0; - -// Helper functions. -var info = function(str) { - postMessage(new bitjs.archive.UnarchiveInfoEvent(str)); -}; -var err = function(str) { - postMessage(new bitjs.archive.UnarchiveErrorEvent(str)); -}; -var postProgress = function() { - postMessage(new bitjs.archive.UnarchiveProgressEvent( - currentFilename, - currentFileNumber, - currentBytesUnarchivedInFile, - currentBytesUnarchived, - totalUncompressedBytesInArchive, - totalFilesInArchive)); -}; - -// shows a byte value as its hex representation -var nibble = "0123456789ABCDEF"; -var byteValueToHexString = function(num) { - return nibble[num>>4] + nibble[num&0xF]; -}; -var twoByteValueToHexString = function(num) { - return nibble[(num>>12)&0xF] + nibble[(num>>8)&0xF] + nibble[(num>>4)&0xF] + nibble[num&0xF]; -}; - - -// Volume Types -var MARK_HEAD = 0x72, - MAIN_HEAD = 0x73, - FILE_HEAD = 0x74, - COMM_HEAD = 0x75, - AV_HEAD = 0x76, - SUB_HEAD = 0x77, - PROTECT_HEAD = 0x78, - SIGN_HEAD = 0x79, - NEWSUB_HEAD = 0x7a, - ENDARC_HEAD = 0x7b; - -// bstream is a bit stream -var RarVolumeHeader = function(bstream) { - - var headPos = bstream.bytePtr; - // byte 1,2 - info("Rar Volume Header @"+bstream.bytePtr); - - this.crc = bstream.readBits(16); - info(" crc=" + this.crc); - - // byte 3 - this.headType = bstream.readBits(8); - info(" headType=" + this.headType); - - // Get flags - // bytes 4,5 - this.flags = {}; - this.flags.value = bstream.peekBits(16); - - info(" flags=" + twoByteValueToHexString(this.flags.value)); - switch (this.headType) { - case MAIN_HEAD: - this.flags.MHD_VOLUME = !!bstream.readBits(1); - this.flags.MHD_COMMENT = !!bstream.readBits(1); - this.flags.MHD_LOCK = !!bstream.readBits(1); - this.flags.MHD_SOLID = !!bstream.readBits(1); - this.flags.MHD_PACK_COMMENT = !!bstream.readBits(1); - this.flags.MHD_NEWNUMBERING = this.flags.MHD_PACK_COMMENT; - this.flags.MHD_AV = !!bstream.readBits(1); - this.flags.MHD_PROTECT = !!bstream.readBits(1); - this.flags.MHD_PASSWORD = !!bstream.readBits(1); - this.flags.MHD_FIRSTVOLUME = !!bstream.readBits(1); - this.flags.MHD_ENCRYPTVER = !!bstream.readBits(1); - bstream.readBits(6); // unused - break; - case FILE_HEAD: - this.flags.LHD_SPLIT_BEFORE = !!bstream.readBits(1); // 0x0001 - this.flags.LHD_SPLIT_AFTER = !!bstream.readBits(1); // 0x0002 - this.flags.LHD_PASSWORD = !!bstream.readBits(1); // 0x0004 - this.flags.LHD_COMMENT = !!bstream.readBits(1); // 0x0008 - this.flags.LHD_SOLID = !!bstream.readBits(1); // 0x0010 - bstream.readBits(3); // unused - this.flags.LHD_LARGE = !!bstream.readBits(1); // 0x0100 - this.flags.LHD_UNICODE = !!bstream.readBits(1); // 0x0200 - this.flags.LHD_SALT = !!bstream.readBits(1); // 0x0400 - this.flags.LHD_VERSION = !!bstream.readBits(1); // 0x0800 - this.flags.LHD_EXTTIME = !!bstream.readBits(1); // 0x1000 - this.flags.LHD_EXTFLAGS = !!bstream.readBits(1); // 0x2000 - bstream.readBits(2); // unused - info(" LHD_SPLIT_BEFORE = " + this.flags.LHD_SPLIT_BEFORE); - break; - default: - bstream.readBits(16); - } - - // byte 6,7 - this.headSize = bstream.readBits(16); - info(" headSize=" + this.headSize); - switch (this.headType) { - case MAIN_HEAD: - this.highPosAv = bstream.readBits(16); - this.posAv = bstream.readBits(32); - if (this.flags.MHD_ENCRYPTVER) { - this.encryptVer = bstream.readBits(8); - } - info("Found MAIN_HEAD with highPosAv=" + this.highPosAv + ", posAv=" + this.posAv); - break; - case FILE_HEAD: - this.packSize = bstream.readBits(32); - this.unpackedSize = bstream.readBits(32); - this.hostOS = bstream.readBits(8); - this.fileCRC = bstream.readBits(32); - this.fileTime = bstream.readBits(32); - this.unpVer = bstream.readBits(8); - this.method = bstream.readBits(8); - this.nameSize = bstream.readBits(16); - this.fileAttr = bstream.readBits(32); - - if (this.flags.LHD_LARGE) { - info("Warning: Reading in LHD_LARGE 64-bit size values"); - this.HighPackSize = bstream.readBits(32); - this.HighUnpSize = bstream.readBits(32); - } else { - this.HighPackSize = 0; - this.HighUnpSize = 0; - if (this.unpackedSize == 0xffffffff) { - this.HighUnpSize = 0x7fffffff - this.unpackedSize = 0xffffffff; - } - } - this.fullPackSize = 0; - this.fullUnpackSize = 0; - this.fullPackSize |= this.HighPackSize; - this.fullPackSize <<= 32; - this.fullPackSize |= this.packSize; - - // read in filename - - this.filename = bstream.readBytes(this.nameSize); - for (var _i = 0, _s = ''; _i < this.filename.length; _i++) { - _s += String.fromCharCode(this.filename[_i]); - } - - this.filename = _s; - - if (this.flags.LHD_SALT) { - info("Warning: Reading in 64-bit salt value"); - this.salt = bstream.readBits(64); // 8 bytes - } - - if (this.flags.LHD_EXTTIME) { - // 16-bit flags - var extTimeFlags = bstream.readBits(16); - - // this is adapted straight out of arcread.cpp, Archive::ReadHeader() - for (var I = 0; I < 4; ++I) { - var rmode = extTimeFlags >> ((3-I)*4); - if ((rmode & 8)==0) - continue; - if (I!=0) - bstream.readBits(16); - var count = (rmode&3); - for (var J = 0; J < count; ++J) - bstream.readBits(8); - } - } - - if (this.flags.LHD_COMMENT) { - info("Found a LHD_COMMENT"); - } - - - while(headPos + this.headSize > bstream.bytePtr) bstream.readBits(1); - - 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: - 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; - } -}; - -var BLOCK_LZ = 0, - BLOCK_PPM = 1; - -var rLDecode = [0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224], - rLBits = [0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5], - rDBitLengthCounts = [4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12], - rSDDecode = [0,4,8,16,32,64,128,192], - rSDBits = [2,2,3, 4, 5, 6, 6, 6]; - -var rDDecode = [0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, - 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, - 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152, 65536, 98304, - 131072, 196608, 262144, 327680, 393216, 458752, 524288, 589824, - 655360, 720896, 786432, 851968, 917504, 983040]; - -var rDBits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, - 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, - 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16]; - -var rLOW_DIST_REP_COUNT = 16; - -var rNC = 299, - rDC = 60, - rLDC = 17, - rRC = 28, - rBC = 20, - rHUFF_TABLE_SIZE = (rNC+rDC+rRC+rLDC); - -var UnpBlockType = BLOCK_LZ; -var UnpOldTable = new Array(rHUFF_TABLE_SIZE); - -var BD = { //bitdecode - DecodeLen: new Array(16), - DecodePos: new Array(16), - DecodeNum: new Array(rBC) -}; -var LD = { //litdecode - DecodeLen: new Array(16), - DecodePos: new Array(16), - DecodeNum: new Array(rNC) -}; -var DD = { //distdecode - DecodeLen: new Array(16), - DecodePos: new Array(16), - DecodeNum: new Array(rDC) -}; -var LDD = { //low dist decode - DecodeLen: new Array(16), - DecodePos: new Array(16), - DecodeNum: new Array(rLDC) -}; -var RD = { //rep decode - DecodeLen: new Array(16), - DecodePos: new Array(16), - DecodeNum: new Array(rRC) -}; - -var rBuffer; - -// read in Huffman tables for RAR -function RarReadTables(bstream) { - var BitLength = new Array(rBC), - Table = new Array(rHUFF_TABLE_SIZE); - - // before we start anything we need to get byte-aligned - bstream.readBits( (8 - bstream.bitPtr) & 0x7 ); - - if (bstream.readBits(1)) { - info("Error! PPM not implemented yet"); - return; - } - - if (!bstream.readBits(1)) { //discard old table - for (var i = UnpOldTable.length; i--;) UnpOldTable[i] = 0; - } - - // read in bit lengths - for (var I = 0; I < rBC; ++I) { - - var Length = bstream.readBits(4); - if (Length == 15) { - var ZeroCount = bstream.readBits(4); - if (ZeroCount == 0) { - BitLength[I] = 15; - } - else { - ZeroCount += 2; - while (ZeroCount-- > 0 && I < rBC) - BitLength[I++] = 0; - --I; - } - } - else { - BitLength[I] = Length; - } - } - - // now all 20 bit lengths are obtained, we construct the Huffman Table: - - RarMakeDecodeTables(BitLength, 0, BD, rBC); - - var TableSize = rHUFF_TABLE_SIZE; - //console.log(DecodeLen, DecodePos, DecodeNum); - for (var i = 0; i < TableSize;) { - var num = RarDecodeNumber(bstream, BD); - if (num < 16) { - Table[i] = (num + UnpOldTable[i]) & 0xf; - i++; - } else if(num < 18) { - var N = (num == 16) ? (bstream.readBits(3) + 3) : (bstream.readBits(7) + 11); - - while (N-- > 0 && i < TableSize) { - Table[i] = Table[i - 1]; - i++; - } - } else { - var N = (num == 18) ? (bstream.readBits(3) + 3) : (bstream.readBits(7) + 11); - - while (N-- > 0 && i < TableSize) { - Table[i++] = 0; - } - } - } - - RarMakeDecodeTables(Table, 0, LD, rNC); - RarMakeDecodeTables(Table, rNC, DD, rDC); - RarMakeDecodeTables(Table, rNC + rDC, LDD, rLDC); - RarMakeDecodeTables(Table, rNC + rDC + rLDC, RD, rRC); - - for (var i = UnpOldTable.length; i--;) { - UnpOldTable[i] = Table[i]; - } - return true; -} - - -function RarDecodeNumber(bstream, dec) { - var DecodeLen = dec.DecodeLen, DecodePos = dec.DecodePos, DecodeNum = dec.DecodeNum; - var bitField = bstream.getBits() & 0xfffe; - //some sort of rolled out binary search - var bits = ((bitField < DecodeLen[8])? - ((bitField < DecodeLen[4])? - ((bitField < DecodeLen[2])? - ((bitField < DecodeLen[1])?1:2) - :((bitField < DecodeLen[3])?3:4)) - :(bitField < DecodeLen[6])? - ((bitField < DecodeLen[5])?5:6) - :((bitField < DecodeLen[7])?7:8)) - :((bitField < DecodeLen[12])? - ((bitField < DecodeLen[10])? - ((bitField < DecodeLen[9])?9:10) - :((bitField < DecodeLen[11])?11:12)) - :(bitField < DecodeLen[14])? - ((bitField < DecodeLen[13])?13:14) - :15)); - bstream.readBits(bits); - var N = DecodePos[bits] + ((bitField - DecodeLen[bits -1]) >>> (16 - bits)); - - return DecodeNum[N]; -} - - - -function RarMakeDecodeTables(BitLength, offset, dec, size) { - var DecodeLen = dec.DecodeLen, DecodePos = dec.DecodePos, DecodeNum = dec.DecodeNum; - var LenCount = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - TmpPos = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - N = 0, M = 0; - for (var i = DecodeNum.length; i--;) DecodeNum[i] = 0; - for (var i = 0; i < size; i++) { - LenCount[BitLength[i + offset] & 0xF]++; - } - LenCount[0] = 0; - TmpPos[0] = 0; - DecodePos[0] = 0; - DecodeLen[0] = 0; - - for (var I = 1; I < 16; ++I) { - N = 2 * (N+LenCount[I]); - M = (N << (15-I)); - if (M > 0xFFFF) - M = 0xFFFF; - DecodeLen[I] = M; - DecodePos[I] = DecodePos[I-1] + LenCount[I-1]; - TmpPos[I] = DecodePos[I]; - } - for (I = 0; I < size; ++I) - if (BitLength[I + offset] != 0) - DecodeNum[ TmpPos[ BitLength[offset + I] & 0xF ]++] = I; - -} - -// TODO: implement -function Unpack15(bstream, Solid) { - info("ERROR! RAR 1.5 compression not supported"); -} - -function Unpack20(bstream, Solid) { - var destUnpSize = rBuffer.data.length; - var oldDistPtr = 0; - - RarReadTables20(bstream); - while (destUnpSize > rBuffer.ptr) { - var num = RarDecodeNumber(bstream, LD); - if (num < 256) { - rBuffer.insertByte(num); - continue; - } - if (num > 269) { - var Length = rLDecode[num -= 270] + 3; - if ((Bits = rLBits[num]) > 0) { - Length += bstream.readBits(Bits); - } - var DistNumber = RarDecodeNumber(bstream, DD); - var Distance = rDDecode[DistNumber] + 1; - if ((Bits = rDBits[DistNumber]) > 0) { - Distance += bstream.readBits(Bits); - } - if (Distance >= 0x2000) { - Length++; - if(Distance >= 0x40000) Length++; - } - lastLength = Length; - lastDist = rOldDist[oldDistPtr++ & 3] = Distance; - RarCopyString(Length, Distance); - continue; - } - if (num == 269) { - RarReadTables20(bstream); - - RarUpdateProgress() - - continue; - } - if (num == 256) { - lastDist = rOldDist[oldDistPtr++ & 3] = lastDist; - RarCopyString(lastLength, lastDist); - continue; - } - if (num < 261) { - var Distance = rOldDist[(oldDistPtr - (num - 256)) & 3]; - var LengthNumber = RarDecodeNumber(bstream, RD); - var Length = rLDecode[LengthNumber] +2; - if ((Bits = rLBits[LengthNumber]) > 0) { - Length += bstream.readBits(Bits); - } - if (Distance >= 0x101) { - Length++; - if (Distance >= 0x2000) { - Length++ - if (Distance >= 0x40000) Length++; - } - } - lastLength = Length; - lastDist = rOldDist[oldDistPtr++ & 3] = Distance; - RarCopyString(Length, Distance); - continue; - } - if (num < 270) { - var Distance = rSDDecode[num -= 261] + 1; - if ((Bits = rSDBits[num]) > 0) { - Distance += bstream.readBits(Bits); - } - lastLength = 2; - lastDist = rOldDist[oldDistPtr++ & 3] = Distance; - RarCopyString(2, Distance); - continue; - } - - } - RarUpdateProgress() -} - -function RarUpdateProgress() { - var change = rBuffer.ptr - currentBytesUnarchivedInFile; - currentBytesUnarchivedInFile = rBuffer.ptr; - currentBytesUnarchived += change; - postProgress(); -} - - -var rNC20 = 298, - rDC20 = 48, - rRC20 = 28, - rBC20 = 19, - rMC20 = 257; - -var UnpOldTable20 = new Array(rMC20 * 4); - -function RarReadTables20(bstream) { - var BitLength = new Array(rBC20); - var Table = new Array(rMC20 * 4); - var TableSize, N, I; - var AudioBlock = bstream.readBits(1); - if (!bstream.readBits(1)) - for (var i = UnpOldTable20.length; i--;) UnpOldTable20[i] = 0; - TableSize = rNC20 + rDC20 + rRC20; - for (var I = 0; I < rBC20; I++) - BitLength[I] = bstream.readBits(4); - RarMakeDecodeTables(BitLength, 0, BD, rBC20); - I = 0; - while (I < TableSize) { - var num = RarDecodeNumber(bstream, BD); - if (num < 16) { - Table[I] = num + UnpOldTable20[I] & 0xf; - I++; - } else if(num == 16) { - N = bstream.readBits(2) + 3; - while (N-- > 0 && I < TableSize) { - Table[I] = Table[I - 1]; - I++; - } - } else { - if (num == 17) { - N = bstream.readBits(3) + 3; - } else { - N = bstream.readBits(7) + 11; - } - while (N-- > 0 && I < TableSize) { - Table[I++] = 0; - } - } - } - RarMakeDecodeTables(Table, 0, LD, rNC20); - RarMakeDecodeTables(Table, rNC20, DD, rDC20); - RarMakeDecodeTables(Table, rNC20 + rDC20, RD, rRC20); - for (var i = UnpOldTable20.length; i--;) UnpOldTable20[i] = Table[i]; -} - -var lowDistRepCount = 0, prevLowDist = 0; - -var rOldDist = [0,0,0,0]; -var lastDist; -var lastLength; - - -function Unpack29(bstream, Solid) { - // lazy initialize rDDecode and rDBits - - var DDecode = new Array(rDC); - var DBits = new Array(rDC); - - var Dist=0,BitLength=0,Slot=0; - - for (var I = 0; I < rDBitLengthCounts.length; I++,BitLength++) { - for (var J = 0; J < rDBitLengthCounts[I]; J++,Slot++,Dist+=(1<= 271) { - var Length = rLDecode[num -= 271] + 3; - if ((Bits = rLBits[num]) > 0) { - Length += bstream.readBits(Bits); - } - var DistNumber = RarDecodeNumber(bstream, DD); - var Distance = DDecode[DistNumber]+1; - if ((Bits = DBits[DistNumber]) > 0) { - if (DistNumber > 9) { - if (Bits > 4) { - Distance += ((bstream.getBits() >>> (20 - Bits)) << 4); - bstream.readBits(Bits - 4); - //todo: check this - } - if (lowDistRepCount > 0) { - lowDistRepCount--; - Distance += prevLowDist; - } else { - var LowDist = RarDecodeNumber(bstream, LDD); - if (LowDist == 16) { - lowDistRepCount = rLOW_DIST_REP_COUNT - 1; - Distance += prevLowDist; - } else { - Distance += LowDist; - prevLowDist = LowDist; - } - } - } else { - Distance += bstream.readBits(Bits); - } - } - if (Distance >= 0x2000) { - Length++; - if (Distance >= 0x40000) { - Length++; - } - } - RarInsertOldDist(Distance); - RarInsertLastMatch(Length, Distance); - RarCopyString(Length, Distance); - continue; - } - if (num == 256) { - if (!RarReadEndOfBlock(bstream)) break; - - continue; - } - if (num == 257) { - //console.log("READVMCODE"); - if (!RarReadVMCode(bstream)) break; - continue; - } - if (num == 258) { - if (lastLength != 0) { - RarCopyString(lastLength, lastDist); - } - continue; - } - if (num < 263) { - var DistNum = num - 259; - var Distance = rOldDist[DistNum]; - - for (var I = DistNum; I > 0; I--) { - rOldDist[I] = rOldDist[I-1]; - } - rOldDist[0] = Distance; - - var LengthNumber = RarDecodeNumber(bstream, RD); - var Length = rLDecode[LengthNumber] + 2; - if ((Bits = rLBits[LengthNumber]) > 0) { - Length += bstream.readBits(Bits); - } - RarInsertLastMatch(Length, Distance); - RarCopyString(Length, Distance); - continue; - } - if (num < 272) { - var Distance = rSDDecode[num -= 263] + 1; - if ((Bits = rSDBits[num]) > 0) { - Distance += bstream.readBits(Bits); - } - RarInsertOldDist(Distance); - RarInsertLastMatch(2, Distance); - RarCopyString(2, Distance); - continue; - } - - } - RarUpdateProgress() -} - -function RarReadEndOfBlock(bstream) { - - RarUpdateProgress() - - - var NewTable = false, NewFile = false; - if (bstream.readBits(1)) { - NewTable = true; - } else { - NewFile = true; - NewTable = !!bstream.readBits(1); - } - //tablesRead = !NewTable; - return !(NewFile || NewTable && !RarReadTables(bstream)); -} - - -function RarReadVMCode(bstream) { - var FirstByte = bstream.readBits(8); - var Length = (FirstByte & 7) + 1; - if (Length == 7) { - Length = bstream.readBits(8) + 7; - } else if(Length == 8) { - Length = bstream.readBits(16); - } - var vmCode = []; - for(var I = 0; I < Length; I++) { - //do something here with cheking readbuf - vmCode.push(bstream.readBits(8)); - } - return RarAddVMCode(FirstByte, vmCode, Length); -} - -function RarAddVMCode(firstByte, vmCode, length) { - //console.log(vmCode); - if (vmCode.length > 0) { - info("Error! RarVM not supported yet!"); - } - return true; -} - -function RarInsertLastMatch(length, distance) { - lastDist = distance; - lastLength = length; -} - -function RarInsertOldDist(distance) { - rOldDist.splice(3,1); - rOldDist.splice(0,0,distance); -} - -//this is the real function, the other one is for debugging -function RarCopyString(length, distance) { - var destPtr = rBuffer.ptr - distance; - if(destPtr < 0){ - var l = rOldBuffers.length; - while(destPtr < 0){ - destPtr = rOldBuffers[--l].data.length + destPtr; - } - //TODO: lets hope that it never needs to read beyond file boundaries - while(length--) rBuffer.insertByte(rOldBuffers[l].data[destPtr++]); - - } - if (length > distance) { - while(length--) rBuffer.insertByte(rBuffer.data[destPtr++]); - } else { - rBuffer.insertBytes(rBuffer.data.subarray(destPtr, destPtr + length)); - } - -} - -var rOldBuffers = [] -// v must be a valid RarVolume -function unpack(v) { - - // TODO: implement what happens when unpVer is < 15 - var Ver = v.header.unpVer <= 15 ? 15 : v.header.unpVer, - Solid = v.header.LHD_SOLID, - bstream = new bitjs.io.BitStream(v.fileData.buffer, true /* rtl */, v.fileData.byteOffset, v.fileData.byteLength ); - - rBuffer = new bitjs.io.ByteBuffer(v.header.unpackedSize); - - info("Unpacking "+v.filename+" RAR v"+Ver); - - switch(Ver) { - case 15: // rar 1.5 compression - Unpack15(bstream, Solid); - break; - case 20: // rar 2.x compression - case 26: // files larger than 2GB - Unpack20(bstream, Solid); - break; - case 29: // rar 3.x compression - case 36: // alternative hash - Unpack29(bstream, Solid); - break; - } // switch(method) - - rOldBuffers.push(rBuffer); - //TODO: clear these old buffers when there's over 4MB of history - return rBuffer.data; -} - -// bstream is a bit stream -var RarLocalFile = function(bstream) { - - this.header = new RarVolumeHeader(bstream); - this.filename = this.header.filename; - - if (this.header.headType != FILE_HEAD && this.header.headType != ENDARC_HEAD) { - this.isValid = false; - info("Error! RAR Volume did not include a FILE_HEAD header "); - } - else { - // read in the compressed data - this.fileData = null; - if (this.header.packSize > 0) { - this.fileData = bstream.readBytes(this.header.packSize); - this.isValid = true; - } - } -}; - -RarLocalFile.prototype.unrar = function() { - - if (!this.header.flags.LHD_SPLIT_BEFORE) { - // unstore file - if (this.header.method == 0x30) { - info("Unstore "+this.filename); - this.isValid = true; - - currentBytesUnarchivedInFile += this.fileData.length; - currentBytesUnarchived += this.fileData.length; - - // Create a new buffer and copy it over. - var len = this.header.packSize; - var newBuffer = new bitjs.io.ByteBuffer(len); - newBuffer.insertBytes(this.fileData); - this.fileData = newBuffer.data; - } else { - this.isValid = true; - this.fileData = unpack(this); - } - } -} - -var unrar = function(arrayBuffer) { - currentFilename = ""; - currentFileNumber = 0; - currentBytesUnarchivedInFile = 0; - currentBytesUnarchived = 0; - totalUncompressedBytesInArchive = 0; - totalFilesInArchive = 0; - - postMessage(new bitjs.archive.UnarchiveStartEvent()); - var bstream = new bitjs.io.BitStream(arrayBuffer, false /* rtl */); - - var header = new RarVolumeHeader(bstream); - if (header.crc == 0x6152 && - header.headType == 0x72 && - header.flags.value == 0x1A21 && - header.headSize == 7) { - info("Found RAR signature"); - - var mhead = new RarVolumeHeader(bstream); - if (mhead.headType != MAIN_HEAD) { - info("Error! RAR did not include a MAIN_HEAD header"); - } - else { - var localFiles = [], - localFile = null; - do { - try { - localFile = new RarLocalFile(bstream); - info("RAR localFile isValid=" + localFile.isValid + ", volume packSize=" + localFile.header.packSize); - if (localFile && localFile.isValid && localFile.header.packSize > 0) { - totalUncompressedBytesInArchive += localFile.header.unpackedSize; - localFiles.push(localFile); - } else if (localFile.header.packSize == 0 && localFile.header.unpackedSize == 0) { - localFile.isValid = true; - } - } catch(err) { - break; - } - //info("bstream" + bstream.bytePtr+"/"+bstream.bytes.length); - } while( localFile.isValid ); - totalFilesInArchive = localFiles.length; - - // now we have all information but things are unpacked - // TODO: unpack - localFiles = localFiles.sort(function(a,b) { - var aname = a.filename; - var bname = b.filename; - return aname > bname ? 1 : -1; - - // extract the number at the end of both filenames - /* - var aindex = aname.length, bindex = bname.length; - - // Find the last number character from the back of the filename. - while (aname[aindex-1] < '0' || aname[aindex-1] > '9') --aindex; - while (bname[bindex-1] < '0' || bname[bindex-1] > '9') --bindex; - - // Find the first number character from the back of the filename - while (aname[aindex-1] >= '0' && aname[aindex-1] <= '9') --aindex; - while (bname[bindex-1] >= '0' && bname[bindex-1] <= '9') --bindex; - - // parse them into numbers and return comparison - var anum = parseInt(aname.substr(aindex), 10), - bnum = parseInt(bname.substr(bindex), 10); - return bnum - anum;*/ - }); - - info(localFiles.map(function(a){return a.filename}).join(', ')); - for (var i = 0; i < localFiles.length; ++i) { - var localfile = localFiles[i]; - - // update progress - currentFilename = localfile.header.filename; - currentBytesUnarchivedInFile = 0; - - // actually do the unzipping - localfile.unrar(); - - if (localfile.isValid) { - postMessage(new bitjs.archive.UnarchiveExtractEvent(localfile)); - postProgress(); - } - } - - postProgress(); - } - } - else { - err("Invalid RAR file"); - } - postMessage(new bitjs.archive.UnarchiveFinishEvent()); -}; - -// event.data.file has the ArrayBuffer. -onmessage = function(event) { - var ab = event.data.file; - unrar(ab, true); -}; diff --git a/static/cbr.js/bitjs/untar.js b/static/cbr.js/bitjs/untar.js deleted file mode 100644 index 4eafbb32..00000000 --- a/static/cbr.js/bitjs/untar.js +++ /dev/null @@ -1,188 +0,0 @@ -/** - * untar.js - * - * Copyright(c) 2011 Google Inc. - * - * Reference Documentation: - * - * TAR format: http://www.gnu.org/software/automake/manual/tar/Standard.html - */ - -// This file expects to be invoked as a Worker (see onmessage below). -importScripts('io.js'); -importScripts('archive.js'); - -// Progress variables. -var currentFilename = ""; -var currentFileNumber = 0; -var currentBytesUnarchivedInFile = 0; -var currentBytesUnarchived = 0; -var totalUncompressedBytesInArchive = 0; -var totalFilesInArchive = 0; - -// Helper functions. -var info = function(str) { - postMessage(new bitjs.archive.UnarchiveInfoEvent(str)); -}; -var err = function(str) { - postMessage(new bitjs.archive.UnarchiveErrorEvent(str)); -}; -var postProgress = function() { - postMessage(new bitjs.archive.UnarchiveProgressEvent( - currentFilename, - currentFileNumber, - currentBytesUnarchivedInFile, - currentBytesUnarchived, - totalUncompressedBytesInArchive, - totalFilesInArchive)); -}; - -// Removes all characters from the first zero-byte in the string onwards. -var readCleanString = function(bstr, numBytes) { - var str = bstr.readString(numBytes); - var zIndex = str.indexOf(String.fromCharCode(0)); - return zIndex != -1 ? str.substr(0, zIndex) : str; -}; - -// takes a ByteStream and parses out the local file information -var TarLocalFile = function(bstream) { - this.isValid = false; - - // Read in the header block - this.name = readCleanString(bstream, 100); - this.mode = readCleanString(bstream, 8); - this.uid = readCleanString(bstream, 8); - this.gid = readCleanString(bstream, 8); - this.size = parseInt(readCleanString(bstream, 12), 8); - this.mtime = readCleanString(bstream, 12); - this.chksum = readCleanString(bstream, 8); - this.typeflag = readCleanString(bstream, 1); - this.linkname = readCleanString(bstream, 100); - this.maybeMagic = readCleanString(bstream, 6); - - if (this.maybeMagic == "ustar") { - this.version = readCleanString(bstream, 2); - this.uname = readCleanString(bstream, 32); - this.gname = readCleanString(bstream, 32); - this.devmajor = readCleanString(bstream, 8); - this.devminor = readCleanString(bstream, 8); - this.prefix = readCleanString(bstream, 155); - - if (this.prefix.length) { - this.name = this.prefix + this.name; - } - bstream.readBytes(12); // 512 - 500 - } else { - bstream.readBytes(255); // 512 - 257 - } - - // Done header, now rest of blocks are the file contents. - this.filename = this.name; - this.fileData = null; - - info("Untarring file '" + this.filename + "'"); - info(" size = " + this.size); - info(" typeflag = " + this.typeflag); - - // A regular file. - if (this.typeflag == 0) { - 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) { - this.isValid = true; - } - - bstream.readBytes(this.size); - - // Round up to 512-byte blocks. - var remaining = 512 - this.size % 512; - if (remaining > 0 && remaining < 512) { - bstream.readBytes(remaining); - } - } else if (this.typeflag == 5) { - info(" This is a directory.") - } -}; - -// Takes an ArrayBuffer of a tar file in -// returns null on error -// returns an array of DecompressedFile objects on success -var untar = function(arrayBuffer) { - currentFilename = ""; - currentFileNumber = 0; - currentBytesUnarchivedInFile = 0; - currentBytesUnarchived = 0; - totalUncompressedBytesInArchive = 0; - totalFilesInArchive = 0; - - postMessage(new bitjs.archive.UnarchiveStartEvent()); - var bstream = new bitjs.io.ByteStream(arrayBuffer); - var localFiles = []; - - // While we don't encounter an empty block, keep making TarLocalFiles. - while (bstream.peekNumber(4) != 0) { - var oneLocalFile = new TarLocalFile(bstream); - if (oneLocalFile && oneLocalFile.isValid) { - localFiles.push(oneLocalFile); - totalUncompressedBytesInArchive += oneLocalFile.size; - } - } - totalFilesInArchive = localFiles.length; - - // got all local files, now sort them - localFiles.sort(function(a,b) { - var aname = a.filename; - var bname = b.filename; - return aname > bname ? 1 : -1; - - // extract the number at the end of both filenames - /* - var aname = a.filename; - var bname = b.filename; - var aindex = aname.length, bindex = bname.length; - - // Find the last number character from the back of the filename. - while (aname[aindex-1] < '0' || aname[aindex-1] > '9') --aindex; - while (bname[bindex-1] < '0' || bname[bindex-1] > '9') --bindex; - - // Find the first number character from the back of the filename - while (aname[aindex-1] >= '0' && aname[aindex-1] <= '9') --aindex; - while (bname[bindex-1] >= '0' && bname[bindex-1] <= '9') --bindex; - - // parse them into numbers and return comparison - var anum = parseInt(aname.substr(aindex), 10), - bnum = parseInt(bname.substr(bindex), 10); - return anum - bnum; - */ - }); - - // report # files and total length - if (localFiles.length > 0) { - postProgress(); - } - - // now do the shipping of each file - for (var i = 0; i < localFiles.length; ++i) { - var localfile = localFiles[i]; - info("Sending file '" + localfile.filename + "' up"); - - // update progress - currentFilename = localfile.filename; - currentFileNumber = i; - currentBytesUnarchivedInFile = localfile.size; - currentBytesUnarchived += localfile.size; - postMessage(new bitjs.archive.UnarchiveExtractEvent(localfile)); - postProgress(); - } - - postProgress(); - - postMessage(new bitjs.archive.UnarchiveFinishEvent()); -}; - -// event.data.file has the ArrayBuffer. -onmessage = function(event) { - var ab = event.data.file; - untar(ab); -}; diff --git a/static/cbr.js/bitjs/unzip.js b/static/cbr.js/bitjs/unzip.js deleted file mode 100644 index 1a656212..00000000 --- a/static/cbr.js/bitjs/unzip.js +++ /dev/null @@ -1,637 +0,0 @@ -/** - * unzip.js - * - * Copyright(c) 2011 Google Inc. - * Copyright(c) 2011 antimatter15 - * - * Reference Documentation: - * - * ZIP format: http://www.pkware.com/documents/casestudies/APPNOTE.TXT - * DEFLATE format: http://tools.ietf.org/html/rfc1951 - */ - -// This file expects to be invoked as a Worker (see onmessage below). -importScripts('io.js'); -importScripts('archive.js'); - -// Progress variables. -var currentFilename = ""; -var currentFileNumber = 0; -var currentBytesUnarchivedInFile = 0; -var currentBytesUnarchived = 0; -var totalUncompressedBytesInArchive = 0; -var totalFilesInArchive = 0; - -// Helper functions. -var info = function(str) { - postMessage(new bitjs.archive.UnarchiveInfoEvent(str)); -}; -var err = function(str) { - postMessage(new bitjs.archive.UnarchiveErrorEvent(str)); -}; -var postProgress = function() { - postMessage(new bitjs.archive.UnarchiveProgressEvent( - currentFilename, - currentFileNumber, - currentBytesUnarchivedInFile, - currentBytesUnarchived, - totalUncompressedBytesInArchive, - totalFilesInArchive)); -}; - -var zLocalFileHeaderSignature = 0x04034b50; -var zArchiveExtraDataSignature = 0x08064b50; -var zCentralFileHeaderSignature = 0x02014b50; -var zDigitalSignatureSignature = 0x05054b50; -var zEndOfCentralDirSignature = 0x06064b50; -var zEndOfCentralDirLocatorSignature = 0x07064b50; - -// takes a ByteStream and parses out the local file information -var ZipLocalFile = function(bstream) { - if (typeof bstream != typeof {} || !bstream.readNumber || typeof bstream.readNumber != typeof function(){}) { - return null; - } - - bstream.readNumber(4); // swallow signature - this.version = bstream.readNumber(2); - this.generalPurpose = bstream.readNumber(2); - this.compressionMethod = bstream.readNumber(2); - this.lastModFileTime = bstream.readNumber(2); - this.lastModFileDate = bstream.readNumber(2); - this.crc32 = bstream.readNumber(4); - this.compressedSize = bstream.readNumber(4); - this.uncompressedSize = bstream.readNumber(4); - this.fileNameLength = bstream.readNumber(2); - this.extraFieldLength = bstream.readNumber(2); - - this.filename = null; - if (this.fileNameLength > 0) { - this.filename = bstream.readString(this.fileNameLength); - } - - info("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); - info(" extra field=" + this.extraField); - } - - // read in the compressed data - this.fileData = null; - if (this.compressedSize > 0) { - this.fileData = new Uint8Array(bstream.bytes.buffer, bstream.ptr, this.compressedSize); - bstream.ptr += this.compressedSize; - } - - // TODO: deal with data descriptor if present (we currently assume no data descriptor!) - // "This descriptor exists only if bit 3 of the general purpose bit flag is set" - // But how do you figure out how big the file data is if you don't know the compressedSize - // from the header?!? - if ((this.generalPurpose & bitjs.BIT[3]) != 0) { - this.crc32 = bstream.readNumber(4); - this.compressedSize = bstream.readNumber(4); - this.uncompressedSize = bstream.readNumber(4); - } -}; - -// determine what kind of compressed data we have and decompress -ZipLocalFile.prototype.unzip = function() { - - // Zip Version 1.0, no compression (store only) - if (this.compressionMethod == 0 ) { - info("ZIP v"+this.version+", store only: " + this.filename + " (" + this.compressedSize + " bytes)"); - currentBytesUnarchivedInFile = this.compressedSize; - currentBytesUnarchived += this.compressedSize; - } - // version == 20, compression method == 8 (DEFLATE) - else if (this.compressionMethod == 8) { - info("ZIP v2.0, DEFLATE: " + this.filename + " (" + this.compressedSize + " bytes)"); - this.fileData = inflate(this.fileData, this.uncompressedSize); - } - else { - err("UNSUPPORTED VERSION/FORMAT: ZIP v" + this.version + ", compression method=" + this.compressionMethod + ": " + this.filename + " (" + this.compressedSize + " bytes)"); - this.fileData = null; - } -}; - - -// Takes an ArrayBuffer of a zip file in -// returns null on error -// returns an array of DecompressedFile objects on success -var unzip = function(arrayBuffer) { - postMessage(new bitjs.archive.UnarchiveStartEvent()); - - currentFilename = ""; - currentFileNumber = 0; - currentBytesUnarchivedInFile = 0; - currentBytesUnarchived = 0; - totalUncompressedBytesInArchive = 0; - totalFilesInArchive = 0; - currentBytesUnarchived = 0; - - var bstream = new bitjs.io.ByteStream(arrayBuffer); - // detect local file header signature or return null - if (bstream.peekNumber(4) == zLocalFileHeaderSignature) { - var localFiles = []; - // loop until we don't see any more local files - while (bstream.peekNumber(4) == zLocalFileHeaderSignature) { - var oneLocalFile = new ZipLocalFile(bstream); - // this should strip out directories/folders - if (oneLocalFile && oneLocalFile.uncompressedSize > 0 && oneLocalFile.fileData) { - localFiles.push(oneLocalFile); - totalUncompressedBytesInArchive += oneLocalFile.uncompressedSize; - } - } - totalFilesInArchive = localFiles.length; - - // got all local files, now sort them - localFiles.sort(function(a,b) { - var aname = a.filename; - var bname = b.filename; - return aname > bname ? 1 : -1; - - // extract the number at the end of both filenames - /* - var aname = a.filename; - var bname = b.filename; - var aindex = aname.length, bindex = bname.length; - - // Find the last number character from the back of the filename. - while (aname[aindex-1] < '0' || aname[aindex-1] > '9') --aindex; - while (bname[bindex-1] < '0' || bname[bindex-1] > '9') --bindex; - - // Find the first number character from the back of the filename - while (aname[aindex-1] >= '0' && aname[aindex-1] <= '9') --aindex; - while (bname[bindex-1] >= '0' && bname[bindex-1] <= '9') --bindex; - - // parse them into numbers and return comparison - var anum = parseInt(aname.substr(aindex), 10), - bnum = parseInt(bname.substr(bindex), 10); - return anum - bnum; - */ - }); - - // archive extra data record - if (bstream.peekNumber(4) == zArchiveExtraDataSignature) { - info(" Found an Archive Extra Data Signature"); - - // skipping this record for now - bstream.readNumber(4); - var archiveExtraFieldLength = bstream.readNumber(4); - bstream.readString(archiveExtraFieldLength); - } - - // central directory structure - // TODO: handle the rest of the structures (Zip64 stuff) - if (bstream.peekNumber(4) == zCentralFileHeaderSignature) { - info(" Found a Central File Header"); - - // read all file headers - while (bstream.peekNumber(4) == zCentralFileHeaderSignature) { - bstream.readNumber(4); // signature - bstream.readNumber(2); // version made by - bstream.readNumber(2); // version needed to extract - bstream.readNumber(2); // general purpose bit flag - bstream.readNumber(2); // compression method - bstream.readNumber(2); // last mod file time - bstream.readNumber(2); // last mod file date - bstream.readNumber(4); // crc32 - bstream.readNumber(4); // compressed size - bstream.readNumber(4); // uncompressed size - var fileNameLength = bstream.readNumber(2); // file name length - var extraFieldLength = bstream.readNumber(2); // extra field length - var fileCommentLength = bstream.readNumber(2); // file comment length - bstream.readNumber(2); // disk number start - bstream.readNumber(2); // internal file attributes - bstream.readNumber(4); // external file attributes - bstream.readNumber(4); // relative offset of local header - - bstream.readString(fileNameLength); // file name - bstream.readString(extraFieldLength); // extra field - bstream.readString(fileCommentLength); // file comment - } - } - - // digital signature - if (bstream.peekNumber(4) == zDigitalSignatureSignature) { - info(" Found a Digital Signature"); - - bstream.readNumber(4); - var sizeOfSignature = bstream.readNumber(2); - bstream.readString(sizeOfSignature); // digital signature data - } - - // report # files and total length - if (localFiles.length > 0) { - postProgress(); - } - - // now do the unzipping of each file - for (var i = 0; i < localFiles.length; ++i) { - var localfile = localFiles[i]; - - // update progress - currentFilename = localfile.filename; - currentFileNumber = i; - currentBytesUnarchivedInFile = 0; - - // actually do the unzipping - localfile.unzip(); - - if (localfile.fileData != null) { - postMessage(new bitjs.archive.UnarchiveExtractEvent(localfile)); - postProgress(); - } - } - postProgress(); - postMessage(new bitjs.archive.UnarchiveFinishEvent()); - } -} - -// returns a table of Huffman codes -// each entry's index is its code and its value is a JavaScript object -// containing {length: 6, symbol: X} -function getHuffmanCodes(bitLengths) { - // ensure bitLengths is an array containing at least one element - if (typeof bitLengths != typeof [] || bitLengths.length < 1) { - err("Error! getHuffmanCodes() called with an invalid array"); - return null; - } - - // Reference: http://tools.ietf.org/html/rfc1951#page-8 - var numLengths = bitLengths.length, - bl_count = [], - MAX_BITS = 1; - - // Step 1: count up how many codes of each length we have - for (var i = 0; i < numLengths; ++i) { - var length = bitLengths[i]; - // test to ensure each bit length is a positive, non-zero number - if (typeof length != typeof 1 || length < 0) { - err("bitLengths contained an invalid number in getHuffmanCodes(): " + length + " of type " + (typeof length)); - return null; - } - // increment the appropriate bitlength count - if (bl_count[length] == undefined) bl_count[length] = 0; - // a length of zero means this symbol is not participating in the huffman coding - if (length > 0) bl_count[length]++; - - if (length > MAX_BITS) MAX_BITS = length; - } - - // Step 2: Find the numerical value of the smallest code for each code length - var next_code = [], - code = 0; - for (var bits = 1; bits <= MAX_BITS; ++bits) { - var length = bits-1; - // ensure undefined lengths are zero - if (bl_count[length] == undefined) bl_count[length] = 0; - code = (code + bl_count[bits-1]) << 1; - next_code[bits] = code; - } - - // Step 3: Assign numerical values to all codes - var table = {}, tableLength = 0; - for (var n = 0; n < numLengths; ++n) { - var len = bitLengths[n]; - if (len != 0) { - table[next_code[len]] = { length: len, symbol: n }; //, bitstring: binaryValueToString(next_code[len],len) }; - tableLength++; - next_code[len]++; - } - } - table.maxLength = tableLength; - - return table; -} - -/* - The Huffman codes for the two alphabets are fixed, and are not - represented explicitly in the data. The Huffman code lengths - for the literal/length alphabet are: - - Lit Value Bits Codes - --------- ---- ----- - 0 - 143 8 00110000 through - 10111111 - 144 - 255 9 110010000 through - 111111111 - 256 - 279 7 0000000 through - 0010111 - 280 - 287 8 11000000 through - 11000111 -*/ -// fixed Huffman codes go from 7-9 bits, so we need an array whose index can hold up to 9 bits -var fixedHCtoLiteral = null; -var fixedHCtoDistance = null; -function getFixedLiteralTable() { - // create once - if (!fixedHCtoLiteral) { - var bitlengths = new Array(288); - for (var i = 0; i <= 143; ++i) bitlengths[i] = 8; - for (i = 144; i <= 255; ++i) bitlengths[i] = 9; - for (i = 256; i <= 279; ++i) bitlengths[i] = 7; - for (i = 280; i <= 287; ++i) bitlengths[i] = 8; - - // get huffman code table - fixedHCtoLiteral = getHuffmanCodes(bitlengths); - } - return fixedHCtoLiteral; -} -function getFixedDistanceTable() { - // create once - if (!fixedHCtoDistance) { - var bitlengths = new Array(32); - for (var i = 0; i < 32; ++i) { bitlengths[i] = 5; } - - // get huffman code table - fixedHCtoDistance = getHuffmanCodes(bitlengths); - } - return fixedHCtoDistance; -} - -// extract one bit at a time until we find a matching Huffman Code -// then return that symbol -function decodeSymbol(bstream, hcTable) { - var code = 0, len = 0; - var match = false; - - // loop until we match - for (;;) { - // read in next bit - var bit = bstream.readBits(1); - code = (code<<1) | bit; - ++len; - - // check against Huffman Code table and break if found - if (hcTable.hasOwnProperty(code) && hcTable[code].length == len) { - - break; - } - if (len > hcTable.maxLength) { - err("Bit stream out of sync, didn't find a Huffman Code, length was " + len + - " and table only max code length of " + hcTable.maxLength); - break; - } - } - return hcTable[code].symbol; -} - - -var CodeLengthCodeOrder = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; - /* - Extra Extra Extra - Code Bits Length(s) Code Bits Lengths Code Bits Length(s) - ---- ---- ------ ---- ---- ------- ---- ---- ------- - 257 0 3 267 1 15,16 277 4 67-82 - 258 0 4 268 1 17,18 278 4 83-98 - 259 0 5 269 2 19-22 279 4 99-114 - 260 0 6 270 2 23-26 280 4 115-130 - 261 0 7 271 2 27-30 281 5 131-162 - 262 0 8 272 2 31-34 282 5 163-194 - 263 0 9 273 3 35-42 283 5 195-226 - 264 0 10 274 3 43-50 284 5 227-257 - 265 1 11,12 275 3 51-58 285 0 258 - 266 1 13,14 276 3 59-66 - - */ -var LengthLookupTable = [ - [0,3], [0,4], [0,5], [0,6], - [0,7], [0,8], [0,9], [0,10], - [1,11], [1,13], [1,15], [1,17], - [2,19], [2,23], [2,27], [2,31], - [3,35], [3,43], [3,51], [3,59], - [4,67], [4,83], [4,99], [4,115], - [5,131], [5,163], [5,195], [5,227], - [0,258] -]; - /* - Extra Extra Extra - Code Bits Dist Code Bits Dist Code Bits Distance - ---- ---- ---- ---- ---- ------ ---- ---- -------- - 0 0 1 10 4 33-48 20 9 1025-1536 - 1 0 2 11 4 49-64 21 9 1537-2048 - 2 0 3 12 5 65-96 22 10 2049-3072 - 3 0 4 13 5 97-128 23 10 3073-4096 - 4 1 5,6 14 6 129-192 24 11 4097-6144 - 5 1 7,8 15 6 193-256 25 11 6145-8192 - 6 2 9-12 16 7 257-384 26 12 8193-12288 - 7 2 13-16 17 7 385-512 27 12 12289-16384 - 8 3 17-24 18 8 513-768 28 13 16385-24576 - 9 3 25-32 19 8 769-1024 29 13 24577-32768 - */ -var DistLookupTable = [ - [0,1], [0,2], [0,3], [0,4], - [1,5], [1,7], - [2,9], [2,13], - [3,17], [3,25], - [4,33], [4,49], - [5,65], [5,97], - [6,129], [6,193], - [7,257], [7,385], - [8,513], [8,769], - [9,1025], [9,1537], - [10,2049], [10,3073], - [11,4097], [11,6145], - [12,8193], [12,12289], - [13,16385], [13,24577] -]; - -function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) { - /* - loop (until end of block code recognized) - decode literal/length value from input stream - if value < 256 - copy value (literal byte) to output stream - otherwise - if value = end of block (256) - break from loop - otherwise (value = 257..285) - decode distance from input stream - - move backwards distance bytes in the output - stream, and copy length bytes from this - position to the output stream. - */ - var numSymbols = 0, blockSize = 0; - for (;;) { - var symbol = decodeSymbol(bstream, hcLiteralTable); - ++numSymbols; - if (symbol < 256) { - // copy literal byte to output - buffer.insertByte(symbol); - blockSize++; - } - else { - // end of block reached - if (symbol == 256) { - break; - } - else { - var lengthLookup = LengthLookupTable[symbol-257], - length = lengthLookup[1] + bstream.readBits(lengthLookup[0]), - distLookup = DistLookupTable[decodeSymbol(bstream, hcDistanceTable)], - distance = distLookup[1] + bstream.readBits(distLookup[0]); - - // now apply length and distance appropriately and copy to output - - // TODO: check that backward distance < data.length? - - // http://tools.ietf.org/html/rfc1951#page-11 - // "Note also that the referenced string may overlap the current - // position; for example, if the last 2 bytes decoded have values - // X and Y, a string reference with - // adds X,Y,X,Y,X to the output stream." - // - // loop for each character - var ch = buffer.ptr - distance; - blockSize += length; - if(length > distance) { - var data = buffer.data; - while (length--) { - buffer.insertByte(data[ch++]); - } - } else { - buffer.insertBytes(buffer.data.subarray(ch, ch + length)) - } - - } // length-distance pair - } // length-distance pair or end-of-block - } // loop until we reach end of block - return blockSize; -} - -// {Uint8Array} compressedData A Uint8Array of the compressed file data. -// compression method 8 -// deflate: http://tools.ietf.org/html/rfc1951 -function inflate(compressedData, numDecompressedBytes) { - // Bit stream representing the compressed data. - var bstream = new bitjs.io.BitStream(compressedData.buffer, - false /* rtl */, - compressedData.byteOffset, - compressedData.byteLength); - var buffer = new bitjs.io.ByteBuffer(numDecompressedBytes); - var numBlocks = 0, blockSize = 0; - - // block format: http://tools.ietf.org/html/rfc1951#page-9 - do { - var bFinal = bstream.readBits(1), - bType = bstream.readBits(2); - blockSize = 0; - ++numBlocks; - // no compression - if (bType == 0) { - // skip remaining bits in this byte - while (bstream.bitPtr != 0) bstream.readBits(1); - var len = bstream.readBits(16), - nlen = bstream.readBits(16); - // TODO: check if nlen is the ones-complement of len? - - if(len > 0) buffer.insertBytes(bstream.readBytes(len)); - blockSize = len; - } - // fixed Huffman codes - else if(bType == 1) { - blockSize = inflateBlockData(bstream, getFixedLiteralTable(), getFixedDistanceTable(), buffer); - } - // dynamic Huffman codes - else if(bType == 2) { - var numLiteralLengthCodes = bstream.readBits(5) + 257; - var numDistanceCodes = bstream.readBits(5) + 1, - numCodeLengthCodes = bstream.readBits(4) + 4; - - // populate the array of code length codes (first de-compaction) - var codeLengthsCodeLengths = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; - for (var i = 0; i < numCodeLengthCodes; ++i) { - codeLengthsCodeLengths[ CodeLengthCodeOrder[i] ] = bstream.readBits(3); - } - - // get the Huffman Codes for the code lengths - var codeLengthsCodes = getHuffmanCodes(codeLengthsCodeLengths); - - // now follow this mapping - /* - 0 - 15: Represent code lengths of 0 - 15 - 16: Copy the previous code length 3 - 6 times. - The next 2 bits indicate repeat length - (0 = 3, ... , 3 = 6) - Example: Codes 8, 16 (+2 bits 11), - 16 (+2 bits 10) will expand to - 12 code lengths of 8 (1 + 6 + 5) - 17: Repeat a code length of 0 for 3 - 10 times. - (3 bits of length) - 18: Repeat a code length of 0 for 11 - 138 times - (7 bits of length) - */ - // to generate the true code lengths of the Huffman Codes for the literal - // and distance tables together - var literalCodeLengths = []; - var prevCodeLength = 0; - while (literalCodeLengths.length < numLiteralLengthCodes + numDistanceCodes) { - var symbol = decodeSymbol(bstream, codeLengthsCodes); - if (symbol <= 15) { - literalCodeLengths.push(symbol); - prevCodeLength = symbol; - } - else if (symbol == 16) { - var repeat = bstream.readBits(2) + 3; - while (repeat--) { - literalCodeLengths.push(prevCodeLength); - } - } - else if (symbol == 17) { - var repeat = bstream.readBits(3) + 3; - while (repeat--) { - literalCodeLengths.push(0); - } - } - else if (symbol == 18) { - var repeat = bstream.readBits(7) + 11; - while (repeat--) { - literalCodeLengths.push(0); - } - } - } - - // now split the distance code lengths out of the literal code array - var distanceCodeLengths = literalCodeLengths.splice(numLiteralLengthCodes, numDistanceCodes); - - // now generate the true Huffman Code tables using these code lengths - var hcLiteralTable = getHuffmanCodes(literalCodeLengths), - hcDistanceTable = getHuffmanCodes(distanceCodeLengths); - blockSize = inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer); - } - // error - else { - err("Error! Encountered deflate block of type 3"); - return null; - } - - // update progress - currentBytesUnarchivedInFile += blockSize; - currentBytesUnarchived += blockSize; - postProgress(); - - } while (bFinal != 1); - // we are done reading blocks if the bFinal bit was set for this block - - // return the buffer data bytes - return buffer.data; -} - -// event.data.file has the ArrayBuffer. -onmessage = function(event) { - unzip(event.data.file, true); -}; diff --git a/static/cbr.js/cbr.js b/static/cbr.js/cbr.js deleted file mode 100644 index c675fbce..00000000 --- a/static/cbr.js/cbr.js +++ /dev/null @@ -1,462 +0,0 @@ -this.cbrjs = {}; - -cbrjs.open = function(url) { - cbrjs.url = url - cbrjs.loadSettings() - Ox.load('UI', function() { - var $body = Ox.$('body') - .css({ - backgroundColor: 'rgb(255, 255, 255)', - overflowX: 'hidden' - }); - window.app = cbrjs.CBRViewer(Ox.extend({ - url: url, - }, cbrjs.settings) - ).bindEvent({ - page: cbrjs.updateSettings, - fitMode: cbrjs.updateSettings, - }).appendTo($body); - Ox.$window.on({ - resize: app.resize - }); - - }); - -}; - -cbrjs.loadSettings = function() { - var settings = {}; - try { - settings = JSON.parse(localStorage['cbrjs.' + cbrjs.url]); - } catch(e) { - settings.page = 1; - settings.fitMode = 'B'; - } - cbrjs.settings = settings; -} - -cbrjs.updateSettings = function(data) { - Ox.forEach(data, function(value, key) { - cbrjs.settings[key] = value; - }); - localStorage['cbrjs.' + cbrjs.url] = JSON.stringify(cbrjs.settings); -} - -cbrjs.CBRViewer = function(options, self) { - self = self || {}; - var that = Ox.Element({}, self) - .defaults({ - url: '', - page: 1 - }) - .options(options || {}) - .update({ - page: setPage, - fitMode: function() { - resize() - that.triggerEvent('fitMode', {fitMode: self.options.fitMode}); - }, - url: loadBook - }), - moveTimeout, - canvas; - - self.pages = []; - self.rotateTimes = 0; - self.hflip = false; - self.vflip = false; - - self.mimeTypes = { - 'png': 'image/png', - 'jpg': 'image/jpeg', - 'jpeg': 'image/jpeg', - 'gif': 'image/gif', - }; - - self.$frame = Ox.Element() - .on({ - mousemove: showMenu, - mousedown: function() { - self.$frame.gainFocus(); - }, - }) - .bindEvent({ - key_down: function() { - self.$frame.scrollTop(self.$frame.scrollTop() + self.$frame.height()) - }, - key_left: function() { - that.options({ - page: Math.max(self.options.page - 1, 1) - }) - }, - key_pagedown: function() { - that.options({ - page: self.pages.length - }) - }, - key_pageup: function() { - that.options({ - page: 1 - }) - }, - key_right: function() { - that.options({ - page: Math.min(self.options.page + 1, self.pages.length) - }) - }, - key_up: function() { - self.$frame.scrollTop(self.$frame.scrollTop() - self.$frame.height()) - }, - key_n: function() { - that.options({ - fitMode: 'N' - }) - }, - key_h: function() { - that.options({ - fitMode: 'H' - }) - }, - key_b: function() { - that.options({ - fitMode: 'B' - }) - }, - key_w: function() { - that.options({ - fitMode: 'W' - }) - }, - key_l: function() { - self.rotateTimes--; - if (self.rotateTimes < 0) { - self.rotateTimes = 3; - } - setPage(); - }, - key_f: function() { - if (!self.hflip && !self.vflip) { - self.hflip = true; - } else if(self.hflip == true) { - self.vflip = true; - self.hflip = false; - } else if(self.vflip == true) { - self.vflip = false; - } - setPage(); - }, - key_space: function() { - var old = self.$frame.scrollTop() - self.$frame.scrollTop(self.$frame.scrollTop() + self.$frame.height()) - if (self.$frame.scrollTop() == old) { - that.options({ - page: Math.min(self.options.page + 1, self.pages.length) - }) - } - }, - singleclick: function(data) { - if (data.clientX < (that.width() / 2)) { - that.options({ - page: Math.max(self.options.page - 1, 1) - }); - } else { - that.options({ - page: Math.min(self.options.page + 1, self.pages.length) - }); - } - } - }) - .css({ - margin: 0, - overflow: 'auto', - padding: 0, - textAlign: 'center' - }); - self.$canvas = Ox.Element('') - .appendTo(self.$frame); - canvas = self.$canvas[0]; - self.$scrollbar = Ox.Range({ - arrows: true, - max: self.options.page, - min: 1, - orientation: 'horizontal', - step: 1, - value: self.options.page, - thumbValue: true, - thumbSize: 64 - }).bindEvent({ - change: function(data) { - Ox.print('change', data); - that.options({ - page: data.value - }) - } - }); - - self.$panel = Ox.SplitPanel({}) - .appendTo(that); - that.setElement( - self.$mainPanel = Ox.SplitPanel({ - elements: [ - { - element: self.$frame, - }, - { - element: self.$scrollbar, - size: 16 - } - ], - orientation: 'vertical' - }) - ); - - self.$loading = Ox.LoadingScreen({ - size: 16, - }) - .css({ - margin: 'auto', - position: 'absolute' - }) - .start() - .appendTo(that); - - self.$menu = Ox.Element().css({ - position: 'fixed', - right: (Ox.UI.SCROLLBAR_SIZE + 4) + 'px', - top: '4px', - opacity: 0 - }) - .addClass('menu') - .appendTo(that); - - self.$zoom = Ox.Button({ - style: 'symbol', - title: 'fill', - tooltip: Ox._('Zoom to fill'), - type: 'image' - }).css({ - width: '16px', - height: '16px', - }).on({ - mousedown: function(event) { - if (self.$zoom.options('title') == 'fill') { - self.$zoom.options({ - title: 'fit', - tooltip: Ox._('Zoom to fit') - }) - that.options({ - fitMode: 'W' - }) - } else { - self.$zoom.options({ - title: 'fill', - tooltip: Ox._('Zoom to fill') - }) - that.options({ - fitMode: 'B' - }) - } - event.stopPropagation() - event.preventDefault(); - } - }) - .appendTo(self.$menu); - - loadBook(); - - function createURLFromArray(array, mimeType) { - var blob = new Blob([array], {type: mimeType}); - blob = blob.slice(array.byteOffset, array.byteOffset + array.byteLength, mimeType); - return URL.createObjectURL(blob); - } - - function isImage(filename) { - var extension = filename.split('.').pop().toLowerCase(); - return !Ox.isUndefined(self.mimeTypes[extension]); - } - - function loadBook() { - var xhr = new XMLHttpRequest(); - xhr.open('GET', self.options.url, true); - xhr.responseType = "arraybuffer"; - xhr.onload = function() { - loadFromArrayBuffer(this.response, function(pages, progress, total) { - self.pages = pages; - self.$scrollbar.options({ - max: Math.max(pages.length, self.options.page), - size: that.width() - }) - if (pages.length == self.options.page) { - setPage(); - if (self.$loading) { - self.$loading.remove(); - delete self.$loading; - } - } - }); - }; - xhr.send(null); - } - - function loadFromArrayBuffer(buffer, progress) { - var extract, - start = (new Date).getTime(), - h = new Uint8Array(buffer, 0, 10), - pathToBitJS = $('script').map(function(i, script) { - return script.src; - }).filter(function(i, url) { - return url.indexOf('bitjs') > -1; - })[0].replace('archive.js', ''); - - var pages = [], filenames = [], total; - - if (h[0] == 0x52 && h[1] == 0x61 && h[2] == 0x72 && h[3] == 0x21) { // RAR - extract = new bitjs.archive.Unrarrer(buffer, pathToBitJS); - } else if (h[0] == 80 && h[1] == 75) { // ZIP - extract = new bitjs.archive.Unzipper(buffer, pathToBitJS); - } else { // try tar otherwise - extract = new bitjs.archive.Untarrer(buffer, pathToBitJS); - } - if (extract) { - extract.addEventListener( - bitjs.archive.UnarchiveEvent.Type.PROGRESS, - function(e) { - var percentage = e.currentBytesUnarchived / e.totalUncompressedBytesInArchive; - total = e.totalFilesInArchive - progress([], percentage, total); - } - ); - extract.addEventListener( - bitjs.archive.UnarchiveEvent.Type.INFO, - function(e) { - Ox.Log('', e.msg); - } - ); - extract.addEventListener( - bitjs.archive.UnarchiveEvent.Type.EXTRACT, - function(e) { - // convert DecompressedFile into a bunch of ImageFiles - if (e.unarchivedFile) { - var f = e.unarchivedFile; - // add any new pages based on the filename - if (!Ox.contains(filenames, f.filename) && isImage(f.filename)) { - filenames.push(f.filename); - pages.push(f); - } else { - total--; - } - progress(pages, pages.length/total, total); - } - } - ); - extract.addEventListener( - bitjs.archive.UnarchiveEvent.Type.FINISH, - function(e) { - total = pages.length; - progress(pages, 1, pages.length); - var diff = ((new Date).getTime() - start)/1000; - Ox.Log('', 'Unarchiving done in ' + diff + 's'); - } - ); - extract.start(); - } else { - Ox.Log('', 'bitjs.archive failed to open file'); - } - } - - function resize(clear) { - canvas.style.width = ''; - canvas.style.height = ''; - canvas.style.maxWidth = ''; - canvas.style.maxHeight = ''; - var maxheight = self.$frame.height() - 4; - if (clear || self.options.fitMode == 'N') { - - } else if (self.options.fitMode == 'B') { - canvas.style.maxWidth = '100%'; - canvas.style.maxHeight = maxheight + 'px'; - } else if (self.options.fitMode == 'H') { - canvas.style.height = maxheight + 'px'; - } else if (self.options.fitMode == 'W') { - canvas.style.width = '100%'; - } - self.$scrollbar.options({ - size: that.width() - }); - } - - function setImage(url) { - var ctx = canvas.getContext('2d'), - img = new Image(); - img.onerror = function(e) { - canvas.width = innerWidth - 100; - canvas.height = 300; - resize(true); - ctx.fillStyle = 'orange'; - ctx.font = '50px sans-serif'; - ctx.strokeStyle = 'black'; - ctx.fillText('Page #' + (currentImage+1) + ' (' + - imageFiles[currentImage].filename + ')', 100, 100) - ctx.fillStyle = 'red'; - ctx.fillText('Is corrupt or not an image', 100, 200); - }; - img.onload = function() { - var h = img.height, - w = img.width, - sw = w, - sh = h; - self.rotateTimes = (4 + self.rotateTimes) % 4; - ctx.save(); - if (self.rotateTimes % 2 == 1) { sh = w; sw = h;} - canvas.height = sh; - canvas.width = sw; - ctx.translate(sw/2, sh/2); - ctx.rotate(Math.PI/2 * self.rotateTimes); - ctx.translate(-w/2, -h/2); - if (self.vflip) { - ctx.scale(1, -1) - ctx.translate(0, -h); - } - if (self.hflip) { - ctx.scale(-1, 1) - ctx.translate(-w, 0); - } - canvas.style.display = 'none'; - scrollTo(0,0); - ctx.drawImage(img, 0, 0); - - resize(); - - canvas.style.display = ''; - document.body.style.overflowY = ''; - ctx.restore(); - }; - img.src = url; - } - - function setPage() { - var file = self.pages[self.options.page - 1], - filename = file.filename, - extension = file.filename.split('.').pop().toLowerCase(), - mimeType = self.mimeTypes[extension]; - setImage(createURLFromArray(file.fileData, mimeType)); - self.$scrollbar.options({value: self.options.page}); - that.triggerEvent('page', {page: self.options.page}); - } - function showMenu() { - if (moveTimeout) { - clearTimeout(moveTimeout); - } else { - self.$menu.animate({opacity: 1}, 250) - } - moveTimeout = setTimeout(function() { - self.$menu.animate({opacity: 0}, 250) - moveTimeout = null - }, 5000); - } - - that.resize = function() { - resize(); - }; - return that; -}; diff --git a/static/cbr.js/index.html b/static/cbr.js/index.html deleted file mode 100644 index a071f617..00000000 --- a/static/cbr.js/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - diff --git a/static/js/CBRViewer.js b/static/js/CBRViewer.js deleted file mode 100644 index dc0a007f..00000000 --- a/static/js/CBRViewer.js +++ /dev/null @@ -1,100 +0,0 @@ -'use strict'; - -/*@ -Ox.CBRViewer CBR Viewer - options Options - center <[n]|s|'auto'> Center ([x, y] or 'auto') - height Viewer height in px - maxZoom Maximum zoom (minimum zoom is 'fit') - cbrjsURL URL to cbr.js - url CBR URL - width Viewer width in px - zoom Zoom (number or 'fit' or 'fill') - self Shared private variable - ([options[, self]]) -> CBR Viewer - center Center changed - center <[n]|s> Center - zoom Zoom changed - zoom Zoom - page Page changed - page Page -@*/ -Ox.CBRViewer = function(options, self) { - - self = self || {}; - var that = Ox.Element({}, self) - .defaults({ - center: 'auto', - height: 384, - page: 1, - maxZoom: 16, - url: '', - width: 512, - zoom: 'fit' - }) - .options(options || {}) - .update({ - center: function() { - setCenterAndZoom(); - }, - page: updatePage, - // allow for setting height and width at the same time - height: updateSize, - url: function() { - self.$iframe.postMessage('cbr', {cbr: self.options.url}); - }, - width: updateSize, - zoom: function() { - setCenterAndZoom(); - } - }) - .addClass('OxCBRViewer') - .on({ - }) - .bindEvent({ - }); - - self.$iframe = Ox.Element('