Compare commits

..

11 Commits

Author SHA1 Message Date
ed
ca6ec9c5c7 v1.0.2 2021-09-09 09:21:30 +02:00
ed
633b1f0a78 v1.0.1 2021-09-09 00:59:55 +02:00
ed
6136b9bf9c don't double-eof 2021-09-09 00:54:09 +02:00
ed
524a3ba566 actually this is better 2021-09-09 00:41:23 +02:00
ed
58580320f9 make the primary tabs toggle-buttons 2021-09-09 00:35:07 +02:00
ed
759b0a994d alternative equalizer tuning 2021-09-09 00:27:18 +02:00
ed
d2800473e4 less aggressive searching, especially on phones 2021-09-08 23:24:32 +02:00
ed
f5b1a2065e multipart-parser needs exact reads 2021-09-08 21:07:34 +00:00
ed
5e62532295 minimal-up2k: remove filesearch dropzone 2021-09-08 09:16:02 +02:00
ed
c1bee96c40 fix filedrop trying to upload without write access 2021-09-08 00:19:48 +02:00
ed
f273253a2b ( ´ w `) 2021-09-08 00:16:08 +02:00
8 changed files with 156 additions and 29 deletions

View File

@@ -1,8 +1,8 @@
# coding: utf-8
VERSION = (1, 0, 0)
VERSION = (1, 0, 2)
CODENAME = "sufficient"
BUILD_DT = (2021, 9, 7)
BUILD_DT = (2021, 9, 9)
S_VERSION = ".".join(map(str, VERSION))
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)

View File

@@ -169,7 +169,7 @@ class Cooldown(object):
return ret
class Unrecv(object):
class _Unrecv(object):
"""
undo any number of socket recv ops
"""
@@ -189,10 +189,68 @@ class Unrecv(object):
except:
return b""
def recv_ex(self, nbytes):
"""read an exact number of bytes"""
ret = self.recv(nbytes)
while ret and len(ret) < nbytes:
buf = self.recv(nbytes - len(ret))
if not buf:
break
ret += buf
return ret
def unrecv(self, buf):
self.buf = buf + self.buf
class _LUnrecv(object):
"""
with expensive debug logging
"""
def __init__(self, s):
self.s = s
self.buf = b""
def recv(self, nbytes):
if self.buf:
ret = self.buf[:nbytes]
self.buf = self.buf[nbytes:]
m = "\033[0;7mur:pop:\033[0;1;32m {}\n\033[0;7mur:rem:\033[0;1;35m {}\033[0m\n"
print(m.format(ret, self.buf), end="")
return ret
try:
ret = self.s.recv(nbytes)
m = "\033[0;7mur:recv\033[0;1;33m {}\033[0m\n"
print(m.format(ret), end="")
return ret
except:
return b""
def recv_ex(self, nbytes):
"""read an exact number of bytes"""
ret = self.recv(nbytes)
while ret and len(ret) < nbytes:
buf = self.recv(nbytes - len(ret))
if not buf:
break
ret += buf
return ret
def unrecv(self, buf):
self.buf = buf + self.buf
m = "\033[0;7mur:push\033[0;1;31m {}\n\033[0;7mur:rem:\033[0;1;35m {}\033[0m\n"
print(m.format(buf, self.buf), end="")
Unrecv = _Unrecv
class ProgressPrinter(threading.Thread):
"""
periodically print progress info without linefeeds
@@ -587,19 +645,21 @@ class MultipartParser(object):
yields [fieldname, unsanitized_filename, fieldvalue]
where fieldvalue yields chunks of data
"""
while True:
run = True
while run:
fieldname, filename = self._read_header()
yield [fieldname, filename, self._read_data()]
tail = self.sr.recv(2)
tail = self.sr.recv_ex(2)
if tail == b"--":
# EOF indicated by this immediately after final boundary
self.sr.recv(2)
return
tail = self.sr.recv_ex(2)
run = False
if tail != b"\r\n":
raise Pebkac(400, "protocol error after field value")
m = "protocol error after field value: want b'\\r\\n', got {!r}"
raise Pebkac(400, m.format(tail))
def _read_value(self, iterator, max_len):
ret = b""
@@ -985,8 +1045,12 @@ def read_socket_chunked(sr, log=None):
raise Pebkac(400, err)
if chunklen == 0:
sr.recv(2) # \r\n after final chunk
return
x = sr.recv_ex(2)
if x == b"\r\n":
return
m = "protocol error after final chunk: want b'\\r\\n', got {!r}"
raise Pebkac(400, m.format(x))
if log:
log("receiving {} byte chunk".format(chunklen))
@@ -994,7 +1058,10 @@ def read_socket_chunked(sr, log=None):
for chunk in read_socket(sr, chunklen):
yield chunk
sr.recv(2) # \r\n after each chunk too
x = sr.recv_ex(2)
if x != b"\r\n":
m = "protocol error in chunk separator: want b'\\r\\n', got {!r}"
raise Pebkac(400, m.format(x))
def yieldfile(fn):

View File

@@ -9,7 +9,7 @@ function dbg(msg) {
// toolbar
ebi('ops').innerHTML = (
'<a href="#" data-dest="" tt="close submenu">---</a>\n' +
'<a href="#" data-dest="" tt="close submenu">--</a>\n' +
(have_up2k_idx ? (
'<a href="#" data-perm="read" data-dest="search" tt="search for files by attributes, path/name, music tags, or any combination of those.$N$N&lt;code&gt;foo bar&lt;/code&gt; = must contain both foo and bar,$N&lt;code&gt;foo -bar&lt;/code&gt; = must contain foo but not bar,$N&lt;code&gt;^yana .opus$&lt;/code&gt; = must start with yana and have the opus extension">🔎</a>\n' +
(have_del && have_unpost ? '<a href="#" data-dest="unpost" tt="unpost: delete your recent uploads">🧯</a>\n' : '') +
@@ -199,6 +199,9 @@ ebi('tree').innerHTML = (
function opclick(e) {
var dest = this.getAttribute('data-dest');
if (QS('#op_' + dest + '.act'))
dest = '';
swrite('opmode', dest || null);
if (ctrl(e))
return;
@@ -1063,6 +1066,33 @@ var audio_eq = (function () {
"last_au": null
};
// some browsers have insane high-frequency boost
// (or rather the actual problem is Q but close enough)
r.cali = (function () {
try {
var ac = new AudioContext(),
fi = ac.createBiquadFilter(),
freqs = new Float32Array(1),
mag = new Float32Array(1),
phase = new Float32Array(1);
freqs[0] = 14000;
fi.type = 'peaking';
fi.frequency.value = 18000;
fi.Q.value = 0.8;
fi.gain.value = 1;
fi.getFrequencyResponse(freqs, mag, phase);
return mag[0]; // 1.0407 good, 1.0563 bad
}
catch (ex) {
return 0;
}
})();
console.log('eq cali: ' + r.cali);
var e1 = r.cali < 1.05;
var cfg = [ // hz, q, g
[31.25 * 0.88, 0, 1.4], // shelf
[31.25 * 1.04, 0.7, 0.96], // peak
@@ -1073,10 +1103,10 @@ var audio_eq = (function () {
[1000, 0.9, 1.1],
[2000, 0.9, 1.105],
[4000, 0.88, 1.05],
[8000 * 1.006, 0.73, 1.24],
[16000 * 0.89, 0.7, 1.26], // peak
[16000 * 1.13, 0.82, 1.09], // peak
[16000 * 1.205, 0, 1.9] // shelf
[8000 * 1.006, 0.73, e1 ? 1.24 : 1.2],
[16000 * 0.89, 0.7, e1 ? 1.26 : 1.2], // peak
[16000 * 1.13, 0.82, e1 ? 1.09 : 0.75], // peak
[16000 * 1.205, 0, e1 ? 1.9 : 1.85] // shelf
];
try {
@@ -2834,14 +2864,15 @@ document.onkeydown = function (e) {
clearTimeout(defer_timeout);
defer_timeout = setTimeout(try_search, 2000);
try_search();
try_search(v);
}
function try_search() {
function try_search(v) {
if (Date.now() - search_in_progress > 30 * 1000) {
clearTimeout(defer_timeout);
clearTimeout(search_timeout);
search_timeout = setTimeout(do_search, 200);
search_timeout = setTimeout(do_search,
v && v.length < (is_touch ? 4 : 3) ? 600 : 200);
}
}
@@ -4140,7 +4171,7 @@ function ev_row_tgl(e) {
var unpost = (function () {
ebi('op_unpost').innerHTML = (
"you can delete your recent uploads below &ndash; click the fire-extinguisher icon to refresh" +
'you can delete your recent uploads below &ndash; <a id="unpost_refresh" href="#">refresh list</a>' +
'<p>optional filter:&nbsp; URL must contain <input type="text" id="unpost_filt" size="20" /><a id="unpost_nofilt" href="#">clear filter</a></p>' +
'<div id="unpost"></div>'
);
@@ -4285,6 +4316,11 @@ var unpost = (function () {
r.load();
};
ebi('unpost_refresh').onclick = function (e) {
ev(e);
goto('unpost');
};
return r;
})();

View File

@@ -715,13 +715,12 @@ function up2k_init(subtle) {
offdrag.bind(this)();
var dz = (this && this.getAttribute('id'));
if ((dz == 'up_dz' && fsearch) || (dz == 'srch_dz' && !fsearch)) {
var err = this.getAttribute('err');
if (err)
return modal.alert('sorry, ' + err);
var err = this.getAttribute('err');
if (err)
return modal.alert('sorry, ' + err);
if ((dz == 'up_dz' && fsearch) || (dz == 'srch_dz' && !fsearch))
tgl_fsearch();
}
if (!QS('#op_up2k.act'))
goto('up2k');

View File

@@ -3,6 +3,24 @@
setTimeout(location.reload.bind(location), 700);
document.documentElement.scrollLeft = 0;
var cali = (function() {
var ac = new AudioContext(),
fi = ac.createBiquadFilter(),
freqs = new Float32Array(1),
mag = new Float32Array(1),
phase = new Float32Array(1);
freqs[0] = 14000;
fi.type = 'peaking';
fi.frequency.value = 18000;
fi.Q.value = 0.8;
fi.gain.value = 1;
fi.getFrequencyResponse(freqs, mag, phase);
return mag[0]; // 1.0407 good, 1.0563 bad
})(),
mp = cali < 1.05;
var can = document.createElement('canvas'),
cc = can.getContext('2d'),
w = 2048,
@@ -28,12 +46,12 @@ var cfg = [ // hz, q, g
[1000, 0.9, 1.1],
[2000, 0.9, 1.105],
[4000, 0.88, 1.05],
[8000 * 1.006, 0.73, 1.24],
[8000 * 1.006, 0.73, mp ? 1.24 : 1.2],
//[16000 * 1.00, 0.5, 1.75], // peak.v1
//[16000 * 1.19, 0, 1.8] // shelf.v1
[16000 * 0.89, 0.7, 1.26], // peak
[16000 * 1.13, 0.82, 1.09], // peak
[16000 * 1.205, 0, 1.9] // shelf
[16000 * 0.89, 0.7, mp ? 1.26 : 1.2], // peak
[16000 * 1.13, 0.82, mp ? 1.09 : 0.75], // peak
[16000 * 1.205, 0, mp ? 1.9 : 1.85] // shelf
];
var freqs = new Float32Array(22000),

View File

@@ -11,6 +11,8 @@
#u2cleanup, #u2conf tr:first-child>td[rowspan]:not(#u2btn_cw), /* most of the config options */
#srch_dz, #srch_zd, /* the filesearch dropzone */
#u2cards, #u2etaw /* and the upload progress tabs */
{display: none !important} /* do it! */

View File

@@ -39,6 +39,8 @@ class Cfg(Namespace):
no_scandir=False,
no_sendfile=True,
no_rescan=True,
no_logues=False,
no_readme=False,
re_maxage=0,
ihead=False,
nih=True,
@@ -151,6 +153,7 @@ class TestHttpCli(unittest.TestCase):
tar = tarfile.open(fileobj=io.BytesIO(b)).getnames()
except:
tar = []
tar = [x[4:] if x.startswith("top/") else x for x in tar]
tar = ["/".join([y for y in [top, durl, x] if y]) for x in tar]
tar = [[x] + self.can_rw(x) for x in tar]
tar_ok = [x[0] for x in tar if x[1]]

View File

@@ -26,6 +26,8 @@ class Cfg(Namespace):
"no_hash": False,
"css_browser": None,
"no_voldump": True,
"no_logues": False,
"no_readme": False,
"re_maxage": 0,
"rproxy": 0,
}