"use strict"; window.onerror = vis_exh; function goto_up2k() { if (up2k === false) return goto('bup'); if (!up2k) return setTimeout(goto_up2k, 100); up2k.init_deps(); } // chrome requires https to use crypto.subtle, // usually it's undefined but some chromes throw on invoke var up2k = null; try { crypto.subtle.digest( 'SHA-512', new Uint8Array(1) ).then( function (x) { up2k = up2k_init(true) }, function (x) { up2k = up2k_init(false) } ); } catch (ex) { try { up2k = up2k_init(false); } catch (ex) { } } function up2k_flagbus() { var flag = { "id": Math.floor(Math.random() * 1024 * 1024 * 1023 * 2), "ch": new BroadcastChannel("up2k_flagbus"), "ours": false, "owner": null, "wants": null, "act": false, "last_tx": ["x", null] }; var dbg = function (who, msg) { console.log('flagbus(' + flag.id + '): [' + who + '] ' + msg); }; flag.ch.onmessage = function (ev) { var who = ev.data[0], what = ev.data[1]; if (who == flag.id) { dbg(who, 'hi me (??)'); return; } flag.act = new Date().getTime(); if (what == "want") { // lowest id wins, don't care if that's us if (who < flag.id) { dbg(who, 'wants (ack)'); flag.wants = [who, flag.act]; } else { dbg(who, 'wants (ign)'); } } else if (what == "have") { dbg(who, 'have'); flag.owner = [who, flag.act]; } else if (what == "give") { if (flag.owner && flag.owner[0] == who) { flag.owner = null; dbg(who, 'give (ok)'); } else { dbg(who, 'give, INVALID, ' + flag.owner); } } else if (what == "hi") { dbg(who, 'hi'); flag.ch.postMessage([flag.id, "hey"]); } else { dbg('?', ev.data); } }; var tx = function (now, msg) { var td = now - flag.last_tx[1]; if (td > 500 || flag.last_tx[0] != msg) { dbg('*', 'tx ' + msg); flag.ch.postMessage([flag.id, msg]); flag.last_tx = [msg, now]; } }; var do_take = function (now) { //dbg('*', 'do_take'); tx(now, "have"); flag.owner = [flag.id, now]; flag.ours = true; }; var do_want = function (now) { //dbg('*', 'do_want'); tx(now, "want"); }; flag.take = function (now) { if (flag.ours) { do_take(now); return; } if (flag.owner && now - flag.owner[1] > 5000) { flag.owner = null; } if (flag.wants && now - flag.wants[1] > 5000) { flag.wants = null; } if (!flag.owner && !flag.wants) { do_take(now); return; } do_want(now); }; flag.give = function () { dbg('#', 'put give'); flag.ch.postMessage([flag.id, "give"]); flag.owner = null; flag.ours = false; }; flag.ch.postMessage([flag.id, 'hi']); return flag; } function up2k_init(have_crypto) { //have_crypto = false; var need_filereader_cache = undefined; // show modal message function showmodal(msg) { ebi('u2notbtn').innerHTML = msg; ebi('u2btn').style.display = 'none'; ebi('u2notbtn').style.display = 'block'; ebi('u2conf').style.opacity = '0.5'; } // hide modal message function unmodal() { ebi('u2notbtn').style.display = 'none'; ebi('u2btn').style.display = 'block'; ebi('u2conf').style.opacity = '1'; ebi('u2notbtn').innerHTML = ''; } var shame = 'your browser disables sha512 unless you use https' var is_https = (window.location + '').indexOf('https:') === 0; if (is_https) // chrome<37 firefox<34 edge<12 ie<11 opera<24 safari<10.1 shame = 'your browser is impressively ancient'; // upload ui hidden by default, clicking the header shows it function init_deps() { if (!have_crypto && !window.asmCrypto) { showmodal('

loading sha512.js

since ' + shame + '

thanks chrome

