lufi/themes/default/public/js/lufi-down.js

280 lines
12 KiB
JavaScript

// vim:set sw=4 ts=4 sts=4 ft=javascript expandtab:
/*
* Return the deciphering key stored in anchor part of the URL
* Stolen from https://github.com/sebsauvage/ZeroBin/blob/master/js/zerobin.js
*/
function pageKey() {
var key = window.location.hash.substring(1); // Get key
// Some stupid web 2.0 services and redirectors add data AFTER the anchor
// (such as &utm_source=...).
// We will strip any additional data.
// First, strip everything after the equal sign (=) which signals end of base64 string.
i = key.indexOf('='); if (i>-1) { key = key.substring(0, i + 1); }
// If the equal sign was not present, some parameters may remain:
i = key.indexOf('&'); if (i>-1) { key = key.substring(0, i); }
// Then add trailing equal sign if it's missing
if (key.charAt(key.length-1)!=='=') key += '=';
return key;
}
function base64ToArrayBuffer(base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array( len );
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
// Something's wring
function addAlert(msg) {
$('#please-wait').remove();
var pbd = $('.file-progress');
pbd.attr('role', 'alert');
pbd.removeClass('progress');
pbd.html(`<div class="card pink">
<div class="card-content white-text">
<strong>${msg}</strong>
</div>
</div>`);
}
// Spawn WebSocket
function spawnWebsocket(pa) {
console.log('Spawning websocket…');
var ws = new WebSocket(ws_url);
ws.onopen = function() {
console.log('Connection is established!');
var l = $('#loading');
l.html(i18n.loading.replace(/XX1/, (pa + 1)));
if ($('#file_pwd').length === 1) {
val = $('#file_pwd').val();
window.ws.send(`{"part":${pa}, "file_pwd": "${val}"}`);
} else {
window.ws.send(`{"part":${pa}}`);
}
};
ws.onclose = function() {
console.log('Connection is closed');
if (!window.completed) {
window.attempts++;
if (window.attempts < 10) {
console.log(`Connection closed. Retrying to get slice ${pa}`);
window.ws = spawnWebsocket(pa);
} else {
alert(i18n.tooMuchAttempts);
}
}
}
ws.onmessage = function(e) {
var res = e.data.split('XXMOJOXX');
var json = res.shift();
var data = JSON.parse(json);
// Reset counter since we succeded to open a websocket and got a message
window.attempts = 0;
if (data.msg !== undefined) {
addAlert(data.msg);
console.log(data.msg);
if ($('#file_pwd').length === 1) {
$('.file-abort').addClass('hide');
}
window.onbeforeunload = null;
window.attempts = 10;
} else {
console.log(`Getting slice ${data.part + 1} of ${data.total}`);
var slice = JSON.parse(res.shift());
var percent = Math.round(1000 * (data.part + 1)/data.total)/10;
var wClass = percent.toString().replace('.', '-');
var pb = $('#pb');
pb.removeClass();
pb.addClass('determinate');
pb.addClass(`width-${wClass}`);
pb.attr('aria-valuenow', percent);
$('#pbt').html(`${percent}%`);
try {
var b64 = sjcl.decrypt(window.key, slice);
window.a[data.part] = base64ToArrayBuffer(b64);
if (data.part + 1 === data.total) {
var blob = new Blob(a, {type: data.type});
notify(i18n.fileDownloaded, data.name);
$('#please-wait').remove();
$('#loading').remove();
var pbd = $('#pbd');
pbd.attr('class', 'center-align');
// IE & Edge fix for downloading blob files, gives option to save or open the file when the link is opened.
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
var fileName = escapeHtml(data.name);
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
var blobURL = URL.createObjectURL(blob);
}
var innerHTML = `<p><a href="${blobURL}" class="btn btn-primary" download="${escapeHtml(data.name)}">${i18n.download}</a></p>`;
var isZip = ($('#filesize').attr('data-zipped') === 'true');
if (data.type.match(/^image\//) !== null) {
innerHTML += `<img id="render-image" class="responsive-img" alt="${escapeHtml(data.name)}" src="${blobURL}">`;
} else if (data.type.match(/^video\//) !== null) {
innerHTML += `<video class="responsive-video" controls>
<source src="${blobURL}" type="${data.type}">
</video>`;
} else if (data.type.match(/^audio\//) !== null) {
innerHTML += `<audio class="responsive-video" controls>
<source src="${blobURL}" type="${data.type}">
</audio>`;
} else if (isZip) {
innerHTML += `<p><a class="btn btn-primary" id="showZipContent">${i18n.showZipContent}</a></p>`;
}
pbd.html(innerHTML);
if (isZip) {
$('#showZipContent').click(function() {
JSZip.loadAsync(blob)
.then(function (zip) {
var innerHTML = `<h3>${i18n.zipContent}</h3><ul>`;
zip.forEach(function (relativePath, zipEntry) {
innerHTML += `<li>
${escapeHtml(zipEntry.name)}
(${filesize(zipEntry._data.uncompressedSize, {base: 10})})
<a href="#"
download="${escapeHtml(zipEntry.name)}"
class="download-zip-content"
title="${i18n.download}">
<i class="mdi-file-file-download"></i>
</a>
</li>`
});
innerHTML += '</ul>';
pbd.append(innerHTML);
$('.download-zip-content').click(function(e) {
e.preventDefault();
var t = $(this);
var filename = t.attr('download');
zip.files[filename].async('blob').then(function(blob) {
t.unbind('click');
t.attr('href', URL.createObjectURL(blob));
t[0].click();
});
})
$('#showZipContent').hide();
$('#showZipContent').unbind('click');
});
});
}
if ($('#file_pwd').length === 1) {
val = $('#file_pwd').val();
window.ws.send(`{"ended":true, "file_pwd": "${val}"}`);
} else {
window.ws.send('{"ended":true}');
}
window.onbeforeunload = null;
window.completed = true;
$('#abort').remove();
} else {
var l = $('#loading');
l.html(i18n.loading.replace(/XX1/, (data.part + 1)));
if (ws.readyState === 3) {
window.ws = spawnWebsocket(data.part + 1);
} else {
window.ws.onclose = function() {
console.log('Connection is closed');
if (!window.completed) {
console.log(`Connection closed. Retrying to get slice ${data.part + 1}`);
window.ws = spawnWebsocket(data.part + 1);
}
}
window.ws.onerror = function() {
console.log(`Error. Retrying to get slice ${data.part + 1}`);
window.ws = spawnWebsocket(data.part + 1);
};
if ($('#file_pwd').length === 1) {
val = $('#file_pwd').val();
window.ws.send(`{"part":${data.part + 1}, "file_pwd": "${val}"}`);
} else {
window.ws.send(`{"part":${data.part + 1}}`);
}
}
}
} catch(err) {
if (err.message === 'ccm: tag doesn\'t match') {
addAlert(i18n.badkey);
} else {
addAlert(err.message);
}
window.onbeforeunload = null;
}
}
}
ws.onerror = function() {
window.attempts++;
if (window.attempts < 10) {
console.log(`Error. Retrying to get slice ${pa}`);
window.ws = spawnWebsocket(pa);
} else {
alert(i18n.tooMuchAttempts);
}
}
return ws;
}
// When it's ready
$(document).ready(function(){
$('#abort').click(function() {
window.ws.onclose = function() {};
window.ws.close();
$('#please-wait, #loading, #pbd, #abort').remove();
$('#filesize').parent().append(`<h4>${i18n.aborted1}</h4>
<p>
<a id="reloadLocation"
class="waves-effect waves-light btn">
${i18n.aborted2}
</a>
</p>`);
window.onbeforeunload = null;
$('#reloadLocation').on('click', function(e) {
e.preventDefault();
window.location.reload();
})
});
$('#filesize').html(filesize($('#filesize').attr('data-filesize'), {base: 10}));
window.a = new Array();
window.key = pageKey();
window.completed = false;
window.attempts = 0;
if (key !== '=') {
var go = true;
if ($('#file_pwd').length === 1) {
go = false;
$('#go').click(function() {
$('.file-progress, .file-abort').removeClass('hide');
$('#file_pwd').parent().parent().addClass('hide');
// Set websocket
window.ws = spawnWebsocket(0);
// Prevent exiting page before full download
window.onbeforeunload = confirmExit;
});
}
if (go) {
// Set websocket
window.ws = spawnWebsocket(0);
// Prevent exiting page before full download
window.onbeforeunload = confirmExit;
}
} else {
addAlert(i18n.nokey);
}
});