diff --git a/cps/static/js/kthoom.js b/cps/static/js/kthoom.js
index ef4c0de0..55576d75 100644
--- a/cps/static/js/kthoom.js
+++ b/cps/static/js/kthoom.js
@@ -5,7 +5,7 @@
*
* Copyright(c) 2011 Google Inc.
* Copyright(c) 2011 antimatter15
- */
+*/
/* Reference Documentation:
@@ -17,27 +17,27 @@
*/
if (!window.console) {
- window.console = {};
- window.console.log = function(str) {};
- window.console.dir = function(str) {};
+ window.console = {};
+ window.console.log = function(str) {};
+ window.console.dir = function(str) {};
}
if (window.opera) {
- window.console.log = function(str) {opera.postError(str);};
- window.console.dir = function(str) {};
+ window.console.log = function(str) {opera.postError(str);};
+ window.console.dir = function(str) {};
}
// gets the element with the given id
function getElem(id) {
- if (document.documentElement.querySelector) {
- // querySelector lookup
- return document.body.querySelector('#' + id);
- }
- // getElementById lookup
- return document.getElementById(id);
+ if (document.documentElement.querySelector) {
+ // querySelector lookup
+ return document.body.querySelector('#' + id);
+ }
+ // getElementById lookup
+ return document.getElementById(id);
}
if (window.kthoom == undefined) {
- window.kthoom = {};
+ window.kthoom = {};
}
// key codes
@@ -65,32 +65,32 @@ var imageFilenames = [];
var totalImages = 0;
var lastCompletion = 0;
var library = {
- allBooks: [],
- currentBookNum: 0,
+ allBooks: [],
+ currentBookNum: 0,
};
var hflip = false, vflip = false, fitMode = kthoom.Key.B;
var canKeyNext = true, canKeyPrev = true;
kthoom.saveSettings = function() {
- localStorage.kthoom_settings = JSON.stringify({
- rotateTimes: kthoom.rotateTimes,
- hflip: hflip,
- vflip: vflip,
- fitMode: fitMode
- });
+ localStorage.kthoom_settings = JSON.stringify({
+ rotateTimes: kthoom.rotateTimes,
+ hflip: hflip,
+ vflip: vflip,
+ fitMode: fitMode
+ });
}
kthoom.loadSettings = function() {
- try {
- if (localStorage.kthoom_settings.length < 10) return;
- var s = JSON.parse(localStorage.kthoom_settings);
- kthoom.rotateTimes = s.rotateTimes;
- hflip = s.hflip;
- vflip = s.vflip;
- fitMode = s.fitMode;
- } catch(err) {
- }
+ try {
+ if (localStorage.kthoom_settings.length < 10) return;
+ var s = JSON.parse(localStorage.kthoom_settings);
+ kthoom.rotateTimes = s.rotateTimes;
+ hflip = s.hflip;
+ vflip = s.vflip;
+ fitMode = s.fitMode;
+ } catch(err) {
+ }
}
// Stores an image filename and its data: URI.
@@ -98,511 +98,505 @@ kthoom.loadSettings = function() {
// non-safe URL characters are encoded as %xx ?)
// This would save 25% on memory since base64-encoded strings are 4/3 the size of the binary
kthoom.ImageFile = function(file) {
- this.filename = file.filename;
- var fileExtension = file.filename.split('.').pop().toLowerCase();
- var mimeType = fileExtension == 'png' ? 'image/png' :
- (fileExtension == 'jpg' || fileExtension == 'jpeg') ? 'image/jpeg' :
- fileExtension == 'gif' ? 'image/gif' : undefined;
- this.dataURI = createURLFromArray(file.fileData, mimeType);
- this.data = file;
+ this.filename = file.filename;
+ var fileExtension = file.filename.split('.').pop().toLowerCase();
+ var mimeType = fileExtension == 'png' ? 'image/png' :
+ (fileExtension == 'jpg' || fileExtension == 'jpeg') ? 'image/jpeg' :
+ fileExtension == 'gif' ? 'image/gif' : undefined;
+ this.dataURI = createURLFromArray(file.fileData, mimeType);
+ this.data = file;
};
kthoom.initProgressMeter = function() {
- var svgns = 'http://www.w3.org/2000/svg';
- var pdiv = $('#progress')[0]; // document.getElementById('progress');
- var svg = document.createElementNS(svgns, 'svg');
- svg.style.width = '100%';
- svg.style.height = '100%';
-
- var defs = document.createElementNS(svgns, 'defs');
-
- var patt = document.createElementNS(svgns, 'pattern');
- patt.id = 'progress_pattern';
- patt.setAttribute('width', '30');
- patt.setAttribute('height', '20');
- patt.setAttribute('patternUnits', 'userSpaceOnUse');
-
- var rect = document.createElementNS(svgns, 'rect');
- rect.setAttribute('width', '100%');
- rect.setAttribute('height', '100%');
- rect.setAttribute('fill', '#cc2929');
-
- var poly = document.createElementNS(svgns, 'polygon');
- poly.setAttribute('fill', 'yellow');
- poly.setAttribute('points', '15,0 30,0 15,20 0,20');
-
- patt.appendChild(rect);
- patt.appendChild(poly);
- defs.appendChild(patt);
-
- svg.appendChild(defs);
-
- var g = document.createElementNS(svgns, 'g');
-
- var outline = document.createElementNS(svgns, 'rect');
- outline.setAttribute('y', '1');
- outline.setAttribute('width', '100%');
- outline.setAttribute('height', '15');
- outline.setAttribute('fill', '#777');
- outline.setAttribute('stroke', 'white');
- outline.setAttribute('rx', '5');
- outline.setAttribute('ry', '5');
- g.appendChild(outline);
-
- var title = document.createElementNS(svgns, 'text');
- title.id = 'progress_title';
- title.appendChild(document.createTextNode('0%'));
- title.setAttribute('y', '13');
- title.setAttribute('x', '99.5%');
- title.setAttribute('fill', 'white');
- title.setAttribute('font-size', '12px');
- title.setAttribute('text-anchor', 'end');
- g.appendChild(title);
-
- var meter = document.createElementNS(svgns, 'rect');
- meter.id = 'meter';
- meter.setAttribute('width', '0%');
- meter.setAttribute('height', '17');
- meter.setAttribute('fill', 'url(#progress_pattern)');
- meter.setAttribute('rx', '5');
- meter.setAttribute('ry', '5');
+ var svgns = 'http://www.w3.org/2000/svg';
+ var pdiv = $('#progress')[0]; // document.getElementById('progress');
+ var svg = document.createElementNS(svgns, 'svg');
+ svg.style.width = '100%';
+ svg.style.height = '100%';
+
+ var defs = document.createElementNS(svgns, 'defs');
+
+ var patt = document.createElementNS(svgns, 'pattern');
+ patt.id = 'progress_pattern';
+ patt.setAttribute('width', '30');
+ patt.setAttribute('height', '20');
+ patt.setAttribute('patternUnits', 'userSpaceOnUse');
+
+ var rect = document.createElementNS(svgns, 'rect');
+ rect.setAttribute('width', '100%');
+ rect.setAttribute('height', '100%');
+ rect.setAttribute('fill', '#cc2929');
+
+ var poly = document.createElementNS(svgns, 'polygon');
+ poly.setAttribute('fill', 'yellow');
+ poly.setAttribute('points', '15,0 30,0 15,20 0,20');
+
+ patt.appendChild(rect);
+ patt.appendChild(poly);
+ defs.appendChild(patt);
+
+ svg.appendChild(defs);
+
+ var g = document.createElementNS(svgns, 'g');
+
+ var outline = document.createElementNS(svgns, 'rect');
+ outline.setAttribute('y', '1');
+ outline.setAttribute('width', '100%');
+ outline.setAttribute('height', '15');
+ outline.setAttribute('fill', '#777');
+ outline.setAttribute('stroke', 'white');
+ outline.setAttribute('rx', '5');
+ outline.setAttribute('ry', '5');
+ g.appendChild(outline);
+
+ var title = document.createElementNS(svgns, 'text');
+ title.id = 'progress_title';
+ title.appendChild(document.createTextNode('0%'));
+ title.setAttribute('y', '13');
+ title.setAttribute('x', '99.5%');
+ title.setAttribute('fill', 'white');
+ title.setAttribute('font-size', '12px');
+ title.setAttribute('text-anchor', 'end');
+ g.appendChild(title);
+
+ var meter = document.createElementNS(svgns, 'rect');
+ meter.id = 'meter';
+ meter.setAttribute('width', '0%');
+ meter.setAttribute('height', '17');
+ meter.setAttribute('fill', 'url(#progress_pattern)');
+ meter.setAttribute('rx', '5');
+ meter.setAttribute('ry', '5');
+
+ var meter2 = document.createElementNS(svgns, 'rect');
+ meter2.id = 'meter2';
+ meter2.setAttribute('width', '0%');
+ meter2.setAttribute('height', '17');
+ meter2.setAttribute('opacity', '0.8');
+ meter2.setAttribute('fill', '#007fff');
+ meter2.setAttribute('rx', '5');
+ meter2.setAttribute('ry', '5');
+
+ g.appendChild(meter);
+ g.appendChild(meter2);
+
+ var page = document.createElementNS(svgns, 'text');
+ page.id = 'page';
+ page.appendChild(document.createTextNode('0/0'));
+ page.setAttribute('y', '13');
+ page.setAttribute('x', '0.5%');
+ page.setAttribute('fill', 'white');
+ page.setAttribute('font-size', '12px');
+ g.appendChild(page);
- var meter2 = document.createElementNS(svgns, 'rect');
- meter2.id = 'meter2';
- meter2.setAttribute('width', '0%');
- meter2.setAttribute('height', '17');
- meter2.setAttribute('opacity', '0.8');
- meter2.setAttribute('fill', '#007fff');
- meter2.setAttribute('rx', '5');
- meter2.setAttribute('ry', '5');
- g.appendChild(meter);
- g.appendChild(meter2);
+ svg.appendChild(g);
+ pdiv.appendChild(svg);
- var page = document.createElementNS(svgns, 'text');
- page.id = 'page';
- page.appendChild(document.createTextNode('0/0'));
- page.setAttribute('y', '13');
- page.setAttribute('x', '0.5%');
- page.setAttribute('fill', 'white');
- page.setAttribute('font-size', '12px');
- g.appendChild(page);
-
-
- svg.appendChild(g);
- pdiv.appendChild(svg);
-
- svg.onclick = function(e) {
- for (var x = pdiv, l = 0; x != document.documentElement; x = x.parentNode) l += x.offsetLeft;
- var page = Math.max(1, Math.ceil(((e.clientX - l)/pdiv.offsetWidth) * totalImages)) - 1;
- currentImage = page;
- updatePage();
- };
+ svg.onclick = function(e) {
+ for (var x = pdiv, l = 0; x != document.documentElement; x = x.parentNode) l += x.offsetLeft;
+ var page = Math.max(1, Math.ceil(((e.clientX - l)/pdiv.offsetWidth) * totalImages)) - 1;
+ currentImage = page;
+ updatePage();
+ };
}
kthoom.setProgressMeter = function(pct, opt_label) {
- var pct = (pct*100);
- var part = 1/totalImages;
- var remain = ((pct - lastCompletion)/100)/part;
- var fract = Math.min(1, remain);
- var smartpct = ((imageFiles.length/totalImages) + fract * part )* 100;
- if (totalImages == 0) smartpct = pct;
+ var pct = (pct*100);
+ var part = 1/totalImages;
+ var remain = ((pct - lastCompletion)/100)/part;
+ var fract = Math.min(1, remain);
+ var smartpct = ((imageFiles.length/totalImages) + fract * part )* 100;
+ if (totalImages == 0) smartpct = pct;
- // + Math.min((pct - lastCompletion), 100/totalImages * 0.9 + (pct - lastCompletion - 100/totalImages)/2, 100/totalImages);
- var oldval = parseFloat(getElem('meter').getAttribute('width'));
- if (isNaN(oldval)) oldval = 0;
- var weight = 0.5;
- smartpct = (weight * smartpct + (1-weight) * oldval);
- if (pct == 100) smartpct = 100;
+ // + Math.min((pct - lastCompletion), 100/totalImages * 0.9 + (pct - lastCompletion - 100/totalImages)/2, 100/totalImages);
+ var oldval = parseFloat(getElem('meter').getAttribute('width'));
+ if (isNaN(oldval)) oldval = 0;
+ var weight = 0.5;
+ smartpct = (weight * smartpct + (1-weight) * oldval);
+ if (pct == 100) smartpct = 100;
- if (!isNaN(smartpct)) {
- getElem('meter').setAttribute('width', smartpct + '%');
- }
- var title = getElem('progress_title');
- while (title.firstChild) title.removeChild(title.firstChild);
-
- var labelText = pct.toFixed(2) + '% ' + imageFiles.length + '/' + totalImages + '';
- if (opt_label) {
- labelText = opt_label + ' ' + labelText;
- }
- title.appendChild(document.createTextNode(labelText));
- // fade it out as it approaches finish
- //title.setAttribute('fill-opacity', (pct > 90) ? ((100-pct)*5)/100 : 1);
-
- getElem('meter2').setAttribute('width',
- 100 * (totalImages == 0 ? 0 : ((currentImage+1)/totalImages)) + '%');
+ if (!isNaN(smartpct)) {
+ getElem('meter').setAttribute('width', smartpct + '%');
+ }
+ var title = getElem('progress_title');
+ while (title.firstChild) title.removeChild(title.firstChild);
+
+ var labelText = pct.toFixed(2) + '% ' + imageFiles.length + '/' + totalImages + '';
+ if (opt_label) {
+ labelText = opt_label + ' ' + labelText;
+ }
+ title.appendChild(document.createTextNode(labelText));
+
+ getElem('meter2').setAttribute('width',
+ 100 * (totalImages == 0 ? 0 : ((currentImage+1)/totalImages)) + '%');
- var title = getElem('page');
- while (title.firstChild) title.removeChild(title.firstChild);
- title.appendChild(document.createTextNode( (currentImage+1) + '/' + totalImages ));
+ var title = getElem('page');
+ while (title.firstChild) title.removeChild(title.firstChild);
+ title.appendChild(document.createTextNode( (currentImage+1) + '/' + totalImages ));
- if (pct > 0) {
- //getElem('nav').className = '';
- getElem('progress').className = '';
- }
+ if (pct > 0) {
+ //getElem('nav').className = '';
+ getElem('progress').className = '';
+ }
}
function loadFromArrayBuffer(ab) {
- var start = (new Date).getTime();
- var h = new Uint8Array(ab, 0, 10);
- var pathToBitJS = '../../static/js/';
- 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);
- }
- // Listen for UnarchiveEvents.
- if (unarchiver) {
- unarchiver.addEventListener(bitjs.archive.UnarchiveEvent.Type.PROGRESS,
- function(e) {
- var percentage = e.currentBytesUnarchived / e.totalUncompressedBytesInArchive;
- totalImages = e.totalFilesInArchive;
- kthoom.setProgressMeter(percentage, 'Unzipping');
- // display nav
- lastCompletion = percentage * 100;
- });
- unarchiver.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 (imageFilenames.indexOf(f.filename) == -1) {
- imageFilenames.push(f.filename);
- imageFiles.push(new kthoom.ImageFile(f));
- }
- }
-
- // display first page if we haven't yet
- if (imageFiles.length == currentImage + 1) {
- updatePage();
- }
- });
- unarchiver.addEventListener(bitjs.archive.UnarchiveEvent.Type.FINISH,
- function(e) {
- var diff = ((new Date).getTime() - start)/1000;
- console.log('Unarchiving done in ' + diff + 's');
- })
- unarchiver.start();
- } else {
- alert('Some error');
- }
+ var start = (new Date).getTime();
+ var h = new Uint8Array(ab, 0, 10);
+ var pathToBitJS = '../../static/js/';
+ 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);
+ }
+ // Listen for UnarchiveEvents.
+ if (unarchiver) {
+ unarchiver.addEventListener(bitjs.archive.UnarchiveEvent.Type.PROGRESS,
+ function(e) {
+ var percentage = e.currentBytesUnarchived / e.totalUncompressedBytesInArchive;
+ totalImages = e.totalFilesInArchive;
+ kthoom.setProgressMeter(percentage, 'Unzipping');
+ // display nav
+ lastCompletion = percentage * 100;
+ });
+ unarchiver.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 (imageFilenames.indexOf(f.filename) == -1) {
+ imageFilenames.push(f.filename);
+ imageFiles.push(new kthoom.ImageFile(f));
+ }
+ }
+ // display first page if we haven't yet
+ if (imageFiles.length == currentImage + 1) {
+ updatePage();
+ }
+ });
+ unarchiver.addEventListener(bitjs.archive.UnarchiveEvent.Type.FINISH,
+ function(e) {
+ var diff = ((new Date).getTime() - start)/1000;
+ console.log('Unarchiving done in ' + diff + 's');
+ });
+ unarchiver.start();
+ } else {
+ alert('Some error');
+ }
}
var createURLFromArray = function(array, mimeType) {
- var offset = array.byteOffset, len = array.byteLength;
- var bb, url;
- var blob;
-
- // TODO: Move all this browser support testing to a common place
- // and do it just once.
-
- // Blob constructor, see http://dev.w3.org/2006/webapi/FileAPI/#dfn-Blob.
- if (typeof Blob == 'function') {
- blob = new Blob([array], {type: mimeType});
- } else {
- throw 'Browser support for Blobs is missing.'
- }
-
- if (blob.slice) {
- blob = blob.slice(offset, offset + len, mimeType);
- } else {
- throw 'Browser support for Blobs is missing.'
- }
-
- if ((typeof URL != 'function' && typeof URL != 'object') ||
+ var offset = array.byteOffset, len = array.byteLength;
+ var bb, url;
+ var blob;
+
+ // TODO: Move all this browser support testing to a common place
+ // and do it just once.
+
+ // Blob constructor, see http://dev.w3.org/2006/webapi/FileAPI/#dfn-Blob.
+ if (typeof Blob == 'function') {
+ blob = new Blob([array], {type: mimeType});
+ } else {
+ throw 'Browser support for Blobs is missing.'
+ }
+
+ if (blob.slice) {
+ blob = blob.slice(offset, offset + len, mimeType);
+ } else {
+ throw 'Browser support for Blobs is missing.'
+ }
+
+ if ((typeof URL != 'function' && typeof URL != 'object') ||
typeof URL.createObjectURL != 'function') {
- throw 'Browser support for Object URLs is missing';
- }
+ throw 'Browser support for Object URLs is missing';
+ }
- return URL.createObjectURL(blob);
+ return URL.createObjectURL(blob);
}
function updatePage() {
- var title = getElem('page');
- while (title.firstChild) title.removeChild(title.firstChild);
- title.appendChild(document.createTextNode( (currentImage+1) + '/' + totalImages ));
-
- getElem('meter2').setAttribute('width',
+ var title = getElem('page');
+ while (title.firstChild) title.removeChild(title.firstChild);
+ title.appendChild(document.createTextNode( (currentImage+1) + '/' + totalImages ));
+
+ getElem('meter2').setAttribute('width',
100 * (totalImages == 0 ? 0 : ((currentImage+1)/totalImages)) + '%');
- if (imageFiles[currentImage]) {
- setImage(imageFiles[currentImage].dataURI);
- } else {
- setImage('loading');
- }
+ if (imageFiles[currentImage]) {
+ setImage(imageFiles[currentImage].dataURI);
+ } else {
+ setImage('loading');
+ }
}
function setImage(url) {
- var canvas = $("#mainImage")[0];
- var x = $("#mainImage")[0].getContext('2d');
- $('#mainText').hide();
- if (url == 'loading') {
- updateScale(true);
- canvas.width = innerWidth - 100;
- canvas.height = 200;
- x.fillStyle = 'red';
- x.font = '50px sans-serif';
- x.strokeStyle = 'black';
- x.fillText('Loading Page #' + (currentImage + 1), 100, 100)
- } else {
- if ($('body').css('scrollHeight')/innerHeight > 1) {
- $('body').css('overflowY', 'scroll');
- }
-
- var img = new Image();
- img.onerror = function(e) {
- canvas.width = innerWidth - 100;
- canvas.height = 300;
- updateScale(true);
- x.fillStyle = 'orange';
- x.font = '50px sans-serif';
- x.strokeStyle = 'black';
- x.fillText('Page #' + (currentImage+1) + ' (' +
- imageFiles[currentImage].filename + ')', 100, 100)
- x.fillStyle = 'red';
- x.fillText('Is corrupt or not an image', 100, 200);
-
- if (/(html|htm)$/.test(imageFiles[currentImage].filename)) {
- var xhr = new XMLHttpRequest();
- xhr.open('GET', url, true);
- xhr.onload = function() {
- //document.getElementById('mainText').style.display = '';
- $("#mainText").css("display", "");
- $("#mainText").innerHTML('');
+ var canvas = $("#mainImage")[0];
+ var x = $("#mainImage")[0].getContext('2d');
+ $('#mainText').hide();
+ if (url == 'loading') {
+ updateScale(true);
+ canvas.width = innerWidth - 100;
+ canvas.height = 200;
+ x.fillStyle = 'red';
+ x.font = '50px sans-serif';
+ x.strokeStyle = 'black';
+ x.fillText('Loading Page #' + (currentImage + 1), 100, 100)
+ } else {
+ if ($('body').css('scrollHeight')/innerHeight > 1) {
+ $('body').css('overflowY', 'scroll');
}
- xhr.send(null);
- } else if (!/(jpg|jpeg|png|gif)$/.test(imageFiles[currentImage].filename) && imageFiles[currentImage].data.uncompressedSize < 10*1024) {
- var xhr = new XMLHttpRequest();
- xhr.open('GET', url, true);
- xhr.onload = function() {
- $("#mainText").css("display", "");
- $("#mainText").innerText(xhr.responseText);
+
+ var img = new Image();
+ img.onerror = function(e) {
+ canvas.width = innerWidth - 100;
+ canvas.height = 300;
+ updateScale(true);
+ x.fillStyle = 'orange';
+ x.font = '50px sans-serif';
+ x.strokeStyle = 'black';
+ x.fillText('Page #' + (currentImage+1) + ' (' +
+ imageFiles[currentImage].filename + ')', 100, 100)
+ x.fillStyle = 'red';
+ x.fillText('Is corrupt or not an image', 100, 200);
+
+ if (/(html|htm)$/.test(imageFiles[currentImage].filename)) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.onload = function() {
+ //document.getElementById('mainText').style.display = '';
+ $("#mainText").css("display", "");
+ $("#mainText").innerHTML('');
+ }
+ xhr.send(null);
+ } else if (!/(jpg|jpeg|png|gif)$/.test(imageFiles[currentImage].filename) && imageFiles[currentImage].data.uncompressedSize < 10*1024) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.onload = function() {
+ $("#mainText").css("display", "");
+ $("#mainText").innerText(xhr.responseText);
+ };
+ xhr.send(null);
+ }
};
- xhr.send(null);
- }
- };
- img.onload = function() {
- var h = img.height,
- w = img.width,
- sw = w,
- sh = h;
- kthoom.rotateTimes = (4 + kthoom.rotateTimes) % 4;
- x.save();
- if (kthoom.rotateTimes % 2 == 1) { sh = w; sw = h;}
- canvas.height = sh;
- canvas.width = sw;
- x.translate(sw/2, sh/2);
- x.rotate(Math.PI/2 * kthoom.rotateTimes);
- x.translate(-w/2, -h/2);
- if (vflip) {
- x.scale(1, -1)
- x.translate(0, -h);
- }
- if (hflip) {
- x.scale(-1, 1)
- x.translate(-w, 0);
- }
- canvas.style.display = 'none';
- scrollTo(0,0);
- x.drawImage(img, 0, 0);
-
- updateScale();
-
- canvas.style.display = '';
- $("body").css("overflowY", "");
- x.restore();
- };
- img.src = url;
- };
+ img.onload = function() {
+ var h = img.height,
+ w = img.width,
+ sw = w,
+ sh = h;
+ kthoom.rotateTimes = (4 + kthoom.rotateTimes) % 4;
+ x.save();
+ if (kthoom.rotateTimes % 2 == 1) { sh = w; sw = h;}
+ canvas.height = sh;
+ canvas.width = sw;
+ x.translate(sw/2, sh/2);
+ x.rotate(Math.PI/2 * kthoom.rotateTimes);
+ x.translate(-w/2, -h/2);
+ if (vflip) {
+ x.scale(1, -1)
+ x.translate(0, -h);
+ }
+ if (hflip) {
+ x.scale(-1, 1)
+ x.translate(-w, 0);
+ }
+ canvas.style.display = 'none';
+ scrollTo(0,0);
+ x.drawImage(img, 0, 0);
+
+ updateScale();
+
+ canvas.style.display = '';
+ $("body").css("overflowY", "");
+ x.restore();
+ };
+ img.src = url;
+ }
}
function showPrevPage() {
- currentImage--;
+ currentImage--;
- if (currentImage < 0) {
- if (library.allBooks.length == 1) {
- currentImage = imageFiles.length - 1;
- } else if (library.currentBookNum > 0) {
- loadPrevBook();
- } else {
- // Freeze on the current page.
- currentImage++;
- return;
+ if (currentImage < 0) {
+ if (library.allBooks.length == 1) {
+ currentImage = imageFiles.length - 1;
+ } else if (library.currentBookNum > 0) {
+ loadPrevBook();
+ } else {
+ // Freeze on the current page.
+ currentImage++;
+ return;
+ }
}
- }
-
- updatePage();
+ updatePage();
}
function showNextPage() {
- currentImage++;
+ currentImage++;
- if (currentImage >= Math.max(totalImages, imageFiles.length)) {
- if (library.allBooks.length == 1) {
- currentImage = 0;
- } else if (library.currentBookNum < library.allBooks.length - 1) {
- loadNextBook();
- } else {
- // Freeze on the current page.
- currentImage--;
- return;
+ if (currentImage >= Math.max(totalImages, imageFiles.length)) {
+ if (library.allBooks.length == 1) {
+ currentImage = 0;
+ } else if (library.currentBookNum < library.allBooks.length - 1) {
+ loadNextBook();
+ } else {
+ // Freeze on the current page.
+ currentImage--;
+ return;
+ }
}
- }
-
- updatePage();
+ updatePage();
}
function updateScale(clear) {
- var mainImageStyle = getElem('mainImage').style;
- mainImageStyle.width = '';
- mainImageStyle.height = '';
- mainImageStyle.maxWidth = '';
- mainImageStyle.maxHeight = '';
- var maxheight = innerHeight - 15;
- if (!/main/.test(getElem('titlebar').className)) {
- maxheight -= 25;
- }
- if (clear || fitMode == kthoom.Key.N) {
- } else if (fitMode == kthoom.Key.B) {
- mainImageStyle.maxWidth = '100%';
- mainImageStyle.maxHeight = maxheight + 'px';
- } else if (fitMode == kthoom.Key.H) {
- mainImageStyle.height = maxheight + 'px';
- } else if (fitMode == kthoom.Key.W) {
- mainImageStyle.width = '100%';
- }
- kthoom.saveSettings();
+ var mainImageStyle = getElem('mainImage').style;
+ mainImageStyle.width = '';
+ mainImageStyle.height = '';
+ mainImageStyle.maxWidth = '';
+ mainImageStyle.maxHeight = '';
+ var maxheight = innerHeight - 15;
+ if (!/main/.test(getElem('titlebar').className)) {
+ maxheight -= 25;
+ }
+ if (clear || fitMode == kthoom.Key.N) {
+ } else if (fitMode == kthoom.Key.B) {
+ mainImageStyle.maxWidth = '100%';
+ mainImageStyle.maxHeight = maxheight + 'px';
+ } else if (fitMode == kthoom.Key.H) {
+ mainImageStyle.height = maxheight + 'px';
+ } else if (fitMode == kthoom.Key.W) {
+ mainImageStyle.width = '100%';
+ }
+ kthoom.saveSettings();
}
function keyHandler(evt) {
- var code = evt.keyCode;
-
- if (getComputedStyle(getElem('progress')).display == 'none') return;
- canKeyNext = ((document.body.offsetWidth+document.body.scrollLeft)/ document.body.scrollWidth) >= 1;
- canKeyPrev = (scrollX <= 0);
-
- if (evt.ctrlKey || evt.shiftKey || evt.metaKey) return;
- switch(code) {
- case kthoom.Key.LEFT:
- if (canKeyPrev) showPrevPage();
- break;
- case kthoom.Key.RIGHT:
- if (canKeyNext) showNextPage();
- break;
- case kthoom.Key.L:
- kthoom.rotateTimes--;
- if (kthoom.rotateTimes < 0) {
- kthoom.rotateTimes = 3;
- }
- updatePage();
- break;
- case kthoom.Key.R:
- kthoom.rotateTimes++;
- if (kthoom.rotateTimes > 3) {
- kthoom.rotateTimes = 0;
- }
- updatePage();
- break;
- case kthoom.Key.F:
- if (!hflip && !vflip) {
- hflip = true;
- } else if(hflip == true) {
- vflip = true;
- hflip = false;
- } else if(vflip == true) {
- vflip = false;
- }
- updatePage();
- break;
- case kthoom.Key.W:
- fitMode = kthoom.Key.W;
- updateScale();
- break;
- case kthoom.Key.H:
- fitMode = kthoom.Key.H;
- updateScale();
- break;
- case kthoom.Key.B:
- fitMode = kthoom.Key.B;
- updateScale();
- break;
- case kthoom.Key.N:
- fitMode = kthoom.Key.N;
- updateScale();
- break;
- default:
- //console.log('KeyCode = ' + code);
- break;
- }
+ var code = evt.keyCode;
+
+ if (getComputedStyle(getElem('progress')).display == 'none') return;
+ canKeyNext = ((document.body.offsetWidth+document.body.scrollLeft)/ document.body.scrollWidth) >= 1;
+ canKeyPrev = (scrollX <= 0);
+
+ if (evt.ctrlKey || evt.shiftKey || evt.metaKey) return;
+ switch(code) {
+ case kthoom.Key.LEFT:
+ if (canKeyPrev) showPrevPage();
+ break;
+ case kthoom.Key.RIGHT:
+ if (canKeyNext) showNextPage();
+ break;
+ case kthoom.Key.L:
+ kthoom.rotateTimes--;
+ if (kthoom.rotateTimes < 0) {
+ kthoom.rotateTimes = 3;
+ }
+ updatePage();
+ break;
+ case kthoom.Key.R:
+ kthoom.rotateTimes++;
+ if (kthoom.rotateTimes > 3) {
+ kthoom.rotateTimes = 0;
+ }
+ updatePage();
+ break;
+ case kthoom.Key.F:
+ if (!hflip && !vflip) {
+ hflip = true;
+ } else if(hflip == true) {
+ vflip = true;
+ hflip = false;
+ } else if(vflip == true) {
+ vflip = false;
+ }
+ updatePage();
+ break;
+ case kthoom.Key.W:
+ fitMode = kthoom.Key.W;
+ updateScale();
+ break;
+ case kthoom.Key.H:
+ fitMode = kthoom.Key.H;
+ updateScale();
+ break;
+ case kthoom.Key.B:
+ fitMode = kthoom.Key.B;
+ updateScale();
+ break;
+ case kthoom.Key.N:
+ fitMode = kthoom.Key.N;
+ updateScale();
+ break;
+ default:
+ //console.log('KeyCode = ' + code);
+ break;
+ }
}
function init(filename) {
- if (!window.FileReader) {
- alert('Sorry, kthoom will not work with your browser because it does not support the File API. Please try kthoom with Chrome 12+ or Firefox 7+');
- } else {
- var request = new XMLHttpRequest();
- request.open("GET",filename);
- request.responseType="arraybuffer";
- request.setRequestHeader("X-Test","test1");
- request.setRequestHeader("X-Test","test2");
- request.addEventListener('load', function(event) {
- if (request.status >= 200 && request.status < 300) {
- loadFromArrayBuffer(request.response);
- } else {
- console.warn(request.statusText, request.responseText);
- }
- });
- request.send();
- kthoom.initProgressMeter();
- document.body.className += /AppleWebKit/.test(navigator.userAgent) ? ' webkit' : '';
- //kthoom.resetFileUploader();
- kthoom.loadSettings();
- $(document).keydown(keyHandler);
-
- $(window).resize(function() {
- var f = (screen.width - innerWidth < 4 && screen.height - innerHeight < 4);
- getElem('titlebar').className = f ? 'main' : '';
- updateScale();
- });
-
- $('#mainImage').click(function(evt) {
- // Firefox does not support offsetX/Y so we have to manually calculate
- // where the user clicked in the image.
- var mainContentWidth = getElem('mainContent').clientWidth;
- var mainContentHeight = getElem('mainContent').clientHeight;
- var comicWidth = evt.target.clientWidth;
- var comicHeight = evt.target.clientHeight;
- var offsetX = (mainContentWidth - comicWidth) / 2;
- var offsetY = (mainContentHeight - comicHeight) / 2;
- var clickX = !!evt.offsetX ? evt.offsetX : (evt.clientX - offsetX);
- var clickY = !!evt.offsetY ? evt.offsetY : (evt.clientY - offsetY);
-
- // Determine if the user clicked/tapped the left side or the
- // right side of the page.
- var clickedPrev = false;
- switch (kthoom.rotateTimes) {
- case 0:
- clickedPrev = clickX < (comicWidth / 2);
- break;
- case 1:
- clickedPrev = clickY < (comicHeight / 2);
- break;
- case 2:
- clickedPrev = clickX > (comicWidth / 2);
- break;
- case 3:
- clickedPrev = clickY > (comicHeight / 2);
- break;
- }
- if (clickedPrev) {
- showPrevPage();
- } else {
- showNextPage();
- }
- });
- }
+ if (!window.FileReader) {
+ alert('Sorry, kthoom will not work with your browser because it does not support the File API. Please try kthoom with Chrome 12+ or Firefox 7+');
+ } else {
+ var request = new XMLHttpRequest();
+ request.open("GET",filename);
+ request.responseType="arraybuffer";
+ request.setRequestHeader("X-Test","test1");
+ request.setRequestHeader("X-Test","test2");
+ request.addEventListener('load', function(event) {
+ if (request.status >= 200 && request.status < 300) {
+ loadFromArrayBuffer(request.response);
+ } else {
+ console.warn(request.statusText, request.responseText);
+ }
+ });
+ request.send();
+ kthoom.initProgressMeter();
+ document.body.className += /AppleWebKit/.test(navigator.userAgent) ? ' webkit' : '';
+ kthoom.loadSettings();
+ $(document).keydown(keyHandler);
+
+ $(window).resize(function() {
+ var f = (screen.width - innerWidth < 4 && screen.height - innerHeight < 4);
+ getElem('titlebar').className = f ? 'main' : '';
+ updateScale();
+ });
+
+ $('#mainImage').click(function(evt) {
+ // Firefox does not support offsetX/Y so we have to manually calculate
+ // where the user clicked in the image.
+ var mainContentWidth = getElem('mainContent').clientWidth;
+ var mainContentHeight = getElem('mainContent').clientHeight;
+ var comicWidth = evt.target.clientWidth;
+ var comicHeight = evt.target.clientHeight;
+ var offsetX = (mainContentWidth - comicWidth) / 2;
+ var offsetY = (mainContentHeight - comicHeight) / 2;
+ var clickX = !!evt.offsetX ? evt.offsetX : (evt.clientX - offsetX);
+ var clickY = !!evt.offsetY ? evt.offsetY : (evt.clientY - offsetY);
+
+ // Determine if the user clicked/tapped the left side or the
+ // right side of the page.
+ var clickedPrev = false;
+ switch (kthoom.rotateTimes) {
+ case 0:
+ clickedPrev = clickX < (comicWidth / 2);
+ break;
+ case 1:
+ clickedPrev = clickY < (comicHeight / 2);
+ break;
+ case 2:
+ clickedPrev = clickX > (comicWidth / 2);
+ break;
+ case 3:
+ clickedPrev = clickY > (comicHeight / 2);
+ break;
+ }
+ if (clickedPrev) {
+ showPrevPage();
+ } else {
+ showNextPage();
+ }
+ });
+ }
}
diff --git a/cps/static/js/unrar.js b/cps/static/js/unrar.js
index 6d63b216..c2a50467 100644
--- a/cps/static/js/unrar.js
+++ b/cps/static/js/unrar.js
@@ -23,196 +23,196 @@ var totalFilesInArchive = 0;
// Helper functions.
var info = function(str) {
- postMessage(new bitjs.archive.UnarchiveInfoEvent(str));
+ postMessage(new bitjs.archive.UnarchiveInfoEvent(str));
};
var err = function(str) {
- postMessage(new bitjs.archive.UnarchiveErrorEvent(str));
+ postMessage(new bitjs.archive.UnarchiveErrorEvent(str));
};
var postProgress = function() {
- postMessage(new bitjs.archive.UnarchiveProgressEvent(
- currentFilename,
- currentFileNumber,
- currentBytesUnarchivedInFile,
- currentBytesUnarchived,
- totalUncompressedBytesInArchive,
- totalFilesInArchive));
+ 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];
+ 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];
+ 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;
+ 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);
+ 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);
+ // byte 3
+ this.headType = bstream.readBits(8);
+ info(" headType=" + this.headType);
- // Get flags
- // bytes 4,5
- this.flags = {};
- this.flags.value = bstream.peekBits(16);
+ // 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);
- }
+ 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);
+// 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;
+ 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
+ // 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 = bstream.readBytes(this.nameSize);
+ for (var _i = 0, _s = ''; _i < this.filename.length; _i++) {
+ _s += String.fromCharCode(this.filename[_i]);
+ }
- this.filename = _s;
+ 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_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);
+ 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);
- }
- }
+ // 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");
- }
+ if (this.flags.LHD_COMMENT) {
+ info("Found a LHD_COMMENT");
+ }
- while(headPos + this.headSize > bstream.bytePtr) bstream.readBits(1);
+ 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);
+ 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;
- }
+ 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 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];
+ 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,
@@ -227,11 +227,11 @@ var rDBits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5,
var rLOW_DIST_REP_COUNT = 16;
var rNC = 299,
- rDC = 60,
- rLDC = 17,
- rRC = 28,
- rBC = 20,
- rHUFF_TABLE_SIZE = (rNC+rDC+rRC+rLDC);
+ 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);
@@ -266,223 +266,220 @@ var rBuffer;
// read in Huffman tables for RAR
function RarReadTables(bstream) {
- var BitLength = new Array(rBC),
- Table = new Array(rHUFF_TABLE_SIZE);
+ 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 );
+ // 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)) {
+ 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;
- }
+ if (!bstream.readBits(1)) { //discard old table
+ for (var i = UnpOldTable.length; i--;) UnpOldTable[i] = 0;
}
- else {
- BitLength[I] = Length;
+
+ // 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);
+ // 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);
+ 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;
- }
+ 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);
+ 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;
+ 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));
+ 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];
+ 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;
+ 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)
+ 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;
-
+ DecodeNum[ TmpPos[ BitLength[offset + I] & 0xF ]++] = I;
}
// TODO: implement
function Unpack15(bstream, Solid) {
- info("ERROR! RAR 1.5 compression not supported");
+ info("ERROR! RAR 1.5 compression not supported");
}
function Unpack20(bstream, Solid) {
- var destUnpSize = rBuffer.data.length;
- var oldDistPtr = 0;
+ 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);
+ 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++;
+ 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;
}
- }
- 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()
+ RarUpdateProgress()
}
function RarUpdateProgress() {
- var change = rBuffer.ptr - currentBytesUnarchivedInFile;
- currentBytesUnarchivedInFile = rBuffer.ptr;
- currentBytesUnarchived += change;
- postProgress();
+ var change = rBuffer.ptr - currentBytesUnarchivedInFile;
+ currentBytesUnarchivedInFile = rBuffer.ptr;
+ currentBytesUnarchived += change;
+ postProgress();
}
@@ -495,43 +492,43 @@ var rNC20 = 298,
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++)
+ 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(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];
+ 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;
@@ -542,200 +539,195 @@ var lastLength;
function Unpack29(bstream, Solid) {
- // lazy initialize rDDecode and rDBits
+ // 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;
+ if (num < 256) {
+ rBuffer.insertByte(num);
+ continue;
+ }
+ if (num >= 271) {
+ var Length = rLDecode[num -= 271] + 3;
+ if ((Bits = rLBits[num]) > 0) {
+ Length += bstream.readBits(Bits);
}
- }
- } else {
- Distance += 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 (Distance >= 0x2000) {
- Length++;
- if (Distance >= 0x40000) {
- Length++;
+ 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;
}
- }
- 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()
+ 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));
+ 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);
+ 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;
+ //console.log(vmCode);
+ if (vmCode.length > 0) {
+ info("Error! RarVM not supported yet!");
+ }
+ return true;
}
function RarInsertLastMatch(length, distance) {
- lastDist = distance;
- lastLength = length;
+ lastDist = distance;
+ lastLength = length;
}
function RarInsertOldDist(distance) {
- rOldDist.splice(3,1);
- rOldDist.splice(0,0,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;
+ 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));
}
- //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 = []
@@ -743,154 +735,154 @@ var rOldBuffers = []
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 );
+ 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);
+ rBuffer = new bitjs.io.ByteBuffer(v.header.unpackedSize);
- info("Unpacking "+v.filename+" RAR v"+Ver);
+ 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)
+ 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;
+ 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;
+ 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;
+ 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;
+ 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);
+ 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 */);
+ 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");
+ 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.toLowerCase();
+ var bname = b.filename.toLowerCase();
+ return aname > bname ? 1 : -1;
+ });
+
+ 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 {
- 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.toLowerCase();
- var bname = b.filename.toLowerCase();
- return aname > bname ? 1 : -1;
- });
-
- 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();
+ err("Invalid RAR file");
}
- }
- else {
- err("Invalid RAR file");
- }
- postMessage(new bitjs.archive.UnarchiveFinishEvent());
+ postMessage(new bitjs.archive.UnarchiveFinishEvent());
};
// event.data.file has the ArrayBuffer.
onmessage = function(event) {
- var ab = event.data.file;
- unrar(ab, true);
+ var ab = event.data.file;
+ unrar(ab, true);
};
diff --git a/cps/static/js/untar.js b/cps/static/js/untar.js
index defed7d7..93297028 100644
--- a/cps/static/js/untar.js
+++ b/cps/static/js/untar.js
@@ -22,147 +22,147 @@ var totalFilesInArchive = 0;
// Helper functions.
var info = function(str) {
- postMessage(new bitjs.archive.UnarchiveInfoEvent(str));
+ postMessage(new bitjs.archive.UnarchiveInfoEvent(str));
};
var err = function(str) {
- postMessage(new bitjs.archive.UnarchiveErrorEvent(str));
+ postMessage(new bitjs.archive.UnarchiveErrorEvent(str));
};
var postProgress = function() {
- postMessage(new bitjs.archive.UnarchiveProgressEvent(
- currentFilename,
- currentFileNumber,
- currentBytesUnarchivedInFile,
- currentBytesUnarchived,
- totalUncompressedBytesInArchive,
- totalFilesInArchive));
+ 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;
+ 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
- }
+ 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.")
- }
+ // 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.toLowerCase();
- var bname = b.filename.toLowerCase();
- return aname > bname ? 1 : -1;
- });
-
- // 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();
- }
+ 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.toLowerCase();
+ var bname = b.filename.toLowerCase();
+ return aname > bname ? 1 : -1;
+ });
+
+ // 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();
+ postProgress();
- postMessage(new bitjs.archive.UnarchiveFinishEvent());
+ postMessage(new bitjs.archive.UnarchiveFinishEvent());
};
// event.data.file has the ArrayBuffer.
onmessage = function(event) {
- var ab = event.data.file;
- untar(ab);
+ var ab = event.data.file;
+ untar(ab);
};