// 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(`
${msg}
`); } // 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 = `

${i18n.download}

`; var isZip = ($('#filesize').attr('data-zipped') === 'true'); if (data.type.match(/^image\//) !== null) { innerHTML += `${escapeHtml(data.name)}`; } else if (data.type.match(/^video\//) !== null) { innerHTML += ``; } else if (data.type.match(/^audio\//) !== null) { innerHTML += ``; } else if (isZip) { innerHTML += `

${i18n.showZipContent}

`; } pbd.html(innerHTML); if (isZip) { $('#showZipContent').click(function() { JSZip.loadAsync(blob) .then(function (zip) { var innerHTML = `

${i18n.zipContent}

'; 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(`

${i18n.aborted1}

${i18n.aborted2}

`); 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); } });