'); import_js('/.cpr/deps/sha512.js', unmodal); if (is_https) ebi('u2foot').innerHTML = shame + ' so this uploader will do like 500kB/s at best'; else ebi('u2foot').innerHTML = 'seems like ' + shame + ' so do that if you want more performance'; } } // show uploader if the user only has write-access if (!ebi('files')) goto('up2k'); // shows or clears an error message in the basic uploader ui function setmsg(msg) { if (msg !== undefined) { ebi('u2err').setAttribute('class', 'err'); ebi('u2err').innerHTML = msg; } else { ebi('u2err').setAttribute('class', ''); ebi('u2err').innerHTML = ''; } } // switches to the basic uploader with msg as error message function un2k(msg) { setmsg(msg); return false; } // handle user intent to use the basic uploader instead ebi('u2nope').onclick = function (e) { e.preventDefault(); setmsg(); goto('bup'); }; if (!String.prototype.format) { String.prototype.format = function () { var args = arguments; return this.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); }; } function cfg_get(name) { var val = localStorage.getItem(name); if (val === null) return parseInt(ebi(name).value); ebi(name).value = val; return val; } function bcfg_get(name, defval) { var o = ebi(name); if (!o) return defval; var val = localStorage.getItem(name); if (val === null) val = defval; else val = (val == '1'); o.checked = val; return val; } function bcfg_set(name, val) { localStorage.setItem( name, val ? '1' : '0'); var o = ebi(name); if (o) o.checked = val; return val; } var parallel_uploads = cfg_get('nthread'); var multitask = bcfg_get('multitask', true); var ask_up = bcfg_get('ask_up', true); var flag_en = bcfg_get('flag_en', false); var fsearch = bcfg_get('fsearch', false); var col_hashing = '#00bbff'; var col_hashed = '#004466'; var col_uploading = '#ffcc44'; var col_uploaded = '#00bb00'; var fdom_ctr = 0; var st = { "files": [], "todo": { "hash": [], "handshake": [], "upload": [] }, "busy": { "hash": [], "handshake": [], "upload": [] }, "bytes": { "hashed": 0, "uploaded": 0 } }; var bobslice = null; if (window.File) bobslice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; if (!bobslice || !window.FileReader || !window.FileList) return un2k("this is the basic uploader; up2k needs at least
chrome 21 // firefox 13 // edge 12 // opera 12 // safari 5.1"); var flag = false; apply_flag_cfg(); apply_fsearch_cfg(); function nav() { ebi('file' + fdom_ctr).click(); } ebi('u2btn').addEventListener('click', nav, false); function ondrag(ev) { ev.stopPropagation(); ev.preventDefault(); ev.dataTransfer.dropEffect = 'copy'; ev.dataTransfer.effectAllowed = 'copy'; } ebi('u2btn').addEventListener('dragover', ondrag, false); ebi('u2btn').addEventListener('dragenter', ondrag, false); function gotfile(ev) { ev.stopPropagation(); ev.preventDefault(); var files; var is_itemlist = false; if (ev.dataTransfer) { if (ev.dataTransfer.items) { files = ev.dataTransfer.items; // DataTransferItemList is_itemlist = true; } else files = ev.dataTransfer.files; // FileList } else files = ev.target.files; if (files.length == 0) return alert('no files selected??'); more_one_file(); var bad_files = []; var good_files = []; for (var a = 0; a < files.length; a++) { var fobj = files[a]; if (is_itemlist) { if (fobj.kind !== 'file') continue; fobj = fobj.getAsFile(); } try { if (fobj.size < 1) throw 1; } catch (ex) { bad_files.push(fobj.name); continue; } good_files.push(fobj); } if (bad_files.length > 0) { var msg = 'These {0} files (of {1} total) were skipped because they are empty:\n'.format(bad_files.length, files.length); for (var a = 0; a < bad_files.length; a++) msg += '-- ' + bad_files[a] + '\n'; if (files.length - bad_files.length <= 1 && /(android)/i.test(navigator.userAgent)) msg += '\nFirefox-Android has a bug which prevents selecting multiple files. Try selecting one file at a time. For more info, see firefox bug 1456557'; alert(msg); } var msg = ['upload these ' + good_files.length + ' files?']; for (var a = 0; a < good_files.length; a++) msg.push(good_files[a].name); if (ask_up && !fsearch && !confirm(msg.join('\n'))) return; for (var a = 0; a < good_files.length; a++) { var fobj = good_files[a]; var now = new Date().getTime(); var lmod = fobj.lastModified || now; var entry = { "n": parseInt(st.files.length.toString()), "t0": now, // TODO remove probably "fobj": fobj, "name": fobj.name, "size": fobj.size, "lmod": lmod / 1000, "purl": get_vpath(), "done": false, "hash": [] }; var skip = false; for (var b = 0; b < st.files.length; b++) if (entry.name == st.files[b].name && entry.size == st.files[b].size) skip = true; if (skip) continue; var tr = document.createElement('tr'); tr.innerHTML = 'hashing'.format(st.files.length); tr.getElementsByTagName('td')[0].innerHTML = fsearch ? entry.name : linksplit(esc(entry.purl + entry.name)).join(' '); ebi('u2tab').appendChild(tr); st.files.push(entry); st.todo.hash.push(entry); } } ebi('u2btn').addEventListener('drop', gotfile, false); function more_one_file() { fdom_ctr++; var elm = document.createElement('div') elm.innerHTML = ''.format(fdom_ctr); ebi('u2form').appendChild(elm); ebi('file' + fdom_ctr).addEventListener('change', gotfile, false); } more_one_file(); function u2cleanup(e) { ev(e); for (var a = 0; a < st.files.length; a++) { var t = st.files[a]; if (t.done && t.name) { var tr = ebi('f{0}p'.format(t.n)).parentNode; tr.parentNode.removeChild(tr); t.name = undefined; } } } ebi('u2cleanup').onclick = u2cleanup; ///// //// /// actuator // function handshakes_permitted() { var lim = multitask ? 1 : 0; return lim >= st.todo.upload.length + st.busy.upload.length; } function hashing_permitted() { if (multitask) { var ahead = st.bytes.hashed - st.bytes.uploaded; return ahead < 1024 * 1024 * 128; } return handshakes_permitted() && 0 == st.todo.handshake.length + st.busy.handshake.length; } var tasker = (function () { var mutex = false; var was_busy = false; function taskerd() { if (mutex) return; mutex = true; while (true) { if (false) { ebi('srv_info').innerHTML = new Date().getTime() + ", " + st.todo.hash.length + ", " + st.todo.handshake.length + ", " + st.todo.upload.length + ", " + st.busy.hash.length + ", " + st.busy.handshake.length + ", " + st.busy.upload.length; } var is_busy = 0 != st.todo.hash.length + st.todo.handshake.length + st.todo.upload.length + st.busy.hash.length + st.busy.handshake.length + st.busy.upload.length; if (was_busy != is_busy) { was_busy = is_busy; if (is_busy) window.addEventListener("beforeunload", warn_uploader_busy); else window.removeEventListener("beforeunload", warn_uploader_busy); } if (flag) { if (is_busy) { var now = new Date().getTime(); flag.take(now); if (!flag.ours) { setTimeout(taskerd, 100); mutex = false; return; } } else if (flag.ours) { flag.give(); } } var mou_ikkai = false; if (st.todo.handshake.length > 0 && st.busy.handshake.length == 0 && ( st.todo.handshake[0].t3 || ( handshakes_permitted() && st.busy.upload.length < parallel_uploads ) ) ) { exec_handshake(); mou_ikkai = true; } if (handshakes_permitted() && st.todo.handshake.length > 0 && st.busy.handshake.length == 0 && st.busy.upload.length < parallel_uploads) { exec_handshake(); mou_ikkai = true; } if (st.todo.upload.length > 0 && st.busy.upload.length < parallel_uploads) { exec_upload(); mou_ikkai = true; } if (hashing_permitted() && st.todo.hash.length > 0 && st.busy.hash.length == 0) { exec_hash(); mou_ikkai = true; } if (!mou_ikkai) { setTimeout(taskerd, 100); mutex = false; return; } } } taskerd(); return taskerd; })(); ///// //// /// hashing // // https://gist.github.com/jonleighton/958841 function buf2b64(arrayBuffer) { var base64 = ''; var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; var bytes = new Uint8Array(arrayBuffer); var byteLength = bytes.byteLength; var byteRemainder = byteLength % 3; var mainLength = byteLength - byteRemainder; var a, b, c, d; var chunk; for (var i = 0; i < mainLength; i = i + 3) { chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; // create 8*3=24bit segment then split into 6bit segments a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18 b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12 c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6 d = chunk & 63; // 63 = 2^6 - 1 // Convert the raw binary segments to the appropriate ASCII encoding base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]; } if (byteRemainder == 1) { chunk = bytes[mainLength]; a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2 b = (chunk & 3) << 4; // 3 = 2^2 - 1 (zero 4 LSB) base64 += encodings[a] + encodings[b];//+ '=='; } else if (byteRemainder == 2) { chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]; a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10 b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4 c = (chunk & 15) << 2; // 15 = 2^4 - 1 (zero 2 LSB) base64 += encodings[a] + encodings[b] + encodings[c];//+ '='; } return base64; } function get_chunksize(filesize) { var chunksize = 1024 * 1024; var stepsize = 512 * 1024; while (true) { for (var mul = 1; mul <= 2; mul++) { var nchunks = Math.ceil(filesize / chunksize); if (nchunks <= 256 || chunksize >= 32 * 1024 * 1024) return chunksize; chunksize += stepsize; stepsize *= mul; } } } function test_filereader_speed(segm_err) { var f = st.todo.hash[0].fobj, sz = Math.min(2, f.size), reader = new FileReader(), t0, ctr = 0; var segm_next = function () { var t = new Date().getTime(), td = t - t0; if (++ctr > 2) { need_filereader_cache = td > 50; st.busy.hash.pop(); return; } t0 = t; reader.onload = segm_next; reader.onerror = segm_err; reader.readAsArrayBuffer( bobslice.call(f, 0, sz)); }; segm_next(); } function ensure_rendered(func) { var hidden = false; var keys = ['hidden', 'msHidden', 'webkitHidden']; for (var a = 0; a < keys.length; a++) if (typeof document[keys[a]] !== "undefined") hidden = document[keys[a]]; if (hidden) return func(); window.requestAnimationFrame(func); } function exec_hash() { if (need_filereader_cache === undefined) { st.busy.hash.push(1); return test_filereader_speed(segm_err); } var t = st.todo.hash.shift(); st.busy.hash.push(t); st.bytes.hashed += t.size; t.bytes_uploaded = 0; t.t1 = new Date().getTime(); var nchunk = 0; var chunksize = get_chunksize(t.size); var nchunks = Math.ceil(t.size / chunksize); // android-chrome has 180ms latency on FileReader calls, // detect this and do 32MB at a time var cache_buf = undefined, cache_ofs = 0, subchunks = 2; while (subchunks * chunksize <= 32 * 1024 * 1024) subchunks++; subchunks--; if (!need_filereader_cache) subchunks = 1; var pb_html = ''; var pb_perc = 99.9 / nchunks; for (var a = 0; a < nchunks; a++) pb_html += '
'.format( t.n, a, pb_perc); ebi('f{0}p'.format(t.n)).innerHTML = pb_html; var reader = new FileReader(); var segm_next = function () { if (cache_buf) { return hash_calc(); } reader.onload = segm_load; reader.onerror = segm_err; var car = nchunk * chunksize; var cdr = car + chunksize * subchunks; if (cdr >= t.size) cdr = t.size; reader.readAsArrayBuffer( bobslice.call(t.fobj, car, cdr)); prog(t.n, nchunk, col_hashing); }; var segm_load = function (ev) { cache_buf = ev.target.result; cache_ofs = 0; hash_calc(); }; var hash_calc = function () { var buf = cache_buf; if (chunksize >= buf.byteLength) cache_buf = undefined; else { var ofs = cache_ofs; var ofs2 = ofs + Math.min(chunksize, cache_buf.byteLength - cache_ofs); cache_ofs = ofs2; buf = new Uint8Array(cache_buf).subarray(ofs, ofs2); if (ofs2 >= cache_buf.byteLength) cache_buf = undefined; } var func = function () { if (have_crypto) crypto.subtle.digest('SHA-512', buf).then(hash_done); else { var hasher = new asmCrypto.Sha512(); hasher.process(new Uint8Array(buf)); hasher.finish(); hash_done(hasher.result); } }; if (cache_buf) ensure_rendered(func); else func(); }; var hash_done = function (hashbuf) { var hslice = new Uint8Array(hashbuf).subarray(0, 32); var b64str = buf2b64(hslice).replace(/=$/, ''); t.hash.push(b64str); prog(t.n, nchunk, col_hashed); if (++nchunk < nchunks) { prog(t.n, nchunk, col_hashing); return segm_next(); } t.t2 = new Date().getTime(); if (t.n == 0 && window.location.hash == '#dbg') { var spd = (t.size / ((t.t2 - t.t1) / 1000.)) / (1024 * 1024.); alert('{0} ms, {1} MB/s\n'.format(t.t2 - t.t1, spd.toFixed(3)) + t.hash.join('\n')); } ebi('f{0}t'.format(t.n)).innerHTML = 'connecting'; st.busy.hash.splice(st.busy.hash.indexOf(t), 1); st.todo.handshake.push(t); }; var segm_err = function () { alert('y o u b r o k e i t\n\n(was that a folder? just files please)'); }; segm_next(); } ///// //// /// handshake // function exec_handshake() { var t = st.todo.handshake.shift(); st.busy.handshake.push(t); var xhr = new XMLHttpRequest(); xhr.onload = function (ev) { if (xhr.status == 200) { var response = JSON.parse(xhr.responseText); if (!response.name) { var msg = ''; var smsg = ''; if (!response || !response.length) { msg = 'not found on server'; smsg = '404'; } else { smsg = 'found'; var hit = response[0], msg = linksplit(hit.rp).join(''), tr = unix2iso(hit.ts), tu = unix2iso(t.lmod), diff = parseInt(t.lmod) - parseInt(hit.ts), cdiff = (Math.abs(diff) <= 2) ? '3c0' : 'f0b', sdiff = 'diff ' + diff; msg += '
' + tr + ' (srv), ' + tu + ' (You), ' + sdiff + '
'; } ebi('f{0}p'.format(t.n)).innerHTML = msg; ebi('f{0}t'.format(t.n)).innerHTML = smsg; st.busy.handshake.splice(st.busy.handshake.indexOf(t), 1); st.bytes.uploaded += t.size; tasker(); return; } if (response.name !== t.name) { // file exists; server renamed us t.name = response.name; ebi('f{0}n'.format(t.n)).innerHTML = linksplit(esc(t.purl + t.name)).join(' '); } t.postlist = []; t.wark = response.wark; var missing = response.hash; for (var a = 0; a < missing.length; a++) { var idx = t.hash.indexOf(missing[a]); if (idx < 0) return alert('wtf negative index for hash "{0}" in task:\n{1}'.format( missing[a], JSON.stringify(t))); t.postlist.push(idx); } for (var a = 0; a < t.hash.length; a++) prog(t.n, a, (t.postlist.indexOf(a) == -1) ? col_uploaded : col_hashed); var done = true; var msg = '🎷🐛'; if (t.postlist.length > 0) { for (var a = 0; a < t.postlist.length; a++) st.todo.upload.push({ 'nfile': t.n, 'npart': t.postlist[a] }); msg = 'uploading'; done = false; } ebi('f{0}t'.format(t.n)).innerHTML = msg; st.busy.handshake.splice(st.busy.handshake.indexOf(t), 1); if (done) { t.done = true; st.bytes.uploaded += t.size - t.bytes_uploaded; var spd1 = (t.size / ((t.t2 - t.t1) / 1000.)) / (1024 * 1024.); var spd2 = (t.size / ((t.t3 - t.t2) / 1000.)) / (1024 * 1024.); ebi('f{0}p'.format(t.n)).innerHTML = 'hash {0}, up {1} MB/s'.format( spd1.toFixed(2), spd2.toFixed(2)); } else t.t3 = undefined; tasker(); } else { var err = ""; var rsp = (xhr.responseText + ''); if (rsp.indexOf('partial upload exists') !== -1 || rsp.indexOf('file already exists') !== -1) { err = rsp; var ofs = err.lastIndexOf(' : '); if (ofs > 0) err = err.slice(0, ofs); ofs = err.indexOf('\n/'); if (ofs !== -1) { err = err.slice(0, ofs + 1) + linksplit(err.slice(ofs + 2, -1)).join(' '); } } if (err != "") { ebi('f{0}t'.format(t.n)).innerHTML = "ERROR"; ebi('f{0}p'.format(t.n)).innerHTML = err; st.busy.handshake.splice(st.busy.handshake.indexOf(t), 1); tasker(); return; } alert("server broke (error {0}):\n\"{1}\"\n".format( xhr.status, (xhr.response && xhr.response.err) || (xhr.responseText && xhr.responseText) || "no further information")); } }; var req = { "name": t.name, "size": t.size, "lmod": t.lmod, "hash": t.hash }; if (fsearch) req.srch = 1; xhr.open('POST', t.purl + 'handshake.php', true); xhr.responseType = 'text'; xhr.send(JSON.stringify(req)); } ///// //// /// upload // function exec_upload() { var upt = st.todo.upload.shift(); st.busy.upload.push(upt); var npart = upt.npart; var t = st.files[upt.nfile]; prog(t.n, npart, col_uploading); var chunksize = get_chunksize(t.size); var car = npart * chunksize; var cdr = car + chunksize; if (cdr >= t.size) cdr = t.size; var reader = new FileReader(); reader.onerror = function () { alert('y o u b r o k e i t\n\n(was that a folder? just files please)'); }; reader.onload = function (ev) { var xhr = new XMLHttpRequest(); xhr.upload.onprogress = function (xev) { var perc = xev.loaded / (cdr - car) * 100; prog(t.n, npart, '', perc); }; xhr.onload = function (xev) { if (xhr.status == 200) { prog(t.n, npart, col_uploaded); st.bytes.uploaded += cdr - car; t.bytes_uploaded += cdr - car; st.busy.upload.splice(st.busy.upload.indexOf(upt), 1); t.postlist.splice(t.postlist.indexOf(npart), 1); if (t.postlist.length == 0) { t.t3 = new Date().getTime(); ebi('f{0}t'.format(t.n)).innerHTML = 'verifying'; st.todo.handshake.unshift(t); } tasker(); } else alert("server broke (error {0}):\n\"{1}\"\n".format( xhr.status, (xhr.response && xhr.response.err) || (xhr.responseText && xhr.responseText) || "no further information")); }; xhr.open('POST', t.purl + 'chunkpit.php', true); //xhr.setRequestHeader("X-Up2k-Hash", t.hash[npart].substr(1) + "x"); xhr.setRequestHeader("X-Up2k-Hash", t.hash[npart]); xhr.setRequestHeader("X-Up2k-Wark", t.wark); xhr.setRequestHeader('Content-Type', 'application/octet-stream'); xhr.overrideMimeType('Content-Type', 'application/octet-stream'); xhr.responseType = 'text'; xhr.send(ev.target.result); }; reader.readAsArrayBuffer(bobslice.call(t.fobj, car, cdr)); } ///// //// /// progress bar // function prog(nfile, nchunk, color, percent) { var n1 = ebi('f{0}p{1}'.format(nfile, nchunk)); var n2 = n1.getElementsByTagName('div')[0]; if (percent === undefined) { n1.style.background = color; n2.style.display = 'none'; } else { n2.style.width = percent + '%'; n2.style.display = 'block'; } } ///// //// /// config ui // function onresize(ev) { var bar = ebi('ops'), wpx = innerWidth, fpx = parseInt(getComputedStyle(bar)['font-size']), wem = wpx * 1.0 / fpx, wide = wem > 54, parent = ebi(wide ? 'u2btn_cw' : 'u2btn_ct'), btn = ebi('u2btn'); //console.log([wpx, fpx, wem]); if (btn.parentNode !== parent) { parent.appendChild(btn); ebi('u2conf').setAttribute('class', wide ? 'has_btn' : ''); } } window.onresize = onresize; onresize(); function desc_show(ev) { var msg = this.getAttribute('alt'); msg = msg.replace(/\$N/g, "
"); var cdesc = ebi('u2cdesc'); cdesc.innerHTML = msg; cdesc.setAttribute('class', 'show'); } function desc_hide(ev) { ebi('u2cdesc').setAttribute('class', ''); } var o = document.querySelectorAll('#u2conf *[alt]'); for (var a = o.length - 1; a >= 0; a--) { o[a].parentNode.getElementsByTagName('input')[0].setAttribute('alt', o[a].getAttribute('alt')); } var o = document.querySelectorAll('#u2conf *[alt]'); for (var a = 0; a < o.length; a++) { o[a].onfocus = desc_show; o[a].onblur = desc_hide; o[a].onmouseenter = desc_show; o[a].onmouseleave = desc_hide; } function bumpthread(dir) { try { dir.stopPropagation(); dir.preventDefault(); } catch (ex) { } var obj = ebi('nthread'); if (dir.target) { obj.style.background = '#922'; var v = Math.floor(parseInt(obj.value)); if (v < 1 || v > 8 || v !== v) return; parallel_uploads = v; localStorage.setItem('nthread', v); obj.style.background = '#444'; return; } parallel_uploads += dir; if (parallel_uploads < 1) parallel_uploads = 1; if (parallel_uploads > 8) parallel_uploads = 8; obj.value = parallel_uploads; bumpthread({ "target": 1 }) } function tgl_multitask() { multitask = !multitask; bcfg_set('multitask', multitask); } function tgl_ask_up() { ask_up = !ask_up; bcfg_set('ask_up', ask_up); } function tgl_fsearch() { fsearch = !fsearch; bcfg_set('fsearch', fsearch); apply_fsearch_cfg(); } function apply_fsearch_cfg() { try { var fun = fsearch ? 'add' : 'remove'; ebi('op_up2k').classList[fun]('srch'); } catch (ex) { } } function set_fsearch() { if (!fsearch) tgl_fsearch(); } function tgl_flag_en() { flag_en = !flag_en; bcfg_set('flag_en', flag_en); apply_flag_cfg(); } function apply_flag_cfg() { if (flag_en && !flag) { try { flag = up2k_flagbus(); } catch (ex) { console.log("flag error: " + ex.toString()); tgl_flag_en(); } } else if (!flag_en && flag) { flag.ch.close(); flag = false; } } function nop(ev) { ev.preventDefault(); this.click(); } ebi('nthread_add').onclick = function (ev) { ev.preventDefault(); bumpthread(1); }; ebi('nthread_sub').onclick = function (ev) { ev.preventDefault(); bumpthread(-1); }; ebi('nthread').addEventListener('input', bumpthread, false); ebi('multitask').addEventListener('click', tgl_multitask, false); ebi('ask_up').addEventListener('click', tgl_ask_up, false); ebi('flag_en').addEventListener('click', tgl_flag_en, false); var o = ebi('fsearch'); if (o) o.addEventListener('click', tgl_fsearch, false); var nodes = ebi('u2conf').getElementsByTagName('a'); for (var a = nodes.length - 1; a >= 0; a--) nodes[a].addEventListener('touchend', nop, false); var perms = document.body.getAttribute('perms'); if (perms && perms.indexOf('write') === -1) set_fsearch(); bumpthread({ "target": 1 }) return { "init_deps": init_deps, "set_fsearch": set_fsearch } } function warn_uploader_busy(e) { e.preventDefault(); e.returnValue = ''; return "upload in progress, click abort and use the file-tree to navigate instead"; } if (document.querySelector('#op_up2k.act')) goto_up2k();