mirror of
https://github.com/9001/copyparty.git
synced 2025-10-25 00:53:47 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04f1b2cf3a | ||
|
|
c06d928bb5 | ||
|
|
ab09927e7b | ||
|
|
779437db67 | ||
|
|
28cbdb652e | ||
|
|
2b2415a7d8 | ||
|
|
746a8208aa | ||
|
|
a2a041a98a | ||
|
|
10b436e449 | ||
|
|
4d62b34786 | ||
|
|
0546210687 | ||
|
|
f8c11faada | ||
|
|
16d6e9be1f |
@@ -111,6 +111,8 @@ the browser has the following hotkeys
|
||||
* `I/K` prev/next folder
|
||||
* `P` parent folder
|
||||
|
||||
you can link a particular timestamp in an audio file by adding it to the URL, such as `&20` / `&20s` / `&1m20` / `&1:20` after the `.../#af-c8960dab`
|
||||
|
||||
|
||||
## zip downloads
|
||||
|
||||
@@ -339,7 +341,6 @@ in the `scripts` folder:
|
||||
|
||||
roughly sorted by priority
|
||||
|
||||
* audio link with timestamp
|
||||
* separate sqlite table per tag
|
||||
* audio fingerprinting
|
||||
* readme.md as epilogue
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# coding: utf-8
|
||||
|
||||
VERSION = (0, 10, 9)
|
||||
VERSION = (0, 10, 13)
|
||||
CODENAME = "zip it"
|
||||
BUILD_DT = (2021, 4, 17)
|
||||
BUILD_DT = (2021, 4, 20)
|
||||
|
||||
S_VERSION = ".".join(map(str, VERSION))
|
||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||
|
||||
@@ -101,17 +101,18 @@ class Up2k(object):
|
||||
thr.daemon = True
|
||||
thr.start()
|
||||
|
||||
thr = threading.Thread(target=self._tagger)
|
||||
thr.daemon = True
|
||||
thr.start()
|
||||
|
||||
thr = threading.Thread(target=self._hasher)
|
||||
thr.daemon = True
|
||||
thr.start()
|
||||
|
||||
thr = threading.Thread(target=self._run_all_mtp)
|
||||
thr.daemon = True
|
||||
thr.start()
|
||||
if self.mtag:
|
||||
thr = threading.Thread(target=self._tagger)
|
||||
thr.daemon = True
|
||||
thr.start()
|
||||
|
||||
thr = threading.Thread(target=self._run_all_mtp)
|
||||
thr.daemon = True
|
||||
thr.start()
|
||||
|
||||
def log(self, msg, c=0):
|
||||
self.log_func("up2k", msg + "\033[K", c)
|
||||
|
||||
@@ -284,7 +284,7 @@ a, #files tbody div a:last-child {
|
||||
line-height: 1em;
|
||||
}
|
||||
#wtoggle.sel {
|
||||
width: 6em;
|
||||
width: 6.4em;
|
||||
}
|
||||
#wtoggle.sel #wzip {
|
||||
display: inline-block;
|
||||
@@ -685,3 +685,173 @@ input[type="checkbox"]:checked+label {
|
||||
font-family: monospace, monospace;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
html.light {
|
||||
color: #333;
|
||||
background: #eee;
|
||||
text-shadow: none;
|
||||
}
|
||||
html.light #ops,
|
||||
html.light .opbox,
|
||||
html.light #srch_form {
|
||||
background: #f7f7f7;
|
||||
box-shadow: 0 0 .3em #ddd;
|
||||
border-color: #f7f7f7;
|
||||
}
|
||||
html.light #ops a.act {
|
||||
box-shadow: 0 .2em .2em #ccc;
|
||||
background: #f7f7f7;
|
||||
border-color: #07a;
|
||||
padding-top: .4em;
|
||||
}
|
||||
html.light #op_cfg h3 {
|
||||
border-color: #ccc;
|
||||
}
|
||||
html.light .tglbtn,
|
||||
html.light #tree > a + a {
|
||||
color: #666;
|
||||
background: #ddd;
|
||||
box-shadow: none;
|
||||
}
|
||||
html.light .tglbtn:hover,
|
||||
html.light #tree > a + a:hover {
|
||||
background: #caf;
|
||||
}
|
||||
html.light .tglbtn.on,
|
||||
html.light #tree > a + a.on {
|
||||
background: #4a0;
|
||||
color: #fff;
|
||||
}
|
||||
html.light #srv_info {
|
||||
color: #c83;
|
||||
text-shadow: 1px 1px 0 #fff;
|
||||
}
|
||||
html.light #srv_info span {
|
||||
color: #000;
|
||||
}
|
||||
html.light #treeul a+a {
|
||||
background: inherit;
|
||||
color: #06a;
|
||||
}
|
||||
html.light #treeul a.hl {
|
||||
background: #07a;
|
||||
color: #fff;
|
||||
}
|
||||
html.light #tree li {
|
||||
border-color: #ddd #fff #f7f7f7 #fff;
|
||||
}
|
||||
html.light #tree ul {
|
||||
border-color: #ccc;
|
||||
}
|
||||
html.light a,
|
||||
html.light #ops a,
|
||||
html.light #files tbody div a:last-child {
|
||||
color: #06a;
|
||||
}
|
||||
html.light #files tbody {
|
||||
background: #f7f7f7;
|
||||
}
|
||||
html.light #files {
|
||||
box-shadow: 0 0 .3em #ccc;
|
||||
}
|
||||
html.light #files thead th {
|
||||
background: #eee;
|
||||
}
|
||||
html.light #files tr+tr td {
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
html.light #files td {
|
||||
border-bottom: 1px solid #f7f7f7;
|
||||
}
|
||||
html.light #files tbody tr:last-child td {
|
||||
border-bottom: .2em solid #ccc;
|
||||
}
|
||||
html.light #files td:nth-child(2n) {
|
||||
color: #d38;
|
||||
}
|
||||
html.light #files tr:hover td {
|
||||
background: #fff;
|
||||
}
|
||||
html.light #files tbody a.play {
|
||||
color: #c0f;
|
||||
}
|
||||
html.light tr.play td {
|
||||
background: #fc5;
|
||||
}
|
||||
html.light tr.play a {
|
||||
color: #406;
|
||||
}
|
||||
html.light #files > thead > tr > th.min span {
|
||||
background: linear-gradient(90deg, rgba(68,68,68,0), rgba(68,68,68,0.2) 70%, rgba(68,68,68,0.5));
|
||||
}
|
||||
html.light #blocked {
|
||||
background: #eee;
|
||||
}
|
||||
html.light #blk_play a,
|
||||
html.light #blk_abrt a {
|
||||
background: #fff;
|
||||
box-shadow: 0 .2em .4em #ddd;
|
||||
}
|
||||
html.light #widget a {
|
||||
color: #fc5;
|
||||
}
|
||||
html.light #files tr.sel:hover td {
|
||||
background: #c37;
|
||||
}
|
||||
html.light #files tr.sel td {
|
||||
color: #fff;
|
||||
}
|
||||
html.light #files tr.sel a {
|
||||
color: #fff;
|
||||
}
|
||||
html.light input[type="checkbox"] + label {
|
||||
color: #333;
|
||||
}
|
||||
html.light .opview input[type="text"] {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
box-shadow: 0 0 2px #888;
|
||||
border-color: #38d;
|
||||
}
|
||||
html.light #ops:hover #opdesc {
|
||||
background: #fff;
|
||||
box-shadow: 0 .3em 1em #ccc;
|
||||
}
|
||||
html.light #opdesc code {
|
||||
background: #060;
|
||||
color: #fff;
|
||||
}
|
||||
html.light #u2tab a>span,
|
||||
html.light #files td div span {
|
||||
color: #000;
|
||||
}
|
||||
html.light #path {
|
||||
background: #f7f7f7;
|
||||
text-shadow: none;
|
||||
box-shadow: 0 0 .3em #bbb;
|
||||
}
|
||||
html.light #path a {
|
||||
color: #333;
|
||||
}
|
||||
html.light #path a:not(:last-child)::after {
|
||||
border-color: #ccc;
|
||||
background: none;
|
||||
border-width: .1em .1em 0 0;
|
||||
margin: -.2em .3em -.2em -.3em;
|
||||
}
|
||||
html.light #path a:hover {
|
||||
background: none;
|
||||
color: #60a;
|
||||
}
|
||||
html.light #files tbody div a {
|
||||
color: #d38;
|
||||
}
|
||||
html.light #files a:hover,
|
||||
html.light #files tr.sel a:hover {
|
||||
color: #000;
|
||||
background: #fff;
|
||||
}
|
||||
@@ -39,14 +39,17 @@
|
||||
{%- include 'upload.html' %}
|
||||
|
||||
<div id="op_cfg" class="opview opbox">
|
||||
<h3>key notation</h3>
|
||||
<div id="key_notation"></div>
|
||||
<h3>switches</h3>
|
||||
<div>
|
||||
<a id="tooltips" class="tglbtn" href="#">tooltips</a>
|
||||
<a id="lightmode" class="tglbtn" href="#">lightmode</a>
|
||||
</div>
|
||||
{%- if have_zip %}
|
||||
<h3>folder download</h3>
|
||||
<div id="arc_fmt"></div>
|
||||
{%- endif %}
|
||||
<h3>tooltips</h3>
|
||||
<div><a id="tooltips" class="tglbtn" href="#">enable</a></div>
|
||||
<h3>key notation</h3>
|
||||
<div id="key_notation"></div>
|
||||
</div>
|
||||
|
||||
<h1 id="path">
|
||||
|
||||
@@ -314,8 +314,8 @@ function seek_au_sec(seek) {
|
||||
|
||||
mp.au.currentTime = seek;
|
||||
|
||||
// ogv.js breaks on .play() during playback
|
||||
if (mp.au === mp.au_native)
|
||||
// hack: ogv.js breaks on .play() during playback
|
||||
mp.au.play();
|
||||
}
|
||||
|
||||
@@ -427,7 +427,7 @@ catch (ex) { }
|
||||
|
||||
|
||||
// plays the tid'th audio file on the page
|
||||
function play(tid, call_depth) {
|
||||
function play(tid, seek, call_depth) {
|
||||
if (mp.order.length == 0)
|
||||
return alert('no audio found wait what');
|
||||
|
||||
@@ -449,7 +449,7 @@ function play(tid, call_depth) {
|
||||
}
|
||||
|
||||
// ogv.js breaks on .play() unless directly user-triggered
|
||||
var hack_attempt_play = true;
|
||||
var attempt_play = true;
|
||||
|
||||
var url = mp.tracks[tid];
|
||||
if (need_ogv && /\.(ogg|opus)$/i.test(url)) {
|
||||
@@ -458,7 +458,7 @@ function play(tid, call_depth) {
|
||||
}
|
||||
else if (window['OGVPlayer']) {
|
||||
mp.au = mp.au_ogvjs = new OGVPlayer();
|
||||
hack_attempt_play = false;
|
||||
attempt_play = false;
|
||||
mp.au.addEventListener('error', evau_error, true);
|
||||
mp.au.addEventListener('progress', pbar.drawpos, false);
|
||||
widget.open();
|
||||
@@ -470,7 +470,7 @@ function play(tid, call_depth) {
|
||||
show_modal('<h1>loading ogv.js</h1><h2>thanks apple</h2>');
|
||||
|
||||
import_js('/.cpr/deps/ogv.js', function () {
|
||||
play(tid, 1);
|
||||
play(tid, seek, 1);
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -498,21 +498,26 @@ function play(tid, call_depth) {
|
||||
ebi(oid).parentElement.parentElement.className += ' play';
|
||||
|
||||
try {
|
||||
if (hack_attempt_play)
|
||||
if (attempt_play)
|
||||
mp.au.play();
|
||||
|
||||
if (mp.au.paused)
|
||||
autoplay_blocked();
|
||||
autoplay_blocked(seek);
|
||||
else if (seek) {
|
||||
seek_au_sec(seek);
|
||||
}
|
||||
|
||||
var o = ebi(oid);
|
||||
o.setAttribute('id', 'thx_js');
|
||||
if (window.history && history.replaceState) {
|
||||
hist_replace(document.location.pathname + '#' + oid);
|
||||
if (!seek) {
|
||||
var o = ebi(oid);
|
||||
o.setAttribute('id', 'thx_js');
|
||||
if (window.history && history.replaceState) {
|
||||
hist_replace(document.location.pathname + '#' + oid);
|
||||
}
|
||||
else {
|
||||
document.location.hash = oid;
|
||||
}
|
||||
o.setAttribute('id', oid);
|
||||
}
|
||||
else {
|
||||
document.location.hash = oid;
|
||||
}
|
||||
o.setAttribute('id', oid);
|
||||
|
||||
pbar.drawbuf();
|
||||
return true;
|
||||
@@ -576,7 +581,7 @@ function unblocked() {
|
||||
|
||||
|
||||
// show ui to manually start playback of a linked song
|
||||
function autoplay_blocked() {
|
||||
function autoplay_blocked(seek) {
|
||||
show_modal(
|
||||
'<div id="blk_play"><a href="#" id="blk_go"></a></div>' +
|
||||
'<div id="blk_abrt"><a href="#" id="blk_na">Cancel<br />(show file list)</a></div>');
|
||||
@@ -592,6 +597,8 @@ function autoplay_blocked() {
|
||||
if (e) e.preventDefault();
|
||||
unblocked();
|
||||
mp.au.play();
|
||||
if (seek)
|
||||
seek_au_sec(seek);
|
||||
};
|
||||
na.onclick = unblocked;
|
||||
}
|
||||
@@ -600,8 +607,20 @@ function autoplay_blocked() {
|
||||
// autoplay linked track
|
||||
(function () {
|
||||
var v = location.hash;
|
||||
if (v && v.length == 12 && v.indexOf('#af-') === 0)
|
||||
play(v.slice(2));
|
||||
if (v && v.indexOf('#af-') === 0) {
|
||||
var id = v.slice(2).split('&');
|
||||
if (id[0].length != 10)
|
||||
return;
|
||||
|
||||
if (id.length == 1)
|
||||
return play(id[0]);
|
||||
|
||||
var m = /^[Tt=0]*([0-9]+[Mm:])?0*([0-9]+)[Ss]?$/.exec(id[1]);
|
||||
if (!m)
|
||||
return play(id[0]);
|
||||
|
||||
return play(id[0], parseInt(m[1] || 0) * 60 + parseInt(m[2] || 0));
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
@@ -1549,8 +1568,11 @@ function addcrc() {
|
||||
ebi('unsearch') ? 'div>a:last-child' : 'a'));
|
||||
|
||||
for (var a = 0, aa = links.length; a < aa; a++)
|
||||
if (!links[a].getAttribute('id'))
|
||||
links[a].setAttribute('id', 'f-' + crc32(links[a].textContent || links[a].innerText));
|
||||
if (!links[a].getAttribute('id')) {
|
||||
var crc = crc32(links[a].textContent || links[a].innerText);
|
||||
crc = ('00000000' + crc).slice(-8);
|
||||
links[a].setAttribute('id', 'f-' + crc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1577,6 +1599,24 @@ function addcrc() {
|
||||
})();
|
||||
|
||||
|
||||
(function () {
|
||||
var light = bcfg_get('lightmode', false);
|
||||
|
||||
function freshen() {
|
||||
document.documentElement.setAttribute("class", light ? "light" : "");
|
||||
}
|
||||
|
||||
ebi('lightmode').onclick = function (e) {
|
||||
ev(e);
|
||||
light = !light;
|
||||
bcfg_set('lightmode', light);
|
||||
freshen();
|
||||
};
|
||||
|
||||
freshen();
|
||||
})();
|
||||
|
||||
|
||||
var arcfmt = (function () {
|
||||
if (!ebi('arc_fmt'))
|
||||
return { "render": function () { } };
|
||||
|
||||
@@ -138,10 +138,10 @@ var md_opt = {
|
||||
document.documentElement.setAttribute("class", dark ? "dark" : "");
|
||||
btn.innerHTML = "go " + (dark ? "light" : "dark");
|
||||
if (window.localStorage)
|
||||
localStorage.setItem('darkmode', dark ? 1 : 0);
|
||||
localStorage.setItem('lightmode', dark ? 0 : 1);
|
||||
};
|
||||
btn.onclick = toggle;
|
||||
if (window.localStorage && localStorage.getItem('darkmode') == 1)
|
||||
if (window.localStorage && localStorage.getItem('lightmode') != 1)
|
||||
toggle();
|
||||
})();
|
||||
|
||||
|
||||
@@ -31,12 +31,12 @@ var md_opt = {
|
||||
|
||||
var lightswitch = (function () {
|
||||
var fun = function () {
|
||||
var dark = !!!document.documentElement.getAttribute("class");
|
||||
var dark = !document.documentElement.getAttribute("class");
|
||||
document.documentElement.setAttribute("class", dark ? "dark" : "");
|
||||
if (window.localStorage)
|
||||
localStorage.setItem('darkmode', dark ? 1 : 0);
|
||||
localStorage.setItem('lightmode', dark ? 0 : 1);
|
||||
};
|
||||
if (window.localStorage && localStorage.getItem('darkmode') == 1)
|
||||
if (window.localStorage && localStorage.getItem('lightmode') != 1)
|
||||
fun();
|
||||
|
||||
return fun;
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
</div>
|
||||
<script>
|
||||
|
||||
if (window.localStorage && localStorage.getItem('darkmode') == 1)
|
||||
if (window.localStorage && localStorage.getItem('lightmode') != 1)
|
||||
document.documentElement.setAttribute("class", "dark");
|
||||
|
||||
</script>
|
||||
|
||||
@@ -141,7 +141,7 @@ function U2pvis(act, btns) {
|
||||
this.tail = -1;
|
||||
this.wsz = 3;
|
||||
|
||||
this.addfile = function (entry) {
|
||||
this.addfile = function (entry, sz) {
|
||||
this.tab.push({
|
||||
"hn": entry[0],
|
||||
"ht": entry[1],
|
||||
@@ -149,8 +149,10 @@ function U2pvis(act, btns) {
|
||||
"in": 'q',
|
||||
"nh": 0, //hashed
|
||||
"nd": 0, //done
|
||||
"pa": [], //percents
|
||||
"pb": [] //active-list
|
||||
"cb": [], // bytes done in chunk
|
||||
"bt": sz, // bytes total
|
||||
"bd": 0, // bytes done
|
||||
"bd0": 0 // upload start
|
||||
});
|
||||
this.ctr["q"]++;
|
||||
this.drawcard("q");
|
||||
@@ -172,6 +174,9 @@ function U2pvis(act, btns) {
|
||||
this.seth = function (nfile, field, html) {
|
||||
var fo = this.tab[nfile];
|
||||
field = ['hn', 'ht', 'hp'][field];
|
||||
if (fo[field] === html)
|
||||
return;
|
||||
|
||||
fo[field] = html;
|
||||
if (!this.is_act(fo.in))
|
||||
return;
|
||||
@@ -184,28 +189,39 @@ function U2pvis(act, btns) {
|
||||
}
|
||||
};
|
||||
|
||||
this.setab = function (nfile, blocks) {
|
||||
this.setab = function (nfile, nblocks) {
|
||||
var t = [];
|
||||
for (var a = 0; a < blocks; a++)
|
||||
for (var a = 0; a < nblocks; a++)
|
||||
t.push(0);
|
||||
|
||||
this.tab[nfile].pa = t;
|
||||
this.tab[nfile].cb = t;
|
||||
};
|
||||
|
||||
this.perc = function (n, t, e, sz, t0) {
|
||||
var p = (n + e) * 100.0 / t,
|
||||
td = new Date().getTime() - t0,
|
||||
pp = (td / 1000) / p,
|
||||
spd = (sz / 100) / pp,
|
||||
eta = pp * (100 - p);
|
||||
this.setat = function (nfile, blocktab) {
|
||||
this.tab[nfile].cb = blocktab;
|
||||
|
||||
var bd = 0;
|
||||
for (var a = 0; a < blocktab.length; a++)
|
||||
bd += blocktab[a];
|
||||
|
||||
this.tab[nfile].bd = bd;
|
||||
this.tab[nfile].bd0 = bd;
|
||||
};
|
||||
|
||||
this.perc = function (bd, bd0, sz, t0) {
|
||||
var td = new Date().getTime() - t0,
|
||||
p = bd * 100.0 / sz,
|
||||
nb = bd - bd0,
|
||||
spd = nb / (td / 1000),
|
||||
eta = (sz - bd) / spd;
|
||||
|
||||
return [p, s2ms(eta), spd / (1024 * 1024)];
|
||||
};
|
||||
|
||||
this.hashed = function (fobj) {
|
||||
var fo = this.tab[fobj.n];
|
||||
fo.nh++;
|
||||
var p = this.perc(fo.nh, fo.pa.length, 0, fobj.size, fobj.t1);
|
||||
var nb = fo.bt * (++fo.nh / fo.cb.length);
|
||||
var p = this.perc(nb, 0, fobj.size, fobj.t1);
|
||||
fo.hp = '{0}%, {1}, {2} MB/s'.format(
|
||||
p[0].toFixed(2), p[1], p[2].toFixed(2)
|
||||
);
|
||||
@@ -216,29 +232,16 @@ function U2pvis(act, btns) {
|
||||
obj.innerHTML = fo.hp;
|
||||
obj.style.color = '#fff';
|
||||
var o1 = p[0] - 2, o2 = p[0] - 0.1, o3 = p[0];
|
||||
obj.style.background = 'linear-gradient(90deg, #025, #06a ' + o1 + '%, #08d ' + o2 + '%, #333 ' + o3 + '%)';
|
||||
obj.style.background = 'linear-gradient(90deg, #025, #06a ' + o1 + '%, #09d ' + o2 + '%, #333 ' + o3 + '%, #333 99%, #777)';
|
||||
};
|
||||
|
||||
this.prog = function (fobj, nchunk, percent) {
|
||||
var fo = this.tab[fobj.n], pb = fo.pb;
|
||||
var i = pb.indexOf(nchunk);
|
||||
fo.pa[nchunk] = percent;
|
||||
if (percent == 101) {
|
||||
fo.nd++;
|
||||
if (i >= 0)
|
||||
pb.splice(i);
|
||||
}
|
||||
else if (i == -1) {
|
||||
pb.push(nchunk);
|
||||
}
|
||||
this.prog = function (fobj, nchunk, cbd) {
|
||||
var fo = this.tab[fobj.n];
|
||||
var delta = cbd - fo.cb[nchunk];
|
||||
fo.cb[nchunk] = cbd;
|
||||
fo.bd += delta;
|
||||
|
||||
var extra = 0;
|
||||
for (var a = 0; a < pb.length; a++)
|
||||
extra += fo.pa[a];
|
||||
|
||||
extra /= fo.pa.length;
|
||||
|
||||
var p = this.perc(fo.nd, fo.pa.length, extra, fobj.size, fobj.t3);
|
||||
var p = this.perc(fo.bd, fo.bd0, fo.bt, fobj.t3);
|
||||
fo.hp = '{0}%, {1}, {2} MB/s'.format(
|
||||
p[0].toFixed(2), p[1], p[2].toFixed(2)
|
||||
);
|
||||
@@ -250,7 +253,7 @@ function U2pvis(act, btns) {
|
||||
obj.innerHTML = fo.hp;
|
||||
obj.style.color = '#fff';
|
||||
var o1 = p[0] - 2, o2 = p[0] - 0.1, o3 = p[0];
|
||||
obj.style.background = 'linear-gradient(90deg, #050, #270 ' + o1 + '%, #4b0 ' + o2 + '%, #333 ' + o3 + '%)';
|
||||
obj.style.background = 'linear-gradient(90deg, #050, #270 ' + o1 + '%, #4b0 ' + o2 + '%, #333 ' + o3 + '%, #333 99%, #777)';
|
||||
};
|
||||
|
||||
this.move = function (nfile, newcat) {
|
||||
@@ -408,7 +411,6 @@ function U2pvis(act, btns) {
|
||||
|
||||
function up2k_init(have_crypto) {
|
||||
//have_crypto = false;
|
||||
var need_filereader_cache = undefined;
|
||||
|
||||
// show modal message
|
||||
function showmodal(msg) {
|
||||
@@ -690,7 +692,7 @@ function up2k_init(have_crypto) {
|
||||
esc(uricom_dec(entry.purl)[0] + entry.name)).join(' '),
|
||||
'📐 hash',
|
||||
''
|
||||
]);
|
||||
], fobj.size);
|
||||
st.files.push(entry);
|
||||
st.todo.hash.push(entry);
|
||||
}
|
||||
@@ -737,7 +739,7 @@ function up2k_init(have_crypto) {
|
||||
function hashing_permitted() {
|
||||
if (multitask) {
|
||||
var ahead = st.bytes.hashed - st.bytes.uploaded;
|
||||
return ahead < 1024 * 1024 * 128 &&
|
||||
return ahead < 1024 * 1024 * 1024 * 4 &&
|
||||
st.todo.handshake.length + st.busy.handshake.length < 16;
|
||||
}
|
||||
return handshakes_permitted() && 0 ==
|
||||
@@ -904,31 +906,6 @@ function up2k_init(have_crypto) {
|
||||
}
|
||||
}
|
||||
|
||||
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'];
|
||||
@@ -943,115 +920,88 @@ function up2k_init(have_crypto) {
|
||||
}
|
||||
|
||||
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 bpend = 0,
|
||||
nchunk = 0,
|
||||
chunksize = get_chunksize(t.size),
|
||||
nchunks = Math.ceil(t.size / chunksize),
|
||||
hashtab = {};
|
||||
|
||||
pvis.setab(t.n, nchunks);
|
||||
pvis.move(t.n, 'bz');
|
||||
|
||||
var reader = new FileReader();
|
||||
|
||||
var segm_next = function () {
|
||||
if (cache_buf) {
|
||||
return hash_calc();
|
||||
}
|
||||
reader.onload = segm_load;
|
||||
reader.onerror = segm_err;
|
||||
if (nchunk >= nchunks || (bpend > chunksize && bpend >= 32 * 1024 * 1024))
|
||||
return false;
|
||||
|
||||
var reader = new FileReader(),
|
||||
nch = nchunk++,
|
||||
car = nch * chunksize,
|
||||
cdr = car + chunksize;
|
||||
|
||||
var car = nchunk * chunksize;
|
||||
var cdr = car + chunksize * subchunks;
|
||||
if (cdr >= t.size)
|
||||
cdr = t.size;
|
||||
|
||||
bpend += cdr - car;
|
||||
|
||||
reader.onload = function (e) {
|
||||
hash_calc(nch, e.target.result);
|
||||
};
|
||||
reader.onerror = segm_err;
|
||||
reader.readAsArrayBuffer(
|
||||
bobslice.call(t.fobj, car, cdr));
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
var segm_load = function (e) {
|
||||
cache_buf = e.target.result;
|
||||
cache_ofs = 0;
|
||||
hash_calc();
|
||||
};
|
||||
var hash_calc = function (nch, buf) {
|
||||
while (segm_next());
|
||||
|
||||
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 hash_done = function (hashbuf) {
|
||||
var hslice = new Uint8Array(hashbuf).subarray(0, 32);
|
||||
var b64str = buf2b64(hslice).replace(/=$/, '');
|
||||
hashtab[nch] = b64str;
|
||||
t.hash.push(nch);
|
||||
pvis.hashed(t);
|
||||
|
||||
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);
|
||||
bpend -= buf.byteLength;
|
||||
if (t.hash.length < nchunks) {
|
||||
return segm_next();
|
||||
}
|
||||
t.hash = [];
|
||||
for (var a = 0; a < nchunks; a++) {
|
||||
t.hash.push(hashtab[a]);
|
||||
}
|
||||
|
||||
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'));
|
||||
}
|
||||
|
||||
pvis.seth(t.n, 2, 'hashing done');
|
||||
pvis.seth(t.n, 1, '📦 wait');
|
||||
st.busy.hash.splice(st.busy.hash.indexOf(t), 1);
|
||||
st.todo.handshake.push(t);
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
pvis.hashed(t);
|
||||
if (++nchunk < nchunks) {
|
||||
return segm_next();
|
||||
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);
|
||||
}
|
||||
|
||||
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'));
|
||||
}
|
||||
|
||||
pvis.seth(t.n, 2, 'hashing done');
|
||||
pvis.seth(t.n, 1, '📦 wait');
|
||||
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)');
|
||||
alert('y o u b r o k e i t\nerror: ' + reader.error);
|
||||
};
|
||||
|
||||
segm_next();
|
||||
@@ -1106,6 +1056,14 @@ function up2k_init(have_crypto) {
|
||||
pvis.seth(t.n, 0, linksplit(esc(t.purl + t.name)).join(' '));
|
||||
}
|
||||
|
||||
var chunksize = get_chunksize(t.size);
|
||||
var cdr_idx = Math.ceil(t.size / chunksize) - 1;
|
||||
var cdr_sz = (t.size % chunksize) || chunksize;
|
||||
var cbd = [];
|
||||
for (var a = 0; a <= cdr_idx; a++) {
|
||||
cbd.push(a == cdr_idx ? cdr_sz : chunksize);
|
||||
}
|
||||
|
||||
t.postlist = [];
|
||||
t.wark = response.wark;
|
||||
var missing = response.hash;
|
||||
@@ -1116,8 +1074,12 @@ function up2k_init(have_crypto) {
|
||||
missing[a], JSON.stringify(t)));
|
||||
|
||||
t.postlist.push(idx);
|
||||
cbd[idx] = 0;
|
||||
}
|
||||
|
||||
pvis.setat(t.n, cbd);
|
||||
pvis.prog(t, 0, cbd[0]);
|
||||
|
||||
var done = true;
|
||||
var msg = '🎷🐛';
|
||||
if (t.postlist.length > 0) {
|
||||
@@ -1208,6 +1170,8 @@ function up2k_init(have_crypto) {
|
||||
|
||||
var npart = upt.npart;
|
||||
var t = st.files[upt.nfile];
|
||||
if (!t.t3)
|
||||
t.t3 = new Date().getTime();
|
||||
|
||||
pvis.seth(t.n, 1, "🚀 send");
|
||||
|
||||
@@ -1217,55 +1181,40 @@ function up2k_init(have_crypto) {
|
||||
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)');
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.upload.onprogress = function (xev) {
|
||||
pvis.prog(t, npart, xev.loaded);
|
||||
};
|
||||
|
||||
reader.onload = function (e) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.upload.onprogress = function (xev) {
|
||||
var perc = xev.loaded / (cdr - car) * 100;
|
||||
pvis.prog(t, npart, perc, t);
|
||||
};
|
||||
xhr.onload = function (xev) {
|
||||
if (xhr.status == 200) {
|
||||
pvis.prog(t, npart, 101, t);
|
||||
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.t4 = new Date().getTime();
|
||||
pvis.seth(t.n, 1, 'verifying');
|
||||
st.todo.handshake.unshift(t);
|
||||
}
|
||||
tasker();
|
||||
xhr.onload = function (xev) {
|
||||
if (xhr.status == 200) {
|
||||
pvis.prog(t, npart, cdr - car);
|
||||
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.t4 = new Date().getTime();
|
||||
pvis.seth(t.n, 1, 'verifying');
|
||||
st.todo.handshake.unshift(t);
|
||||
}
|
||||
else
|
||||
alert("server broke; cu-err {0} on file [{1}]:\n".format(
|
||||
xhr.status, t.name) + (
|
||||
(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');
|
||||
if (xhr.overrideMimeType)
|
||||
xhr.overrideMimeType('Content-Type', 'application/octet-stream');
|
||||
|
||||
xhr.responseType = 'text';
|
||||
xhr.send(e.target.result);
|
||||
|
||||
if (!t.t3)
|
||||
t.t3 = new Date().getTime();
|
||||
tasker();
|
||||
}
|
||||
else
|
||||
alert("server broke; cu-err {0} on file [{1}]:\n".format(
|
||||
xhr.status, t.name) + (
|
||||
(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]);
|
||||
xhr.setRequestHeader("X-Up2k-Wark", t.wark);
|
||||
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
|
||||
if (xhr.overrideMimeType)
|
||||
xhr.overrideMimeType('Content-Type', 'application/octet-stream');
|
||||
|
||||
reader.readAsArrayBuffer(bobslice.call(t.fobj, car, cdr));
|
||||
xhr.responseType = 'text';
|
||||
xhr.send(bobslice.call(t.fobj, car, cdr));
|
||||
}
|
||||
|
||||
/////
|
||||
@@ -1322,14 +1271,14 @@ function up2k_init(have_crypto) {
|
||||
|
||||
var obj = ebi('nthread');
|
||||
if (dir.target) {
|
||||
obj.style.background = '#922';
|
||||
clmod(obj, 'err', 1);
|
||||
var v = Math.floor(parseInt(obj.value));
|
||||
if (v < 1 || v > 8 || v !== v)
|
||||
return;
|
||||
|
||||
parallel_uploads = v;
|
||||
swrite('nthread', v);
|
||||
obj.style.background = '#444';
|
||||
clmod(obj, 'err');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +141,9 @@
|
||||
font-size: 1.2em;
|
||||
padding: .15em 0;
|
||||
}
|
||||
#u2conf .txtbox.err {
|
||||
background: #922;
|
||||
}
|
||||
#u2conf a {
|
||||
color: #fff;
|
||||
background: #c38;
|
||||
@@ -238,3 +241,35 @@
|
||||
float: right;
|
||||
margin-bottom: -.3em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
html.light #u2btn {
|
||||
box-shadow: .4em .4em 0 #ccc;
|
||||
}
|
||||
html.light #u2cards span {
|
||||
color: #000;
|
||||
}
|
||||
html.light #u2cards a {
|
||||
background: linear-gradient(to bottom, #eee, #fff);
|
||||
}
|
||||
html.light #u2cards a.act {
|
||||
background: inherit;
|
||||
}
|
||||
html.light #u2conf .txtbox {
|
||||
background: #fff;
|
||||
color: #444;
|
||||
}
|
||||
html.light #u2conf .txtbox.err {
|
||||
background: #f96;
|
||||
color: #300;
|
||||
}
|
||||
html.light #u2cdesc {
|
||||
background: #fff;
|
||||
border: none;
|
||||
}
|
||||
html.light #op_up2k.srch #u2btn {
|
||||
border-color: #a80;
|
||||
}
|
||||
Reference in New Issue
Block a user