mirror of
https://github.com/9001/copyparty.git
synced 2025-10-30 03:23:33 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3e4d65b80 | ||
|
|
27a03510c5 | ||
|
|
ed7727f7cb | ||
|
|
127ec10c0d | ||
|
|
5a9c0ad225 |
@@ -1,8 +1,8 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
VERSION = (0, 10, 14)
|
VERSION = (0, 10, 15)
|
||||||
CODENAME = "zip it"
|
CODENAME = "zip it"
|
||||||
BUILD_DT = (2021, 4, 21)
|
BUILD_DT = (2021, 4, 24)
|
||||||
|
|
||||||
S_VERSION = ".".join(map(str, VERSION))
|
S_VERSION = ".".join(map(str, VERSION))
|
||||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||||
|
|||||||
@@ -182,10 +182,8 @@ class HttpCli(object):
|
|||||||
self.out_headers.update(headers)
|
self.out_headers.update(headers)
|
||||||
|
|
||||||
# default to utf8 html if no content-type is set
|
# default to utf8 html if no content-type is set
|
||||||
try:
|
if not mime:
|
||||||
mime = mime or self.out_headers["Content-Type"]
|
mime = self.out_headers.get("Content-Type", "text/html; charset=UTF-8")
|
||||||
except KeyError:
|
|
||||||
mime = "text/html; charset=UTF-8"
|
|
||||||
|
|
||||||
self.out_headers["Content-Type"] = mime
|
self.out_headers["Content-Type"] = mime
|
||||||
|
|
||||||
@@ -536,7 +534,7 @@ class HttpCli(object):
|
|||||||
self.log("qj: " + repr(vbody))
|
self.log("qj: " + repr(vbody))
|
||||||
hits = idx.fsearch(vols, body)
|
hits = idx.fsearch(vols, body)
|
||||||
msg = repr(hits)
|
msg = repr(hits)
|
||||||
taglist = []
|
taglist = {}
|
||||||
else:
|
else:
|
||||||
# search by query params
|
# search by query params
|
||||||
self.log("qj: " + repr(body))
|
self.log("qj: " + repr(body))
|
||||||
@@ -1319,6 +1317,77 @@ class HttpCli(object):
|
|||||||
# print(abspath)
|
# print(abspath)
|
||||||
raise Pebkac(404)
|
raise Pebkac(404)
|
||||||
|
|
||||||
|
srv_info = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not self.args.nih:
|
||||||
|
srv_info.append(unicode(socket.gethostname()).split(".")[0])
|
||||||
|
except:
|
||||||
|
self.log("#wow #whoa")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# some fuses misbehave
|
||||||
|
if not self.args.nid:
|
||||||
|
if WINDOWS:
|
||||||
|
bfree = ctypes.c_ulonglong(0)
|
||||||
|
ctypes.windll.kernel32.GetDiskFreeSpaceExW(
|
||||||
|
ctypes.c_wchar_p(abspath), None, None, ctypes.pointer(bfree)
|
||||||
|
)
|
||||||
|
srv_info.append(humansize(bfree.value) + " free")
|
||||||
|
else:
|
||||||
|
sv = os.statvfs(abspath)
|
||||||
|
free = humansize(sv.f_frsize * sv.f_bfree, True)
|
||||||
|
total = humansize(sv.f_frsize * sv.f_blocks, True)
|
||||||
|
|
||||||
|
srv_info.append(free + " free")
|
||||||
|
srv_info.append(total)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
srv_info = "</span> /// <span>".join(srv_info)
|
||||||
|
|
||||||
|
perms = []
|
||||||
|
if self.readable:
|
||||||
|
perms.append("read")
|
||||||
|
if self.writable:
|
||||||
|
perms.append("write")
|
||||||
|
|
||||||
|
url_suf = self.urlq()
|
||||||
|
is_ls = "ls" in self.uparam
|
||||||
|
ts = "" # "?{}".format(time.time())
|
||||||
|
|
||||||
|
tpl = "browser"
|
||||||
|
if "b" in self.uparam:
|
||||||
|
tpl = "browser2"
|
||||||
|
|
||||||
|
j2a = {
|
||||||
|
"vdir": quotep(self.vpath),
|
||||||
|
"vpnodes": vpnodes,
|
||||||
|
"files": [],
|
||||||
|
"ts": ts,
|
||||||
|
"perms": json.dumps(perms),
|
||||||
|
"taglist": [],
|
||||||
|
"tag_order": [],
|
||||||
|
"have_up2k_idx": ("e2d" in vn.flags),
|
||||||
|
"have_tags_idx": ("e2t" in vn.flags),
|
||||||
|
"have_zip": (not self.args.no_zip),
|
||||||
|
"have_b_u": (self.writable and self.uparam.get("b") == "u"),
|
||||||
|
"url_suf": url_suf,
|
||||||
|
"logues": ["", ""],
|
||||||
|
"title": html_escape(self.vpath, crlf=True),
|
||||||
|
"srv_info": srv_info,
|
||||||
|
}
|
||||||
|
if not self.readable:
|
||||||
|
if is_ls:
|
||||||
|
raise Pebkac(403)
|
||||||
|
|
||||||
|
if not os.path.isdir(fsenc(abspath)):
|
||||||
|
raise Pebkac(404)
|
||||||
|
|
||||||
|
html = self.j2(tpl, **j2a)
|
||||||
|
self.reply(html.encode("utf-8", "replace"))
|
||||||
|
return True
|
||||||
|
|
||||||
if not os.path.isdir(fsenc(abspath)):
|
if not os.path.isdir(fsenc(abspath)):
|
||||||
if abspath.endswith(".md") and "raw" not in self.uparam:
|
if abspath.endswith(".md") and "raw" not in self.uparam:
|
||||||
return self.tx_md(abspath)
|
return self.tx_md(abspath)
|
||||||
@@ -1362,15 +1431,11 @@ class HttpCli(object):
|
|||||||
if rem == ".hist":
|
if rem == ".hist":
|
||||||
hidden = ["up2k."]
|
hidden = ["up2k."]
|
||||||
|
|
||||||
is_ls = "ls" in self.uparam
|
|
||||||
|
|
||||||
icur = None
|
icur = None
|
||||||
if "e2t" in vn.flags:
|
if "e2t" in vn.flags:
|
||||||
idx = self.conn.get_u2idx()
|
idx = self.conn.get_u2idx()
|
||||||
icur = idx.get_cur(vn.realpath)
|
icur = idx.get_cur(vn.realpath)
|
||||||
|
|
||||||
url_suf = self.urlq()
|
|
||||||
|
|
||||||
dirs = []
|
dirs = []
|
||||||
files = []
|
files = []
|
||||||
for fn in vfs_ls:
|
for fn in vfs_ls:
|
||||||
@@ -1461,42 +1526,6 @@ class HttpCli(object):
|
|||||||
for f in dirs:
|
for f in dirs:
|
||||||
f["tags"] = {}
|
f["tags"] = {}
|
||||||
|
|
||||||
srv_info = []
|
|
||||||
|
|
||||||
try:
|
|
||||||
if not self.args.nih:
|
|
||||||
srv_info.append(unicode(socket.gethostname()).split(".")[0])
|
|
||||||
except:
|
|
||||||
self.log("#wow #whoa")
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
# some fuses misbehave
|
|
||||||
if not self.args.nid:
|
|
||||||
if WINDOWS:
|
|
||||||
bfree = ctypes.c_ulonglong(0)
|
|
||||||
ctypes.windll.kernel32.GetDiskFreeSpaceExW(
|
|
||||||
ctypes.c_wchar_p(abspath), None, None, ctypes.pointer(bfree)
|
|
||||||
)
|
|
||||||
srv_info.append(humansize(bfree.value) + " free")
|
|
||||||
else:
|
|
||||||
sv = os.statvfs(abspath)
|
|
||||||
free = humansize(sv.f_frsize * sv.f_bfree, True)
|
|
||||||
total = humansize(sv.f_frsize * sv.f_blocks, True)
|
|
||||||
|
|
||||||
srv_info.append(free + " free")
|
|
||||||
srv_info.append(total)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
srv_info = "</span> /// <span>".join(srv_info)
|
|
||||||
|
|
||||||
perms = []
|
|
||||||
if self.readable:
|
|
||||||
perms.append("read")
|
|
||||||
if self.writable:
|
|
||||||
perms.append("write")
|
|
||||||
|
|
||||||
logues = ["", ""]
|
logues = ["", ""]
|
||||||
for n, fn in enumerate([".prologue.html", ".epilogue.html"]):
|
for n, fn in enumerate([".prologue.html", ".epilogue.html"]):
|
||||||
fn = os.path.join(abspath, fn)
|
fn = os.path.join(abspath, fn)
|
||||||
@@ -1518,34 +1547,12 @@ class HttpCli(object):
|
|||||||
self.reply(ret.encode("utf-8", "replace"), mime="application/json")
|
self.reply(ret.encode("utf-8", "replace"), mime="application/json")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
ts = ""
|
j2a["files"] = dirs + files
|
||||||
# ts = "?{}".format(time.time())
|
j2a["logues"] = logues
|
||||||
|
j2a["taglist"] = taglist
|
||||||
|
if "mte" in vn.flags:
|
||||||
|
j2a["tag_order"] = json.dumps(vn.flags["mte"].split(","))
|
||||||
|
|
||||||
dirs.extend(files)
|
html = self.j2(tpl, **j2a)
|
||||||
|
|
||||||
tpl = "browser"
|
|
||||||
if "b" in self.uparam:
|
|
||||||
tpl = "browser2"
|
|
||||||
|
|
||||||
html = self.j2(
|
|
||||||
tpl,
|
|
||||||
vdir=quotep(self.vpath),
|
|
||||||
vpnodes=vpnodes,
|
|
||||||
files=dirs,
|
|
||||||
ts=ts,
|
|
||||||
perms=json.dumps(perms),
|
|
||||||
taglist=taglist,
|
|
||||||
tag_order=json.dumps(
|
|
||||||
vn.flags["mte"].split(",") if "mte" in vn.flags else []
|
|
||||||
),
|
|
||||||
have_up2k_idx=("e2d" in vn.flags),
|
|
||||||
have_tags_idx=("e2t" in vn.flags),
|
|
||||||
have_zip=(not self.args.no_zip),
|
|
||||||
have_b_u=(self.writable and self.uparam.get("b") == "u"),
|
|
||||||
url_suf=url_suf,
|
|
||||||
logues=logues,
|
|
||||||
title=html_escape(self.vpath, crlf=True),
|
|
||||||
srv_info=srv_info,
|
|
||||||
)
|
|
||||||
self.reply(html.encode("utf-8", "replace"))
|
self.reply(html.encode("utf-8", "replace"))
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ a, #files tbody div a:last-child {
|
|||||||
color: #999;
|
color: #999;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
#files tr+tr:hover {
|
#files tr:hover {
|
||||||
background: #1c1c1c;
|
background: #1c1c1c;
|
||||||
}
|
}
|
||||||
#files thead th {
|
#files thead th {
|
||||||
@@ -98,7 +98,7 @@ a, #files tbody div a:last-child {
|
|||||||
max-width: 30em;
|
max-width: 30em;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
#files tr+tr td {
|
#files tr td {
|
||||||
border-top: 1px solid #383838;
|
border-top: 1px solid #383838;
|
||||||
}
|
}
|
||||||
#files tbody td:nth-child(3) {
|
#files tbody td:nth-child(3) {
|
||||||
@@ -685,6 +685,15 @@ input[type="checkbox"]:checked+label {
|
|||||||
font-family: monospace, monospace;
|
font-family: monospace, monospace;
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
}
|
}
|
||||||
|
#pvol,
|
||||||
|
#barbuf,
|
||||||
|
#barpos,
|
||||||
|
#u2conf label {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -704,7 +713,7 @@ html.light #srch_form {
|
|||||||
}
|
}
|
||||||
html.light #ops a.act {
|
html.light #ops a.act {
|
||||||
box-shadow: 0 .2em .2em #ccc;
|
box-shadow: 0 .2em .2em #ccc;
|
||||||
background: #f7f7f7;
|
background: #fff;
|
||||||
border-color: #07a;
|
border-color: #07a;
|
||||||
padding-top: .4em;
|
padding-top: .4em;
|
||||||
}
|
}
|
||||||
@@ -761,7 +770,7 @@ html.light #files {
|
|||||||
html.light #files thead th {
|
html.light #files thead th {
|
||||||
background: #eee;
|
background: #eee;
|
||||||
}
|
}
|
||||||
html.light #files tr+tr td {
|
html.light #files tr td {
|
||||||
border-top: 1px solid #ddd;
|
border-top: 1px solid #ddd;
|
||||||
}
|
}
|
||||||
html.light #files td {
|
html.light #files td {
|
||||||
@@ -785,8 +794,12 @@ html.light tr.play td {
|
|||||||
html.light tr.play a {
|
html.light tr.play a {
|
||||||
color: #406;
|
color: #406;
|
||||||
}
|
}
|
||||||
|
html.light #files th:hover .cfg,
|
||||||
|
html.light #files th.min .cfg {
|
||||||
|
background: #ccc;
|
||||||
|
}
|
||||||
html.light #files > thead > tr > th.min span {
|
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));
|
background: linear-gradient(90deg, rgba(204,204,204,0), rgba(204,204,204,0.5) 70%, #ccc);
|
||||||
}
|
}
|
||||||
html.light #blocked {
|
html.light #blocked {
|
||||||
background: #eee;
|
background: #eee;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ function dbg(msg) {
|
|||||||
|
|
||||||
// extract songs + add play column
|
// extract songs + add play column
|
||||||
function MPlayer() {
|
function MPlayer() {
|
||||||
this.id = new Date().getTime();
|
this.id = Date.now();
|
||||||
this.au = null;
|
this.au = null;
|
||||||
this.au_native = null;
|
this.au_native = null;
|
||||||
this.au_ogvjs = null;
|
this.au_ogvjs = null;
|
||||||
@@ -17,15 +17,17 @@ function MPlayer() {
|
|||||||
this.tracks = {};
|
this.tracks = {};
|
||||||
this.order = [];
|
this.order = [];
|
||||||
|
|
||||||
var re_audio = /\.(opus|ogg|m4a|aac|mp3|wav|flac)$/i;
|
var re_audio = /\.(opus|ogg|m4a|aac|mp3|wav|flac)$/i,
|
||||||
var trs = document.querySelectorAll('#files tbody tr');
|
trs = QSA('#files tbody tr');
|
||||||
for (var a = 0, aa = trs.length; a < aa; a++) {
|
|
||||||
var tds = trs[a].getElementsByTagName('td');
|
for (var a = 0, aa = trs.length; a < aa; a++) {
|
||||||
var link = tds[1].getElementsByTagName('a');
|
var tds = trs[a].getElementsByTagName('td'),
|
||||||
link = link[link.length - 1];
|
link = tds[1].getElementsByTagName('a');
|
||||||
var url = link.getAttribute('href');
|
|
||||||
|
link = link[link.length - 1];
|
||||||
|
var url = link.getAttribute('href'),
|
||||||
|
m = re_audio.exec(url);
|
||||||
|
|
||||||
var m = re_audio.exec(url);
|
|
||||||
if (m) {
|
if (m) {
|
||||||
var tid = link.getAttribute('id');
|
var tid = link.getAttribute('id');
|
||||||
this.order.push(tid);
|
this.order.push(tid);
|
||||||
@@ -54,8 +56,9 @@ function MPlayer() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.read_order = function () {
|
this.read_order = function () {
|
||||||
var order = [];
|
var order = [],
|
||||||
var links = document.querySelectorAll('#files>tbody>tr>td:nth-child(1)>a');
|
links = QSA('#files>tbody>tr>td:nth-child(1)>a');
|
||||||
|
|
||||||
for (var a = 0, aa = links.length; a < aa; a++) {
|
for (var a = 0, aa = links.length; a < aa; a++) {
|
||||||
var tid = links[a].getAttribute('id');
|
var tid = links[a].getAttribute('id');
|
||||||
if (!tid || tid.indexOf('af-') !== 0)
|
if (!tid || tid.indexOf('af-') !== 0)
|
||||||
@@ -73,12 +76,12 @@ makeSortable(ebi('files'), mp.read_order.bind(mp));
|
|||||||
|
|
||||||
// toggle player widget
|
// toggle player widget
|
||||||
var widget = (function () {
|
var widget = (function () {
|
||||||
var ret = {};
|
var ret = {},
|
||||||
var widget = ebi('widget');
|
widget = ebi('widget'),
|
||||||
var wtico = ebi('wtico');
|
wtico = ebi('wtico'),
|
||||||
var touchmode = false;
|
touchmode = false,
|
||||||
var side_open = false;
|
side_open = false,
|
||||||
var was_paused = true;
|
was_paused = true;
|
||||||
|
|
||||||
ret.open = function () {
|
ret.open = function () {
|
||||||
if (side_open)
|
if (side_open)
|
||||||
@@ -107,159 +110,170 @@ var widget = (function () {
|
|||||||
ebi('bplay').innerHTML = paused ? '▶' : '⏸';
|
ebi('bplay').innerHTML = paused ? '▶' : '⏸';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var click_handler = function (e) {
|
wtico.onclick = function (e) {
|
||||||
if (!touchmode)
|
if (!touchmode)
|
||||||
ret.toggle(e);
|
ret.toggle(e);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
wtico.onclick = click_handler;
|
|
||||||
return ret;
|
return ret;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
function canvas_cfg(can) {
|
||||||
|
var r = {},
|
||||||
|
b = can.getBoundingClientRect(),
|
||||||
|
mul = window.devicePixelRatio || 1;
|
||||||
|
|
||||||
|
r.w = b.width;
|
||||||
|
r.h = b.height;
|
||||||
|
can.width = r.w * mul;
|
||||||
|
can.height = r.h * mul;
|
||||||
|
|
||||||
|
r.can = can;
|
||||||
|
r.ctx = can.getContext('2d');
|
||||||
|
r.ctx.scale(mul, mul);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function glossy_grad(can, hsl) {
|
||||||
|
var g = can.ctx.createLinearGradient(0, 0, 0, can.h),
|
||||||
|
s = [0, 0.49, 0.50, 1];
|
||||||
|
|
||||||
|
for (var a = 0; a < hsl.length; a++)
|
||||||
|
g.addColorStop(s[a], 'hsl(' + hsl[a] + ')');
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// buffer/position bar
|
// buffer/position bar
|
||||||
var pbar = (function () {
|
var pbar = (function () {
|
||||||
var r = {};
|
var r = {},
|
||||||
r.bcan = ebi('barbuf');
|
gradh = -1,
|
||||||
r.pcan = ebi('barpos');
|
grad;
|
||||||
r.bctx = r.bcan.getContext('2d');
|
|
||||||
r.pctx = r.pcan.getContext('2d');
|
|
||||||
|
|
||||||
var bctx = r.bctx;
|
function onresize() {
|
||||||
var pctx = r.pctx;
|
r.buf = canvas_cfg(ebi('barbuf'));
|
||||||
var scale = (window.devicePixelRatio || 1) / (
|
r.pos = canvas_cfg(ebi('barpos'));
|
||||||
bctx.webkitBackingStorePixelRatio ||
|
r.drawbuf();
|
||||||
bctx.mozBackingStorePixelRatio ||
|
r.drawpos();
|
||||||
bctx.msBackingStorePixelRatio ||
|
}
|
||||||
bctx.oBackingStorePixelRatio ||
|
|
||||||
bctx.BackingStorePixelRatio || 1);
|
|
||||||
|
|
||||||
var gradh = 0;
|
|
||||||
var grad = null;
|
|
||||||
|
|
||||||
r.drawbuf = function () {
|
r.drawbuf = function () {
|
||||||
if (!mp.au)
|
if (!mp.au)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var cs = getComputedStyle(r.bcan);
|
var bc = r.buf,
|
||||||
var sw = parseInt(cs['width']);
|
bctx = bc.ctx,
|
||||||
var sh = parseInt(cs['height']);
|
sm = bc.w * 1.0 / mp.au.duration;
|
||||||
var sm = sw * 1.0 / mp.au.duration;
|
|
||||||
|
|
||||||
r.bcan.width = (sw * scale);
|
if (gradh != bc.h) {
|
||||||
r.bcan.height = (sh * scale);
|
gradh = bc.h;
|
||||||
bctx.setTransform(scale, 0, 0, scale, 0, 0);
|
grad = glossy_grad(bc, [
|
||||||
|
'85,35%,42%',
|
||||||
if (!grad || gradh != sh) {
|
'85,40%,49%',
|
||||||
grad = bctx.createLinearGradient(0, 0, 0, sh);
|
'85,37%,47%',
|
||||||
grad.addColorStop(0, 'hsl(85,35%,42%)');
|
'85,35%,42%'
|
||||||
grad.addColorStop(0.49, 'hsl(85,40%,49%)');
|
]);
|
||||||
grad.addColorStop(0.50, 'hsl(85,37%,47%)');
|
|
||||||
grad.addColorStop(1, 'hsl(85,35%,42%)');
|
|
||||||
gradh = sh;
|
|
||||||
}
|
}
|
||||||
bctx.fillStyle = grad;
|
bctx.fillStyle = grad;
|
||||||
bctx.clearRect(0, 0, sw, sh);
|
bctx.clearRect(0, 0, bc.w, bc.h);
|
||||||
for (var a = 0; a < mp.au.buffered.length; a++) {
|
for (var a = 0; a < mp.au.buffered.length; a++) {
|
||||||
var x1 = sm * mp.au.buffered.start(a);
|
var x1 = sm * mp.au.buffered.start(a),
|
||||||
var x2 = sm * mp.au.buffered.end(a);
|
x2 = sm * mp.au.buffered.end(a);
|
||||||
bctx.fillRect(x1, 0, x2 - x1, sh);
|
|
||||||
|
bctx.fillRect(x1, 0, x2 - x1, bc.h);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
r.drawpos = function () {
|
r.drawpos = function () {
|
||||||
if (!mp.au)
|
if (!mp.au)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var cs = getComputedStyle(r.bcan);
|
var bc = r.buf,
|
||||||
var sw = parseInt(cs['width']);
|
pc = r.pos,
|
||||||
var sh = parseInt(cs['height']);
|
pctx = pc.ctx,
|
||||||
var sm = sw * 1.0 / mp.au.duration;
|
sm = bc.w * 1.0 / mp.au.duration;
|
||||||
|
|
||||||
r.pcan.width = (sw * scale);
|
|
||||||
r.pcan.height = (sh * scale);
|
|
||||||
pctx.setTransform(scale, 0, 0, scale, 0, 0);
|
|
||||||
pctx.clearRect(0, 0, sw, sh);
|
|
||||||
|
|
||||||
|
pctx.clearRect(0, 0, pc.w, pc.h);
|
||||||
pctx.fillStyle = 'rgba(204,255,128,0.15)';
|
pctx.fillStyle = 'rgba(204,255,128,0.15)';
|
||||||
for (var p = 1, mins = mp.au.duration / 10; p <= mins; p++)
|
for (var p = 1, mins = mp.au.duration / 10; p <= mins; p++)
|
||||||
pctx.fillRect(Math.floor(sm * p * 10), 0, 2, sh);
|
pctx.fillRect(Math.floor(sm * p * 10), 0, 2, pc.h);
|
||||||
|
|
||||||
pctx.fillStyle = '#9b7';
|
pctx.fillStyle = '#9b7';
|
||||||
pctx.fillStyle = 'rgba(192,255,96,0.5)';
|
pctx.fillStyle = 'rgba(192,255,96,0.5)';
|
||||||
for (var p = 1, mins = mp.au.duration / 60; p <= mins; p++)
|
for (var p = 1, mins = mp.au.duration / 60; p <= mins; p++)
|
||||||
pctx.fillRect(Math.floor(sm * p * 60), 0, 2, sh);
|
pctx.fillRect(Math.floor(sm * p * 60), 0, 2, pc.h);
|
||||||
|
|
||||||
var w = 8;
|
var w = 8,
|
||||||
var x = sm * mp.au.currentTime;
|
x = sm * mp.au.currentTime;
|
||||||
pctx.fillStyle = '#573'; pctx.fillRect((x - w / 2) - 1, 0, w + 2, sh);
|
|
||||||
pctx.fillStyle = '#dfc'; pctx.fillRect((x - w / 2), 0, 8, sh);
|
pctx.fillStyle = '#573'; pctx.fillRect((x - w / 2) - 1, 0, w + 2, pc.h);
|
||||||
|
pctx.fillStyle = '#dfc'; pctx.fillRect((x - w / 2), 0, 8, pc.h);
|
||||||
|
|
||||||
pctx.fillStyle = '#fff';
|
pctx.fillStyle = '#fff';
|
||||||
pctx.font = '1em sans-serif';
|
pctx.font = '1em sans-serif';
|
||||||
var txt = s2ms(mp.au.duration);
|
var txt = s2ms(mp.au.duration),
|
||||||
var tw = pctx.measureText(txt).width;
|
tw = pctx.measureText(txt).width;
|
||||||
pctx.fillText(txt, sw - (tw + 8), sh / 3 * 2);
|
|
||||||
|
pctx.fillText(txt, pc.w - (tw + 8), pc.h / 3 * 2);
|
||||||
|
|
||||||
txt = s2ms(mp.au.currentTime);
|
txt = s2ms(mp.au.currentTime);
|
||||||
tw = pctx.measureText(txt).width;
|
tw = pctx.measureText(txt).width;
|
||||||
var gw = pctx.measureText("88:88::").width;
|
var gw = pctx.measureText("88:88::").width,
|
||||||
var xt = x < sw / 2 ? (x + 8) : (Math.min(sw - gw, x - 8) - tw);
|
xt = x < pc.w / 2 ? (x + 8) : (Math.min(pc.w - gw, x - 8) - tw);
|
||||||
pctx.fillText(txt, xt, sh / 3 * 2);
|
|
||||||
|
pctx.fillText(txt, xt, pc.h / 3 * 2);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.addEventListener('resize', onresize);
|
||||||
|
onresize();
|
||||||
return r;
|
return r;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
// volume bar
|
// volume bar
|
||||||
var vbar = (function () {
|
var vbar = (function () {
|
||||||
var r = {};
|
var r = {},
|
||||||
r.can = ebi('pvol');
|
gradh = -1,
|
||||||
r.ctx = r.can.getContext('2d');
|
can, ctx, w, h, grad1, grad2;
|
||||||
|
|
||||||
var bctx = r.ctx;
|
function onresize() {
|
||||||
var scale = (window.devicePixelRatio || 1) / (
|
r.can = canvas_cfg(ebi('pvol'));
|
||||||
bctx.webkitBackingStorePixelRatio ||
|
can = r.can.can;
|
||||||
bctx.mozBackingStorePixelRatio ||
|
ctx = r.can.ctx;
|
||||||
bctx.msBackingStorePixelRatio ||
|
w = r.can.w;
|
||||||
bctx.oBackingStorePixelRatio ||
|
h = r.can.h;
|
||||||
bctx.BackingStorePixelRatio || 1);
|
r.draw();
|
||||||
|
}
|
||||||
var gradh = 0;
|
|
||||||
var grad1 = null;
|
|
||||||
var grad2 = null;
|
|
||||||
|
|
||||||
r.draw = function () {
|
r.draw = function () {
|
||||||
var cs = getComputedStyle(r.can);
|
if (gradh != h) {
|
||||||
var sw = parseInt(cs['width']);
|
gradh = h;
|
||||||
var sh = parseInt(cs['height']);
|
grad1 = glossy_grad(r.can, [
|
||||||
|
'50,45%,42%',
|
||||||
r.can.width = (sw * scale);
|
'50,50%,49%',
|
||||||
r.can.height = (sh * scale);
|
'50,47%,47%',
|
||||||
bctx.setTransform(scale, 0, 0, scale, 0, 0);
|
'50,45%,42%'
|
||||||
|
]);
|
||||||
if (!grad1 || gradh != sh) {
|
grad2 = glossy_grad(r.can, [
|
||||||
gradh = sh;
|
'205,10%,16%',
|
||||||
|
'205,15%,20%',
|
||||||
grad1 = bctx.createLinearGradient(0, 0, 0, sh);
|
'205,13%,18%',
|
||||||
grad1.addColorStop(0, 'hsl(50,45%,42%)');
|
'205,10%,16%'
|
||||||
grad1.addColorStop(0.49, 'hsl(50,50%,49%)');
|
]);
|
||||||
grad1.addColorStop(0.50, 'hsl(50,47%,47%)');
|
|
||||||
grad1.addColorStop(1, 'hsl(50,45%,42%)');
|
|
||||||
|
|
||||||
grad2 = bctx.createLinearGradient(0, 0, 0, sh);
|
|
||||||
grad2.addColorStop(0, 'hsl(205,10%,16%)');
|
|
||||||
grad2.addColorStop(0.49, 'hsl(205,15%,20%)');
|
|
||||||
grad2.addColorStop(0.50, 'hsl(205,13%,18%)');
|
|
||||||
grad2.addColorStop(1, 'hsl(205,10%,16%)');
|
|
||||||
}
|
}
|
||||||
bctx.fillStyle = grad2; bctx.fillRect(0, 0, sw, sh);
|
ctx.fillStyle = grad2; ctx.fillRect(0, 0, w, h);
|
||||||
bctx.fillStyle = grad1; bctx.fillRect(0, 0, sw * mp.vol, sh);
|
ctx.fillStyle = grad1; ctx.fillRect(0, 0, w * mp.vol, h);
|
||||||
};
|
};
|
||||||
|
window.addEventListener('resize', onresize);
|
||||||
|
onresize();
|
||||||
|
|
||||||
var rect;
|
var rect;
|
||||||
function mousedown(e) {
|
function mousedown(e) {
|
||||||
rect = r.can.getBoundingClientRect();
|
rect = can.getBoundingClientRect();
|
||||||
mousemove(e);
|
mousemove(e);
|
||||||
}
|
}
|
||||||
function mousemove(e) {
|
function mousemove(e) {
|
||||||
@@ -267,34 +281,34 @@ var vbar = (function () {
|
|||||||
e = e.changedTouches[0];
|
e = e.changedTouches[0];
|
||||||
}
|
}
|
||||||
else if (e.buttons === 0) {
|
else if (e.buttons === 0) {
|
||||||
r.can.onmousemove = null;
|
can.onmousemove = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var x = e.clientX - rect.left;
|
var x = e.clientX - rect.left,
|
||||||
var mul = x * 1.0 / rect.width;
|
mul = x * 1.0 / rect.width;
|
||||||
|
|
||||||
if (mul > 0.98)
|
if (mul > 0.98)
|
||||||
mul = 1;
|
mul = 1;
|
||||||
|
|
||||||
mp.setvol(mul);
|
mp.setvol(mul);
|
||||||
r.draw();
|
r.draw();
|
||||||
}
|
}
|
||||||
r.can.onmousedown = function (e) {
|
can.onmousedown = function (e) {
|
||||||
if (e.button !== 0)
|
if (e.button !== 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
r.can.onmousemove = mousemove;
|
can.onmousemove = mousemove;
|
||||||
mousedown(e);
|
mousedown(e);
|
||||||
};
|
};
|
||||||
r.can.onmouseup = function (e) {
|
can.onmouseup = function (e) {
|
||||||
if (e.button === 0)
|
if (e.button === 0)
|
||||||
r.can.onmousemove = null;
|
can.onmousemove = null;
|
||||||
};
|
};
|
||||||
if (window.Touch) {
|
if (window.Touch) {
|
||||||
r.can.ontouchstart = mousedown;
|
can.ontouchstart = mousedown;
|
||||||
r.can.ontouchmove = mousemove;
|
can.ontouchmove = mousemove;
|
||||||
}
|
}
|
||||||
r.draw();
|
|
||||||
return r;
|
return r;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
@@ -358,8 +372,9 @@ function song_skip(n) {
|
|||||||
return play(0);
|
return play(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
var rect = pbar.pcan.getBoundingClientRect();
|
var rect = pbar.buf.can.getBoundingClientRect(),
|
||||||
var x = e.clientX - rect.left;
|
x = e.clientX - rect.left;
|
||||||
|
|
||||||
seek_au_mul(x * 1.0 / rect.width);
|
seek_au_mul(x * 1.0 / rect.width);
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
@@ -367,8 +382,9 @@ function song_skip(n) {
|
|||||||
|
|
||||||
// periodic tasks
|
// periodic tasks
|
||||||
(function () {
|
(function () {
|
||||||
var nth = 0;
|
var nth = 0,
|
||||||
var last_skip_url = '';
|
last_skip_url = '';
|
||||||
|
|
||||||
var progress_updater = function () {
|
var progress_updater = function () {
|
||||||
if (!mp.au) {
|
if (!mp.au) {
|
||||||
widget.paused(true);
|
widget.paused(true);
|
||||||
@@ -389,8 +405,9 @@ function song_skip(n) {
|
|||||||
|
|
||||||
// switch to next track if approaching the end
|
// switch to next track if approaching the end
|
||||||
if (last_skip_url != mp.au.src) {
|
if (last_skip_url != mp.au.src) {
|
||||||
var pos = mp.au.currentTime;
|
var pos = mp.au.currentTime,
|
||||||
var len = mp.au.duration;
|
len = mp.au.duration;
|
||||||
|
|
||||||
if (pos > 0 && pos > len - 0.1) {
|
if (pos > 0 && pos > len - 0.1) {
|
||||||
last_skip_url = mp.au.src;
|
last_skip_url = mp.au.src;
|
||||||
song_skip(1);
|
song_skip(1);
|
||||||
@@ -532,8 +549,8 @@ function play(tid, seek, call_depth) {
|
|||||||
|
|
||||||
// event from the audio object if something breaks
|
// event from the audio object if something breaks
|
||||||
function evau_error(e) {
|
function evau_error(e) {
|
||||||
var err = '';
|
var err = '',
|
||||||
var eplaya = (e && e.target) || (window.event && window.event.srcElement);
|
eplaya = (e && e.target) || (window.event && window.event.srcElement);
|
||||||
|
|
||||||
switch (eplaya.error.code) {
|
switch (eplaya.error.code) {
|
||||||
case eplaya.error.MEDIA_ERR_ABORTED:
|
case eplaya.error.MEDIA_ERR_ABORTED:
|
||||||
@@ -563,8 +580,9 @@ function evau_error(e) {
|
|||||||
|
|
||||||
// show a fullscreen message
|
// show a fullscreen message
|
||||||
function show_modal(html) {
|
function show_modal(html) {
|
||||||
var body = document.body || document.getElementsByTagName('body')[0];
|
var body = document.body || document.getElementsByTagName('body')[0],
|
||||||
var div = document.createElement('div');
|
div = mknod('div');
|
||||||
|
|
||||||
div.setAttribute('id', 'blocked');
|
div.setAttribute('id', 'blocked');
|
||||||
div.innerHTML = html;
|
div.innerHTML = html;
|
||||||
unblocked();
|
unblocked();
|
||||||
@@ -586,10 +604,10 @@ function autoplay_blocked(seek) {
|
|||||||
'<div id="blk_play"><a href="#" id="blk_go"></a></div>' +
|
'<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>');
|
'<div id="blk_abrt"><a href="#" id="blk_na">Cancel<br />(show file list)</a></div>');
|
||||||
|
|
||||||
var go = ebi('blk_go');
|
var go = ebi('blk_go'),
|
||||||
var na = ebi('blk_na');
|
na = ebi('blk_na'),
|
||||||
|
fn = mp.tracks[mp.au.tid].split(/\//).pop();
|
||||||
|
|
||||||
var fn = mp.tracks[mp.au.tid].split(/\//).pop();
|
|
||||||
fn = uricom_dec(fn.replace(/\+/g, ' '))[0];
|
fn = uricom_dec(fn.replace(/\+/g, ' '))[0];
|
||||||
|
|
||||||
go.textContent = 'Play "' + fn + '"';
|
go.textContent = 'Play "' + fn + '"';
|
||||||
@@ -625,7 +643,7 @@ function autoplay_blocked(seek) {
|
|||||||
|
|
||||||
|
|
||||||
function tree_neigh(n) {
|
function tree_neigh(n) {
|
||||||
var links = document.querySelectorAll('#treeul li>a+a');
|
var links = QSA('#treeul li>a+a');
|
||||||
if (!links.length) {
|
if (!links.length) {
|
||||||
alert('switch to the tree for that');
|
alert('switch to the tree for that');
|
||||||
return;
|
return;
|
||||||
@@ -651,7 +669,7 @@ function tree_neigh(n) {
|
|||||||
|
|
||||||
|
|
||||||
function tree_up() {
|
function tree_up() {
|
||||||
var act = document.querySelector('#treeul a.hl');
|
var act = QS('#treeul a.hl');
|
||||||
if (!act) {
|
if (!act) {
|
||||||
alert('switch to the tree for that');
|
alert('switch to the tree for that');
|
||||||
return;
|
return;
|
||||||
@@ -714,7 +732,7 @@ document.onkeydown = function (e) {
|
|||||||
];
|
];
|
||||||
var oldcfg = [];
|
var oldcfg = [];
|
||||||
|
|
||||||
if (document.querySelector('#srch_form.tags')) {
|
if (QS('#srch_form.tags')) {
|
||||||
sconf.push(["tags",
|
sconf.push(["tags",
|
||||||
["tags", "tags", "tags contains (^=start, end=$)", "46"]
|
["tags", "tags", "tags contains (^=start, end=$)", "46"]
|
||||||
]);
|
]);
|
||||||
@@ -723,13 +741,15 @@ document.onkeydown = function (e) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var trs = [];
|
var trs = [],
|
||||||
var orig_html = null;
|
orig_html = null;
|
||||||
|
|
||||||
for (var a = 0; a < sconf.length; a++) {
|
for (var a = 0; a < sconf.length; a++) {
|
||||||
var html = ['<tr><td><br />' + sconf[a][0] + '</td>'];
|
var html = ['<tr><td><br />' + sconf[a][0] + '</td>'];
|
||||||
for (var b = 1; b < 3; b++) {
|
for (var b = 1; b < 3; b++) {
|
||||||
var hn = "srch_" + sconf[a][b][0];
|
var hn = "srch_" + sconf[a][b][0],
|
||||||
var csp = (sconf[a].length == 2) ? 2 : 1;
|
csp = (sconf[a].length == 2) ? 2 : 1;
|
||||||
|
|
||||||
html.push(
|
html.push(
|
||||||
'<td colspan="' + csp + '"><input id="' + hn + 'c" type="checkbox">\n' +
|
'<td colspan="' + csp + '"><input id="' + hn + 'c" type="checkbox">\n' +
|
||||||
'<label for="' + hn + 'c">' + sconf[a][b][2] + '</label>\n' +
|
'<label for="' + hn + 'c">' + sconf[a][b][2] + '</label>\n' +
|
||||||
@@ -747,7 +767,7 @@ document.onkeydown = function (e) {
|
|||||||
}
|
}
|
||||||
ebi('srch_form').innerHTML = html.join('\n');
|
ebi('srch_form').innerHTML = html.join('\n');
|
||||||
|
|
||||||
var o = document.querySelectorAll('#op_search input');
|
var o = QSA('#op_search input');
|
||||||
for (var a = 0; a < o.length; a++) {
|
for (var a = 0; a < o.length; a++) {
|
||||||
o[a].oninput = ev_search_input;
|
o[a].oninput = ev_search_input;
|
||||||
}
|
}
|
||||||
@@ -758,28 +778,30 @@ document.onkeydown = function (e) {
|
|||||||
o.style.color = err ? '#f09' : '#c90';
|
o.style.color = err ? '#f09' : '#c90';
|
||||||
}
|
}
|
||||||
|
|
||||||
var search_timeout;
|
var search_timeout,
|
||||||
var search_in_progress = 0;
|
search_in_progress = 0;
|
||||||
|
|
||||||
function ev_search_input() {
|
function ev_search_input() {
|
||||||
var v = this.value;
|
var v = this.value,
|
||||||
var id = this.getAttribute('id');
|
id = this.getAttribute('id');
|
||||||
|
|
||||||
if (id.slice(-1) == 'v') {
|
if (id.slice(-1) == 'v') {
|
||||||
var chk = ebi(id.slice(0, -1) + 'c');
|
var chk = ebi(id.slice(0, -1) + 'c');
|
||||||
chk.checked = ((v + '').length > 0);
|
chk.checked = ((v + '').length > 0);
|
||||||
}
|
}
|
||||||
clearTimeout(search_timeout);
|
clearTimeout(search_timeout);
|
||||||
var now = new Date().getTime();
|
if (Date.now() - search_in_progress > 30 * 1000)
|
||||||
if (now - search_in_progress > 30 * 1000)
|
|
||||||
search_timeout = setTimeout(do_search, 200);
|
search_timeout = setTimeout(do_search, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
function do_search() {
|
function do_search() {
|
||||||
search_in_progress = new Date().getTime();
|
search_in_progress = Date.now();
|
||||||
srch_msg(false, "searching...");
|
srch_msg(false, "searching...");
|
||||||
clearTimeout(search_timeout);
|
clearTimeout(search_timeout);
|
||||||
var params = {};
|
|
||||||
var o = document.querySelectorAll('#op_search input[type="text"]');
|
var params = {},
|
||||||
|
o = QSA('#op_search input[type="text"]');
|
||||||
|
|
||||||
for (var a = 0; a < o.length; a++) {
|
for (var a = 0; a < o.length; a++) {
|
||||||
var chk = ebi(o[a].getAttribute('id').slice(0, -1) + 'c');
|
var chk = ebi(o[a].getAttribute('id').slice(0, -1) + 'c');
|
||||||
if (!chk.checked)
|
if (!chk.checked)
|
||||||
@@ -792,7 +814,7 @@ document.onkeydown = function (e) {
|
|||||||
xhr.open('POST', '/?srch', true);
|
xhr.open('POST', '/?srch', true);
|
||||||
xhr.setRequestHeader('Content-Type', 'text/plain');
|
xhr.setRequestHeader('Content-Type', 'text/plain');
|
||||||
xhr.onreadystatechange = xhr_search_results;
|
xhr.onreadystatechange = xhr_search_results;
|
||||||
xhr.ts = new Date().getTime();
|
xhr.ts = Date.now();
|
||||||
xhr.send(JSON.stringify(params));
|
xhr.send(JSON.stringify(params));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -982,12 +1004,13 @@ var treectl = (function () {
|
|||||||
if (!entreed || treectl.hidden)
|
if (!entreed || treectl.hidden)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var q = '#tree';
|
var q = '#tree',
|
||||||
var nq = 0;
|
nq = 0;
|
||||||
|
|
||||||
while (dyn) {
|
while (dyn) {
|
||||||
nq++;
|
nq++;
|
||||||
q += '>ul>li';
|
q += '>ul>li';
|
||||||
if (!document.querySelector(q))
|
if (!QS(q))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var w = treesz + nq;
|
var w = treesz + nq;
|
||||||
@@ -1001,7 +1024,7 @@ var treectl = (function () {
|
|||||||
xhr.top = top;
|
xhr.top = top;
|
||||||
xhr.dst = dst;
|
xhr.dst = dst;
|
||||||
xhr.rst = rst;
|
xhr.rst = rst;
|
||||||
xhr.ts = new Date().getTime();
|
xhr.ts = Date.now();
|
||||||
xhr.open('GET', dst + '?tree=' + top, true);
|
xhr.open('GET', dst + '?tree=' + top, true);
|
||||||
xhr.onreadystatechange = recvtree;
|
xhr.onreadystatechange = recvtree;
|
||||||
xhr.send();
|
xhr.send();
|
||||||
@@ -1026,10 +1049,11 @@ var treectl = (function () {
|
|||||||
|
|
||||||
var top = this.top == '.' ? this.dst : this.top,
|
var top = this.top == '.' ? this.dst : this.top,
|
||||||
name = uricom_dec(top.split('/').slice(-2)[0])[0],
|
name = uricom_dec(top.split('/').slice(-2)[0])[0],
|
||||||
rtop = top.replace(/^\/+/, "");
|
rtop = top.replace(/^\/+/, ""),
|
||||||
|
res;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var res = JSON.parse(this.responseText);
|
res = JSON.parse(this.responseText);
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
return;
|
return;
|
||||||
@@ -1045,7 +1069,7 @@ var treectl = (function () {
|
|||||||
esc(top) + '">' + esc(name) +
|
esc(top) + '">' + esc(name) +
|
||||||
"</a>\n<ul>\n" + html + "</ul>";
|
"</a>\n<ul>\n" + html + "</ul>";
|
||||||
|
|
||||||
var links = document.querySelectorAll('#treeul a+a');
|
var links = QSA('#treeul a+a');
|
||||||
for (var a = 0, aa = links.length; a < aa; a++) {
|
for (var a = 0, aa = links.length; a < aa; a++) {
|
||||||
if (links[a].getAttribute('href') == top) {
|
if (links[a].getAttribute('href') == top) {
|
||||||
var o = links[a].parentNode;
|
var o = links[a].parentNode;
|
||||||
@@ -1054,21 +1078,22 @@ var treectl = (function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.querySelector('#treeul>li>a+a').textContent = '[root]';
|
QS('#treeul>li>a+a').textContent = '[root]';
|
||||||
despin('#tree');
|
despin('#tree');
|
||||||
reload_tree();
|
reload_tree();
|
||||||
onresize();
|
onresize();
|
||||||
}
|
}
|
||||||
|
|
||||||
function reload_tree() {
|
function reload_tree() {
|
||||||
var cdir = get_evpath();
|
var cdir = get_evpath(),
|
||||||
var links = document.querySelectorAll('#treeul a+a');
|
links = QSA('#treeul a+a');
|
||||||
|
|
||||||
for (var a = 0, aa = links.length; a < aa; a++) {
|
for (var a = 0, aa = links.length; a < aa; a++) {
|
||||||
var href = links[a].getAttribute('href');
|
var href = links[a].getAttribute('href');
|
||||||
links[a].setAttribute('class', href == cdir ? 'hl' : '');
|
links[a].setAttribute('class', href == cdir ? 'hl' : '');
|
||||||
links[a].onclick = treego;
|
links[a].onclick = treego;
|
||||||
}
|
}
|
||||||
links = document.querySelectorAll('#treeul li>a:first-child');
|
links = QSA('#treeul li>a:first-child');
|
||||||
for (var a = 0, aa = links.length; a < aa; a++) {
|
for (var a = 0, aa = links.length; a < aa; a++) {
|
||||||
links[a].setAttribute('dst', links[a].nextSibling.getAttribute('href'));
|
links[a].setAttribute('dst', links[a].nextSibling.getAttribute('href'));
|
||||||
links[a].onclick = treegrow;
|
links[a].onclick = treegrow;
|
||||||
@@ -1089,7 +1114,7 @@ var treectl = (function () {
|
|||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.top = url;
|
xhr.top = url;
|
||||||
xhr.hpush = hpush;
|
xhr.hpush = hpush;
|
||||||
xhr.ts = new Date().getTime();
|
xhr.ts = Date.now();
|
||||||
xhr.open('GET', xhr.top + '?ls', true);
|
xhr.open('GET', xhr.top + '?ls', true);
|
||||||
xhr.onreadystatechange = recvls;
|
xhr.onreadystatechange = recvls;
|
||||||
xhr.send();
|
xhr.send();
|
||||||
@@ -1139,12 +1164,13 @@ var treectl = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ebi('srv_info').innerHTML = '<span>' + res.srvinf + '</span>';
|
ebi('srv_info').innerHTML = '<span>' + res.srvinf + '</span>';
|
||||||
var nodes = res.dirs.concat(res.files);
|
|
||||||
nodes = sortfiles(nodes);
|
|
||||||
|
|
||||||
var top = this.top;
|
var top = this.top,
|
||||||
var html = mk_files_header(res.taglist);
|
nodes = res.dirs.concat(res.files),
|
||||||
|
html = mk_files_header(res.taglist);
|
||||||
|
|
||||||
html.push('<tbody>');
|
html.push('<tbody>');
|
||||||
|
nodes = sortfiles(nodes);
|
||||||
for (var a = 0; a < nodes.length; a++) {
|
for (var a = 0; a < nodes.length; a++) {
|
||||||
var r = nodes[a],
|
var r = nodes[a],
|
||||||
ln = ['<tr><td>' + r.lead + '</td><td><a href="' +
|
ln = ['<tr><td>' + r.lead + '</td><td><a href="' +
|
||||||
@@ -1262,16 +1288,16 @@ var treectl = (function () {
|
|||||||
|
|
||||||
function enspin(sel) {
|
function enspin(sel) {
|
||||||
despin(sel);
|
despin(sel);
|
||||||
var d = document.createElement('div');
|
var d = mknod('div');
|
||||||
d.setAttribute('class', 'dumb_loader_thing');
|
d.setAttribute('class', 'dumb_loader_thing');
|
||||||
d.innerHTML = '🌲';
|
d.innerHTML = '🌲';
|
||||||
var tgt = document.querySelector(sel);
|
var tgt = QS(sel);
|
||||||
tgt.insertBefore(d, tgt.childNodes[0]);
|
tgt.insertBefore(d, tgt.childNodes[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function despin(sel) {
|
function despin(sel) {
|
||||||
var o = document.querySelectorAll(sel + '>.dumb_loader_thing');
|
var o = QSA(sel + '>.dumb_loader_thing');
|
||||||
for (var a = o.length - 1; a >= 0; a--)
|
for (var a = o.length - 1; a >= 0; a--)
|
||||||
o[a].parentNode.removeChild(o[a]);
|
o[a].parentNode.removeChild(o[a]);
|
||||||
}
|
}
|
||||||
@@ -1280,17 +1306,17 @@ function despin(sel) {
|
|||||||
function apply_perms(perms) {
|
function apply_perms(perms) {
|
||||||
perms = perms || [];
|
perms = perms || [];
|
||||||
|
|
||||||
var o = document.querySelectorAll('#ops>a[data-perm]');
|
var o = QSA('#ops>a[data-perm]');
|
||||||
for (var a = 0; a < o.length; a++)
|
for (var a = 0; a < o.length; a++)
|
||||||
o[a].style.display = 'none';
|
o[a].style.display = 'none';
|
||||||
|
|
||||||
for (var a = 0; a < perms.length; a++) {
|
for (var a = 0; a < perms.length; a++) {
|
||||||
o = document.querySelectorAll('#ops>a[data-perm="' + perms[a] + '"]');
|
o = QSA('#ops>a[data-perm="' + perms[a] + '"]');
|
||||||
for (var b = 0; b < o.length; b++)
|
for (var b = 0; b < o.length; b++)
|
||||||
o[b].style.display = 'inline';
|
o[b].style.display = 'inline';
|
||||||
}
|
}
|
||||||
|
|
||||||
var act = document.querySelector('#ops>a.act');
|
var act = QS('#ops>a.act');
|
||||||
if (act) {
|
if (act) {
|
||||||
var areq = act.getAttribute('data-perm');
|
var areq = act.getAttribute('data-perm');
|
||||||
if (areq && !has(perms, areq))
|
if (areq && !has(perms, areq))
|
||||||
@@ -1299,8 +1325,9 @@ function apply_perms(perms) {
|
|||||||
|
|
||||||
document.body.setAttribute('perms', perms.join(' '));
|
document.body.setAttribute('perms', perms.join(' '));
|
||||||
|
|
||||||
var have_write = has(perms, "write");
|
var have_write = has(perms, "write"),
|
||||||
var tds = document.querySelectorAll('#u2conf td');
|
tds = QSA('#u2conf td');
|
||||||
|
|
||||||
for (var a = 0; a < tds.length; a++) {
|
for (var a = 0; a < tds.length; a++) {
|
||||||
tds[a].style.display =
|
tds[a].style.display =
|
||||||
(have_write || tds[a].getAttribute('data-perm') == 'read') ?
|
(have_write || tds[a].getAttribute('data-perm') == 'read') ?
|
||||||
@@ -1313,9 +1340,10 @@ function apply_perms(perms) {
|
|||||||
|
|
||||||
|
|
||||||
function find_file_col(txt) {
|
function find_file_col(txt) {
|
||||||
var tds = ebi('files').tHead.getElementsByTagName('th');
|
var i = -1,
|
||||||
var i = -1;
|
min = false,
|
||||||
var min = false;
|
tds = ebi('files').tHead.getElementsByTagName('th');
|
||||||
|
|
||||||
for (var a = 0; a < tds.length; a++) {
|
for (var a = 0; a < tds.length; a++) {
|
||||||
var spans = tds[a].getElementsByTagName('span');
|
var spans = tds[a].getElementsByTagName('span');
|
||||||
if (spans.length && spans[0].textContent == txt) {
|
if (spans.length && spans[0].textContent == txt) {
|
||||||
@@ -1340,8 +1368,9 @@ function mk_files_header(taglist) {
|
|||||||
'<th name="sz" sort="int"><span>Size</span></th>'
|
'<th name="sz" sort="int"><span>Size</span></th>'
|
||||||
];
|
];
|
||||||
for (var a = 0; a < taglist.length; a++) {
|
for (var a = 0; a < taglist.length; a++) {
|
||||||
var tag = taglist[a];
|
var tag = taglist[a],
|
||||||
var c1 = tag.slice(0, 1).toUpperCase();
|
c1 = tag.slice(0, 1).toUpperCase();
|
||||||
|
|
||||||
tag = c1 + tag.slice(1);
|
tag = c1 + tag.slice(1);
|
||||||
if (c1 == '.')
|
if (c1 == '.')
|
||||||
tag = '<th name="tags/' + tag + '" sort="int"><span>' + tag.slice(1);
|
tag = '<th name="tags/' + tag + '" sort="int"><span>' + tag.slice(1);
|
||||||
@@ -1363,10 +1392,11 @@ var filecols = (function () {
|
|||||||
var hidden = jread('filecols', []);
|
var hidden = jread('filecols', []);
|
||||||
|
|
||||||
var add_btns = function () {
|
var add_btns = function () {
|
||||||
var ths = document.querySelectorAll('#files th>span');
|
var ths = QSA('#files th>span');
|
||||||
for (var a = 0, aa = ths.length; a < aa; a++) {
|
for (var a = 0, aa = ths.length; a < aa; a++) {
|
||||||
var th = ths[a].parentElement;
|
var th = ths[a].parentElement,
|
||||||
var is_hidden = has(hidden, ths[a].textContent);
|
is_hidden = has(hidden, ths[a].textContent);
|
||||||
|
|
||||||
th.innerHTML = '<div class="cfg"><a href="#">' +
|
th.innerHTML = '<div class="cfg"><a href="#">' +
|
||||||
(is_hidden ? '+' : '-') + '</a></div>' + ths[a].outerHTML;
|
(is_hidden ? '+' : '-') + '</a></div>' + ths[a].outerHTML;
|
||||||
|
|
||||||
@@ -1378,7 +1408,7 @@ var filecols = (function () {
|
|||||||
add_btns();
|
add_btns();
|
||||||
|
|
||||||
var ohidden = [],
|
var ohidden = [],
|
||||||
ths = document.querySelectorAll('#files th'),
|
ths = QSA('#files th'),
|
||||||
ncols = ths.length;
|
ncols = ths.length;
|
||||||
|
|
||||||
for (var a = 0; a < ncols; a++) {
|
for (var a = 0; a < ncols; a++) {
|
||||||
@@ -1396,8 +1426,9 @@ var filecols = (function () {
|
|||||||
clmod(ths[a], 'min', cls)
|
clmod(ths[a], 'min', cls)
|
||||||
}
|
}
|
||||||
for (var a = 0; a < ncols; a++) {
|
for (var a = 0; a < ncols; a++) {
|
||||||
var cls = has(ohidden, a) ? 'min' : '';
|
var cls = has(ohidden, a) ? 'min' : '',
|
||||||
var tds = document.querySelectorAll('#files>tbody>tr>td:nth-child(' + (a + 1) + ')');
|
tds = QSA('#files>tbody>tr>td:nth-child(' + (a + 1) + ')');
|
||||||
|
|
||||||
for (var b = 0, bb = tds.length; b < bb; b++) {
|
for (var b = 0, bb = tds.length; b < bb; b++) {
|
||||||
tds[b].setAttribute('class', cls);
|
tds[b].setAttribute('class', cls);
|
||||||
if (a < 2)
|
if (a < 2)
|
||||||
@@ -1475,9 +1506,9 @@ var mukey = (function () {
|
|||||||
"6m ", "7m ", "8m ", "9m ", "10m", "11m", "12m", "1m ", "2m ", "3m ", "4m ", "5m "
|
"6m ", "7m ", "8m ", "9m ", "10m", "11m", "12m", "1m ", "2m ", "3m ", "4m ", "5m "
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
var map = {};
|
var map = {},
|
||||||
|
html = [];
|
||||||
|
|
||||||
var html = [];
|
|
||||||
for (var k in maps) {
|
for (var k in maps) {
|
||||||
if (!maps.hasOwnProperty(k))
|
if (!maps.hasOwnProperty(k))
|
||||||
continue;
|
continue;
|
||||||
@@ -1551,7 +1582,7 @@ var mukey = (function () {
|
|||||||
ebi('key_' + notation).checked = true;
|
ebi('key_' + notation).checked = true;
|
||||||
load_notation(notation);
|
load_notation(notation);
|
||||||
|
|
||||||
var o = document.querySelectorAll('#key_notation input');
|
var o = QSA('#key_notation input');
|
||||||
for (var a = 0; a < o.length; a++) {
|
for (var a = 0; a < o.length; a++) {
|
||||||
o[a].onchange = set_key_notation;
|
o[a].onchange = set_key_notation;
|
||||||
}
|
}
|
||||||
@@ -1563,7 +1594,7 @@ var mukey = (function () {
|
|||||||
|
|
||||||
|
|
||||||
function addcrc() {
|
function addcrc() {
|
||||||
var links = document.querySelectorAll(
|
var links = QSA(
|
||||||
'#files>tbody>tr>td:first-child+td>' + (
|
'#files>tbody>tr>td:first-child+td>' + (
|
||||||
ebi('unsearch') ? 'div>a:last-child' : 'a'));
|
ebi('unsearch') ? 'div>a:last-child' : 'a'));
|
||||||
|
|
||||||
@@ -1586,7 +1617,7 @@ function addcrc() {
|
|||||||
o.setAttribute('class', tt ? '' : 'off');
|
o.setAttribute('class', tt ? '' : 'off');
|
||||||
}
|
}
|
||||||
|
|
||||||
var btns = document.querySelectorAll('#ops, #ops>a');
|
var btns = QSA('#ops, #ops>a');
|
||||||
for (var a = 0; a < btns.length; a++) {
|
for (var a = 0; a < btns.length; a++) {
|
||||||
btns[a].onmouseenter = set_tooltip;
|
btns[a].onmouseenter = set_tooltip;
|
||||||
}
|
}
|
||||||
@@ -1638,7 +1669,7 @@ var arcfmt = (function () {
|
|||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
var arg = arcv[arcfmts.indexOf(fmt)],
|
var arg = arcv[arcfmts.indexOf(fmt)],
|
||||||
tds = document.querySelectorAll('#files tbody td:first-child a');
|
tds = QSA('#files tbody td:first-child a');
|
||||||
|
|
||||||
for (var a = 0, aa = tds.length; a < aa; a++) {
|
for (var a = 0, aa = tds.length; a < aa; a++) {
|
||||||
var o = tds[a], txt = o.textContent, href = o.getAttribute('href');
|
var o = tds[a], txt = o.textContent, href = o.getAttribute('href');
|
||||||
@@ -1672,7 +1703,7 @@ var arcfmt = (function () {
|
|||||||
try_render();
|
try_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
var o = document.querySelectorAll('#arc_fmt input');
|
var o = QSA('#arc_fmt input');
|
||||||
for (var a = 0; a < o.length; a++) {
|
for (var a = 0; a < o.length; a++) {
|
||||||
o[a].onchange = change_fmt;
|
o[a].onchange = change_fmt;
|
||||||
}
|
}
|
||||||
@@ -1685,8 +1716,9 @@ var arcfmt = (function () {
|
|||||||
|
|
||||||
var msel = (function () {
|
var msel = (function () {
|
||||||
function getsel() {
|
function getsel() {
|
||||||
var names = [];
|
var names = [],
|
||||||
var links = document.querySelectorAll('#files tbody tr.sel td:nth-child(2) a');
|
links = QSA('#files tbody tr.sel td:nth-child(2) a');
|
||||||
|
|
||||||
for (var a = 0, aa = links.length; a < aa; a++)
|
for (var a = 0, aa = links.length; a < aa; a++)
|
||||||
names.push(links[a].getAttribute('href').replace(/\/$/, "").split('/').slice(-1));
|
names.push(links[a].getAttribute('href').replace(/\/$/, "").split('/').slice(-1));
|
||||||
|
|
||||||
@@ -1703,7 +1735,7 @@ var msel = (function () {
|
|||||||
}
|
}
|
||||||
function evsel(e, fun) {
|
function evsel(e, fun) {
|
||||||
ev(e);
|
ev(e);
|
||||||
var trs = document.querySelectorAll('#files tbody tr');
|
var trs = QSA('#files tbody tr');
|
||||||
for (var a = 0, aa = trs.length; a < aa; a++)
|
for (var a = 0, aa = trs.length; a < aa; a++)
|
||||||
clmod(trs[a], 'sel', fun);
|
clmod(trs[a], 'sel', fun);
|
||||||
selui();
|
selui();
|
||||||
@@ -1716,10 +1748,11 @@ var msel = (function () {
|
|||||||
};
|
};
|
||||||
ebi('selzip').onclick = function (e) {
|
ebi('selzip').onclick = function (e) {
|
||||||
ev(e);
|
ev(e);
|
||||||
var names = getsel();
|
var names = getsel(),
|
||||||
var arg = ebi('selzip').getAttribute('fmt');
|
arg = ebi('selzip').getAttribute('fmt'),
|
||||||
var txt = names.join('\n');
|
txt = names.join('\n'),
|
||||||
var frm = document.createElement('form');
|
frm = mknod('form');
|
||||||
|
|
||||||
frm.setAttribute('action', '?' + arg);
|
frm.setAttribute('action', '?' + arg);
|
||||||
frm.setAttribute('method', 'post');
|
frm.setAttribute('method', 'post');
|
||||||
frm.setAttribute('target', '_blank');
|
frm.setAttribute('target', '_blank');
|
||||||
@@ -1728,7 +1761,7 @@ var msel = (function () {
|
|||||||
'<textarea name="files" id="ziptxt"></textarea>';
|
'<textarea name="files" id="ziptxt"></textarea>';
|
||||||
frm.style.display = 'none';
|
frm.style.display = 'none';
|
||||||
|
|
||||||
var oldform = document.querySelector('#widgeti>form');
|
var oldform = QS('#widgeti>form');
|
||||||
if (oldform)
|
if (oldform)
|
||||||
oldform.parentNode.removeChild(oldform);
|
oldform.parentNode.removeChild(oldform);
|
||||||
|
|
||||||
@@ -1739,7 +1772,7 @@ var msel = (function () {
|
|||||||
frm.submit();
|
frm.submit();
|
||||||
};
|
};
|
||||||
function render() {
|
function render() {
|
||||||
var tds = document.querySelectorAll('#files tbody td+td+td');
|
var tds = QSA('#files tbody td+td+td');
|
||||||
for (var a = 0, aa = tds.length; a < aa; a++) {
|
for (var a = 0, aa = tds.length; a < aa; a++) {
|
||||||
tds[a].onclick = seltgl;
|
tds[a].onclick = seltgl;
|
||||||
}
|
}
|
||||||
@@ -1770,21 +1803,22 @@ function reload_mp() {
|
|||||||
function reload_browser(not_mp) {
|
function reload_browser(not_mp) {
|
||||||
filecols.set_style();
|
filecols.set_style();
|
||||||
|
|
||||||
var parts = get_evpath().split('/');
|
var parts = get_evpath().split('/'),
|
||||||
var rm = document.querySelectorAll('#path>a+a+a');
|
rm = QSA('#path>a+a+a');
|
||||||
|
|
||||||
for (a = rm.length - 1; a >= 0; a--)
|
for (a = rm.length - 1; a >= 0; a--)
|
||||||
rm[a].parentNode.removeChild(rm[a]);
|
rm[a].parentNode.removeChild(rm[a]);
|
||||||
|
|
||||||
var link = '/';
|
var link = '/';
|
||||||
for (var a = 1; a < parts.length - 1; a++) {
|
for (var a = 1; a < parts.length - 1; a++) {
|
||||||
link += parts[a] + '/';
|
link += parts[a] + '/';
|
||||||
var o = document.createElement('a');
|
var o = mknod('a');
|
||||||
o.setAttribute('href', link);
|
o.setAttribute('href', link);
|
||||||
o.textContent = uricom_dec(parts[a])[0];
|
o.textContent = uricom_dec(parts[a])[0];
|
||||||
ebi('path').appendChild(o);
|
ebi('path').appendChild(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
var oo = document.querySelectorAll('#files>tbody>tr>td:nth-child(3)');
|
var oo = QSA('#files>tbody>tr>td:nth-child(3)');
|
||||||
for (var a = 0, aa = oo.length; a < aa; a++) {
|
for (var a = 0, aa = oo.length; a < aa; a++) {
|
||||||
var sz = oo[a].textContent.replace(/ /g, ""),
|
var sz = oo[a].textContent.replace(/ /g, ""),
|
||||||
hsz = sz.replace(/\B(?=(\d{3})+(?!\d))/g, " ");
|
hsz = sz.replace(/\B(?=(\d{3})+(?!\d))/g, " ");
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ pre code:last-child {
|
|||||||
pre code::before {
|
pre code::before {
|
||||||
content: counter(precode);
|
content: counter(precode);
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font-size: .75em;
|
font-size: .75em;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ function statify(obj) {
|
|||||||
var ua = navigator.userAgent;
|
var ua = navigator.userAgent;
|
||||||
if (ua.indexOf(') Gecko/') !== -1 && /Linux| Mac /.exec(ua)) {
|
if (ua.indexOf(') Gecko/') !== -1 && /Linux| Mac /.exec(ua)) {
|
||||||
// necessary on ff-68.7 at least
|
// necessary on ff-68.7 at least
|
||||||
var s = document.createElement('style');
|
var s = mknod('style');
|
||||||
s.innerHTML = '@page { margin: .5in .6in .8in .6in; }';
|
s.innerHTML = '@page { margin: .5in .6in .8in .6in; }';
|
||||||
console.log(s.innerHTML);
|
console.log(s.innerHTML);
|
||||||
document.head.appendChild(s);
|
document.head.appendChild(s);
|
||||||
@@ -175,12 +175,12 @@ function md_plug_err(ex, js) {
|
|||||||
msg = "Line " + ln + ", " + msg;
|
msg = "Line " + ln + ", " + msg;
|
||||||
var lns = js.split('\n');
|
var lns = js.split('\n');
|
||||||
if (ln < lns.length) {
|
if (ln < lns.length) {
|
||||||
o = document.createElement('span');
|
o = mknod('span');
|
||||||
o.style.cssText = 'color:#ac2;font-size:.9em;font-family:scp;display:block';
|
o.style.cssText = 'color:#ac2;font-size:.9em;font-family:scp;display:block';
|
||||||
o.textContent = lns[ln - 1];
|
o.textContent = lns[ln - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errbox = document.createElement('div');
|
errbox = mknod('div');
|
||||||
errbox.setAttribute('id', 'md_errbox');
|
errbox.setAttribute('id', 'md_errbox');
|
||||||
errbox.style.cssText = 'position:absolute;top:0;left:0;padding:1em .5em;background:#2b2b2b;color:#fc5'
|
errbox.style.cssText = 'position:absolute;top:0;left:0;padding:1em .5em;background:#2b2b2b;color:#fc5'
|
||||||
errbox.textContent = msg;
|
errbox.textContent = msg;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ var dom_sbs = ebi('sbs');
|
|||||||
var dom_nsbs = ebi('nsbs');
|
var dom_nsbs = ebi('nsbs');
|
||||||
var dom_tbox = ebi('toolsbox');
|
var dom_tbox = ebi('toolsbox');
|
||||||
var dom_ref = (function () {
|
var dom_ref = (function () {
|
||||||
var d = document.createElement('div');
|
var d = mknod('div');
|
||||||
d.setAttribute('id', 'mtr');
|
d.setAttribute('id', 'mtr');
|
||||||
dom_swrap.appendChild(d);
|
dom_swrap.appendChild(d);
|
||||||
d = ebi('mtr');
|
d = ebi('mtr');
|
||||||
@@ -71,7 +71,7 @@ var map_src = [];
|
|||||||
var map_pre = [];
|
var map_pre = [];
|
||||||
function genmap(dom, oldmap) {
|
function genmap(dom, oldmap) {
|
||||||
var find = nlines;
|
var find = nlines;
|
||||||
while (oldmap && find --> 0) {
|
while (oldmap && find-- > 0) {
|
||||||
var tmap = genmapq(dom, '*[data-ln="' + find + '"]');
|
var tmap = genmapq(dom, '*[data-ln="' + find + '"]');
|
||||||
if (!tmap || !tmap.length)
|
if (!tmap || !tmap.length)
|
||||||
continue;
|
continue;
|
||||||
@@ -94,7 +94,7 @@ var nlines = 0;
|
|||||||
var draw_md = (function () {
|
var draw_md = (function () {
|
||||||
var delay = 1;
|
var delay = 1;
|
||||||
function draw_md() {
|
function draw_md() {
|
||||||
var t0 = new Date().getTime();
|
var t0 = Date.now();
|
||||||
var src = dom_src.value;
|
var src = dom_src.value;
|
||||||
convert_markdown(src, dom_pre);
|
convert_markdown(src, dom_pre);
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ var draw_md = (function () {
|
|||||||
|
|
||||||
cls(ebi('save'), 'disabled', src == server_md);
|
cls(ebi('save'), 'disabled', src == server_md);
|
||||||
|
|
||||||
var t1 = new Date().getTime();
|
var t1 = Date.now();
|
||||||
delay = t1 - t0 > 100 ? 25 : 1;
|
delay = t1 - t0 > 100 ? 25 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ function Modpoll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log('modpoll...');
|
console.log('modpoll...');
|
||||||
var url = (document.location + '').split('?')[0] + '?raw&_=' + new Date().getTime();
|
var url = (document.location + '').split('?')[0] + '?raw&_=' + Date.now();
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.modpoll = this;
|
xhr.modpoll = this;
|
||||||
xhr.open('GET', url, true);
|
xhr.open('GET', url, true);
|
||||||
@@ -399,7 +399,7 @@ function save_cb() {
|
|||||||
|
|
||||||
function run_savechk(lastmod, txt, btn, ntry) {
|
function run_savechk(lastmod, txt, btn, ntry) {
|
||||||
// download the saved doc from the server and compare
|
// download the saved doc from the server and compare
|
||||||
var url = (document.location + '').split('?')[0] + '?raw&_=' + new Date().getTime();
|
var url = (document.location + '').split('?')[0] + '?raw&_=' + Date.now();
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', url, true);
|
xhr.open('GET', url, true);
|
||||||
xhr.responseType = 'text';
|
xhr.responseType = 'text';
|
||||||
@@ -455,7 +455,7 @@ function toast(autoclose, style, width, msg) {
|
|||||||
ok.parentNode.removeChild(ok);
|
ok.parentNode.removeChild(ok);
|
||||||
|
|
||||||
style = "width:" + width + "em;left:calc(50% - " + (width / 2) + "em);" + style;
|
style = "width:" + width + "em;left:calc(50% - " + (width / 2) + "em);" + style;
|
||||||
ok = document.createElement('div');
|
ok = mknod('div');
|
||||||
ok.setAttribute('id', 'toast');
|
ok.setAttribute('id', 'toast');
|
||||||
ok.setAttribute('style', style);
|
ok.setAttribute('style', style);
|
||||||
ok.innerHTML = msg;
|
ok.innerHTML = msg;
|
||||||
@@ -1049,7 +1049,7 @@ action_stack = (function () {
|
|||||||
var p1 = from.length,
|
var p1 = from.length,
|
||||||
p2 = to.length;
|
p2 = to.length;
|
||||||
|
|
||||||
while (p1 --> 0 && p2 --> 0)
|
while (p1-- > 0 && p2-- > 0)
|
||||||
if (from[p1] != to[p2])
|
if (from[p1] != to[p2])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ var mde = (function () {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
function set_jumpto() {
|
function set_jumpto() {
|
||||||
document.querySelector('.editor-preview-side').onclick = jumpto;
|
QS('.editor-preview-side').onclick = jumpto;
|
||||||
}
|
}
|
||||||
|
|
||||||
function jumpto(ev) {
|
function jumpto(ev) {
|
||||||
@@ -94,7 +94,7 @@ function md_changed(mde, on_srv) {
|
|||||||
window.md_saved = mde.value();
|
window.md_saved = mde.value();
|
||||||
|
|
||||||
var md_now = mde.value();
|
var md_now = mde.value();
|
||||||
var save_btn = document.querySelector('.editor-toolbar button.save');
|
var save_btn = QS('.editor-toolbar button.save');
|
||||||
|
|
||||||
if (md_now == window.md_saved)
|
if (md_now == window.md_saved)
|
||||||
save_btn.classList.add('disabled');
|
save_btn.classList.add('disabled');
|
||||||
@@ -105,7 +105,7 @@ function md_changed(mde, on_srv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function save(mde) {
|
function save(mde) {
|
||||||
var save_btn = document.querySelector('.editor-toolbar button.save');
|
var save_btn = QS('.editor-toolbar button.save');
|
||||||
if (save_btn.classList.contains('disabled')) {
|
if (save_btn.classList.contains('disabled')) {
|
||||||
alert('there is nothing to save');
|
alert('there is nothing to save');
|
||||||
return;
|
return;
|
||||||
@@ -212,7 +212,7 @@ function save_chk() {
|
|||||||
last_modified = this.lastmod;
|
last_modified = this.lastmod;
|
||||||
md_changed(this.mde, true);
|
md_changed(this.mde, true);
|
||||||
|
|
||||||
var ok = document.createElement('div');
|
var ok = mknod('div');
|
||||||
ok.setAttribute('style', 'font-size:6em;font-family:serif;font-weight:bold;color:#cf6;background:#444;border-radius:.3em;padding:.6em 0;position:fixed;top:30%;left:calc(50% - 2em);width:4em;text-align:center;z-index:9001;transition:opacity 0.2s ease-in-out;opacity:1');
|
ok.setAttribute('style', 'font-size:6em;font-family:serif;font-weight:bold;color:#cf6;background:#444;border-radius:.3em;padding:.6em 0;position:fixed;top:30%;left:calc(50% - 2em);width:4em;text-align:center;z-index:9001;transition:opacity 0.2s ease-in-out;opacity:1');
|
||||||
ok.innerHTML = 'OK✔️';
|
ok.innerHTML = 'OK✔️';
|
||||||
var parent = ebi('m');
|
var parent = ebi('m');
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ function up2k_flagbus() {
|
|||||||
dbg(who, 'hi me (??)');
|
dbg(who, 'hi me (??)');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
flag.act = new Date().getTime();
|
flag.act = Date.now();
|
||||||
if (what == "want") {
|
if (what == "want") {
|
||||||
// lowest id wins, don't care if that's us
|
// lowest id wins, don't care if that's us
|
||||||
if (who < flag.id) {
|
if (who < flag.id) {
|
||||||
@@ -209,7 +209,7 @@ function U2pvis(act, btns) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.perc = function (bd, bd0, sz, t0) {
|
this.perc = function (bd, bd0, sz, t0) {
|
||||||
var td = new Date().getTime() - t0,
|
var td = Date.now() - t0,
|
||||||
p = bd * 100.0 / sz,
|
p = bd * 100.0 / sz,
|
||||||
nb = bd - bd0,
|
nb = bd - bd0,
|
||||||
spd = nb / (td / 1000),
|
spd = nb / (td / 1000),
|
||||||
@@ -292,11 +292,11 @@ function U2pvis(act, btns) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.bzw = function () {
|
this.bzw = function () {
|
||||||
var first = document.querySelector('#u2tab>tbody>tr:first-child');
|
var first = QS('#u2tab>tbody>tr:first-child');
|
||||||
if (!first)
|
if (!first)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var last = document.querySelector('#u2tab>tbody>tr:last-child');
|
var last = QS('#u2tab>tbody>tr:last-child');
|
||||||
first = parseInt(first.getAttribute('id').slice(1));
|
first = parseInt(first.getAttribute('id').slice(1));
|
||||||
last = parseInt(last.getAttribute('id').slice(1));
|
last = parseInt(last.getAttribute('id').slice(1));
|
||||||
|
|
||||||
@@ -312,7 +312,7 @@ function U2pvis(act, btns) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.drawcard = function (cat) {
|
this.drawcard = function (cat) {
|
||||||
var cards = document.querySelectorAll('#u2cards>a>span');
|
var cards = QSA('#u2cards>a>span');
|
||||||
|
|
||||||
if (cat == "q") {
|
if (cat == "q") {
|
||||||
cards[4].innerHTML = this.ctr[cat];
|
cards[4].innerHTML = this.ctr[cat];
|
||||||
@@ -374,7 +374,7 @@ function U2pvis(act, btns) {
|
|||||||
if (as_html)
|
if (as_html)
|
||||||
return '<tr id="f' + nfile + '">' + ret + '</tr>';
|
return '<tr id="f' + nfile + '">' + ret + '</tr>';
|
||||||
|
|
||||||
var obj = document.createElement('tr');
|
var obj = mknod('tr');
|
||||||
obj.setAttribute('id', 'f' + nfile);
|
obj.setAttribute('id', 'f' + nfile);
|
||||||
obj.innerHTML = ret;
|
obj.innerHTML = ret;
|
||||||
return obj;
|
return obj;
|
||||||
@@ -386,7 +386,7 @@ function U2pvis(act, btns) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var that = this;
|
var that = this;
|
||||||
btns = document.querySelectorAll(btns + '>a[act]');
|
btns = QSA(btns + '>a[act]');
|
||||||
for (var a = 0; a < btns.length; a++) {
|
for (var a = 0; a < btns.length; a++) {
|
||||||
btns[a].onclick = function (e) {
|
btns[a].onclick = function (e) {
|
||||||
ev(e);
|
ev(e);
|
||||||
@@ -661,7 +661,7 @@ function up2k_init(have_crypto) {
|
|||||||
|
|
||||||
for (var a = 0; a < good_files.length; a++) {
|
for (var a = 0; a < good_files.length; a++) {
|
||||||
var fobj = good_files[a][0],
|
var fobj = good_files[a][0],
|
||||||
now = new Date().getTime(),
|
now = Date.now(),
|
||||||
lmod = fobj.lastModified || now;
|
lmod = fobj.lastModified || now;
|
||||||
|
|
||||||
var entry = {
|
var entry = {
|
||||||
@@ -699,7 +699,7 @@ function up2k_init(have_crypto) {
|
|||||||
|
|
||||||
function more_one_file() {
|
function more_one_file() {
|
||||||
fdom_ctr++;
|
fdom_ctr++;
|
||||||
var elm = document.createElement('div');
|
var elm = mknod('div');
|
||||||
elm.innerHTML = '<input id="file{0}" type="file" name="file{0}[]" multiple="multiple" />'.format(fdom_ctr);
|
elm.innerHTML = '<input id="file{0}" type="file" name="file{0}[]" multiple="multiple" />'.format(fdom_ctr);
|
||||||
ebi('u2form').appendChild(elm);
|
ebi('u2form').appendChild(elm);
|
||||||
ebi('file' + fdom_ctr).addEventListener('change', gotfile, false);
|
ebi('file' + fdom_ctr).addEventListener('change', gotfile, false);
|
||||||
@@ -780,7 +780,7 @@ function up2k_init(have_crypto) {
|
|||||||
|
|
||||||
if (flag) {
|
if (flag) {
|
||||||
if (is_busy) {
|
if (is_busy) {
|
||||||
var now = new Date().getTime();
|
var now = Date.now();
|
||||||
flag.take(now);
|
flag.take(now);
|
||||||
if (!flag.ours)
|
if (!flag.ours)
|
||||||
return defer();
|
return defer();
|
||||||
@@ -916,7 +916,7 @@ function up2k_init(have_crypto) {
|
|||||||
nch = nchunk++,
|
nch = nchunk++,
|
||||||
car = nch * chunksize,
|
car = nch * chunksize,
|
||||||
cdr = car + chunksize,
|
cdr = car + chunksize,
|
||||||
t0 = new Date().getTime();
|
t0 = Date.now();
|
||||||
|
|
||||||
if (cdr >= t.size)
|
if (cdr >= t.size)
|
||||||
cdr = t.size;
|
cdr = t.size;
|
||||||
@@ -926,7 +926,7 @@ function up2k_init(have_crypto) {
|
|||||||
reader.onload = function (e) {
|
reader.onload = function (e) {
|
||||||
if (!min_filebuf && nch == 1) {
|
if (!min_filebuf && nch == 1) {
|
||||||
min_filebuf = 1;
|
min_filebuf = 1;
|
||||||
var td = (new Date().getTime()) - t0;
|
var td = Date.now() - t0;
|
||||||
if (td > 50) {
|
if (td > 50) {
|
||||||
ebi('u2foot').innerHTML += "<p>excessive filereader latency (" + td + " ms), increasing readahead</p>";
|
ebi('u2foot').innerHTML += "<p>excessive filereader latency (" + td + " ms), increasing readahead</p>";
|
||||||
min_filebuf = 32 * 1024 * 1024;
|
min_filebuf = 32 * 1024 * 1024;
|
||||||
@@ -963,7 +963,7 @@ function up2k_init(have_crypto) {
|
|||||||
t.hash.push(hashtab[a]);
|
t.hash.push(hashtab[a]);
|
||||||
}
|
}
|
||||||
|
|
||||||
t.t2 = new Date().getTime();
|
t.t2 = Date.now();
|
||||||
if (t.n == 0 && window.location.hash == '#dbg') {
|
if (t.n == 0 && window.location.hash == '#dbg') {
|
||||||
var spd = (t.size / ((t.t2 - t.t1) / 1000.)) / (1024 * 1024.);
|
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'));
|
alert('{0} ms, {1} MB/s\n'.format(t.t2 - t.t1, spd.toFixed(3)) + t.hash.join('\n'));
|
||||||
@@ -985,7 +985,7 @@ function up2k_init(have_crypto) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
t.t1 = new Date().getTime();
|
t.t1 = Date.now();
|
||||||
segm_next();
|
segm_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1159,7 +1159,7 @@ function up2k_init(have_crypto) {
|
|||||||
t = st.files[upt.nfile];
|
t = st.files[upt.nfile];
|
||||||
|
|
||||||
if (!t.t3)
|
if (!t.t3)
|
||||||
t.t3 = new Date().getTime();
|
t.t3 = Date.now();
|
||||||
|
|
||||||
pvis.seth(t.n, 1, "🚀 send");
|
pvis.seth(t.n, 1, "🚀 send");
|
||||||
|
|
||||||
@@ -1182,7 +1182,7 @@ function up2k_init(have_crypto) {
|
|||||||
st.busy.upload.splice(st.busy.upload.indexOf(upt), 1);
|
st.busy.upload.splice(st.busy.upload.indexOf(upt), 1);
|
||||||
t.postlist.splice(t.postlist.indexOf(npart), 1);
|
t.postlist.splice(t.postlist.indexOf(npart), 1);
|
||||||
if (t.postlist.length == 0) {
|
if (t.postlist.length == 0) {
|
||||||
t.t4 = new Date().getTime();
|
t.t4 = Date.now();
|
||||||
pvis.seth(t.n, 1, 'verifying');
|
pvis.seth(t.n, 1, 'verifying');
|
||||||
st.todo.handshake.unshift(t);
|
st.todo.handshake.unshift(t);
|
||||||
}
|
}
|
||||||
@@ -1240,11 +1240,11 @@ function up2k_init(have_crypto) {
|
|||||||
function desc_hide(e) {
|
function desc_hide(e) {
|
||||||
ebi('u2cdesc').setAttribute('class', '');
|
ebi('u2cdesc').setAttribute('class', '');
|
||||||
}
|
}
|
||||||
var o = document.querySelectorAll('#u2conf *[alt]');
|
var o = QSA('#u2conf *[alt]');
|
||||||
for (var a = o.length - 1; a >= 0; a--) {
|
for (var a = o.length - 1; a >= 0; a--) {
|
||||||
o[a].parentNode.getElementsByTagName('input')[0].setAttribute('alt', o[a].getAttribute('alt'));
|
o[a].parentNode.getElementsByTagName('input')[0].setAttribute('alt', o[a].getAttribute('alt'));
|
||||||
}
|
}
|
||||||
var o = document.querySelectorAll('#u2conf *[alt]');
|
var o = QSA('#u2conf *[alt]');
|
||||||
for (var a = 0; a < o.length; a++) {
|
for (var a = 0; a < o.length; a++) {
|
||||||
o[a].onfocus = desc_show;
|
o[a].onfocus = desc_show;
|
||||||
o[a].onblur = desc_hide;
|
o[a].onblur = desc_hide;
|
||||||
@@ -1315,7 +1315,7 @@ function up2k_init(have_crypto) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
document.querySelector('label[for="fsearch"]').style.opacity = read_only ? '0' : '1';
|
QS('label[for="fsearch"]').style.opacity = read_only ? '0' : '1';
|
||||||
}
|
}
|
||||||
catch (ex) { }
|
catch (ex) { }
|
||||||
|
|
||||||
@@ -1391,5 +1391,5 @@ function warn_uploader_busy(e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (document.querySelector('#op_up2k.act'))
|
if (QS('#op_up2k.act'))
|
||||||
goto_up2k();
|
goto_up2k();
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
background: #222;
|
background: #222;
|
||||||
}
|
}
|
||||||
#u2cards {
|
#u2cards {
|
||||||
padding: 1em 0 .3em 0;
|
padding: 1em 0 .3em 1em;
|
||||||
margin: 1.5em auto -2.5em auto;
|
margin: 1.5em auto -2.5em auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -175,7 +175,6 @@
|
|||||||
height: 1em;
|
height: 1em;
|
||||||
padding: .4em 0;
|
padding: .4em 0;
|
||||||
display: block;
|
display: block;
|
||||||
user-select: none;
|
|
||||||
border-radius: .25em;
|
border-radius: .25em;
|
||||||
}
|
}
|
||||||
#u2conf input[type="checkbox"] {
|
#u2conf input[type="checkbox"] {
|
||||||
@@ -284,3 +283,6 @@ html.light #u2cdesc {
|
|||||||
html.light #op_up2k.srch #u2btn {
|
html.light #op_up2k.srch #u2btn {
|
||||||
border-color: #a80;
|
border-color: #a80;
|
||||||
}
|
}
|
||||||
|
html.light #u2foot {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,9 +50,11 @@ function vis_exh(msg, url, lineNo, columnNo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function ebi(id) {
|
var ebi = document.getElementById.bind(document),
|
||||||
return document.getElementById(id);
|
QS = document.querySelector.bind(document),
|
||||||
}
|
QSA = document.querySelectorAll.bind(document),
|
||||||
|
mknod = document.createElement.bind(document);
|
||||||
|
|
||||||
|
|
||||||
function ev(e) {
|
function ev(e) {
|
||||||
e = e || window.event;
|
e = e || window.event;
|
||||||
@@ -90,7 +92,7 @@ if (!String.startsWith) {
|
|||||||
// https://stackoverflow.com/a/950146
|
// https://stackoverflow.com/a/950146
|
||||||
function import_js(url, cb) {
|
function import_js(url, cb) {
|
||||||
var head = document.head || document.getElementsByTagName('head')[0];
|
var head = document.head || document.getElementsByTagName('head')[0];
|
||||||
var script = document.createElement('script');
|
var script = mknod('script');
|
||||||
script.type = 'text/javascript';
|
script.type = 'text/javascript';
|
||||||
script.src = url;
|
script.src = url;
|
||||||
|
|
||||||
@@ -275,7 +277,7 @@ function makeSortable(table, cb) {
|
|||||||
|
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
var ops = document.querySelectorAll('#ops>a');
|
var ops = QSA('#ops>a');
|
||||||
for (var a = 0; a < ops.length; a++) {
|
for (var a = 0; a < ops.length; a++) {
|
||||||
ops[a].onclick = opclick;
|
ops[a].onclick = opclick;
|
||||||
}
|
}
|
||||||
@@ -290,25 +292,25 @@ function opclick(e) {
|
|||||||
|
|
||||||
swrite('opmode', dest || null);
|
swrite('opmode', dest || null);
|
||||||
|
|
||||||
var input = document.querySelector('.opview.act input:not([type="hidden"])')
|
var input = QS('.opview.act input:not([type="hidden"])')
|
||||||
if (input)
|
if (input)
|
||||||
input.focus();
|
input.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function goto(dest) {
|
function goto(dest) {
|
||||||
var obj = document.querySelectorAll('.opview.act');
|
var obj = QSA('.opview.act');
|
||||||
for (var a = obj.length - 1; a >= 0; a--)
|
for (var a = obj.length - 1; a >= 0; a--)
|
||||||
clmod(obj[a], 'act');
|
clmod(obj[a], 'act');
|
||||||
|
|
||||||
obj = document.querySelectorAll('#ops>a');
|
obj = QSA('#ops>a');
|
||||||
for (var a = obj.length - 1; a >= 0; a--)
|
for (var a = obj.length - 1; a >= 0; a--)
|
||||||
clmod(obj[a], 'act');
|
clmod(obj[a], 'act');
|
||||||
|
|
||||||
if (dest) {
|
if (dest) {
|
||||||
var ui = ebi('op_' + dest);
|
var ui = ebi('op_' + dest);
|
||||||
clmod(ui, 'act', true);
|
clmod(ui, 'act', true);
|
||||||
document.querySelector('#ops>a[data-dest=' + dest + ']').className += " act";
|
QS('#ops>a[data-dest=' + dest + ']').className += " act";
|
||||||
|
|
||||||
var fn = window['goto_' + dest];
|
var fn = window['goto_' + dest];
|
||||||
if (fn)
|
if (fn)
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ Range: bytes=26- Content-Range: bytes */26
|
|||||||
|
|
||||||
var tsh = [];
|
var tsh = [];
|
||||||
function convert_markdown(md_text, dest_dom) {
|
function convert_markdown(md_text, dest_dom) {
|
||||||
tsh.push(new Date().getTime());
|
tsh.push(Date.now());
|
||||||
while (tsh.length > 10)
|
while (tsh.length > 10)
|
||||||
tsh.shift();
|
tsh.shift();
|
||||||
if (tsh.length > 1) {
|
if (tsh.length > 1) {
|
||||||
|
|||||||
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
33
tests/run.py
Executable file
33
tests/run.py
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import runpy
|
||||||
|
|
||||||
|
host = sys.argv[1]
|
||||||
|
sys.argv = sys.argv[:1] + sys.argv[2:]
|
||||||
|
sys.path.insert(0, ".")
|
||||||
|
|
||||||
|
|
||||||
|
def rp():
|
||||||
|
runpy.run_module("unittest", run_name="__main__")
|
||||||
|
|
||||||
|
|
||||||
|
if host == "vmprof":
|
||||||
|
rp()
|
||||||
|
|
||||||
|
elif host == "cprofile":
|
||||||
|
import cProfile
|
||||||
|
import pstats
|
||||||
|
|
||||||
|
log_fn = "cprofile.log"
|
||||||
|
cProfile.run("rp()", log_fn)
|
||||||
|
p = pstats.Stats(log_fn)
|
||||||
|
p.sort_stats(pstats.SortKey.CUMULATIVE).print_stats(64)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
python3.9 tests/run.py cprofile -v tests/test_httpcli.py
|
||||||
|
|
||||||
|
python3.9 -m pip install --user vmprof
|
||||||
|
python3.9 -m vmprof --lines -o vmprof.log tests/run.py vmprof -v tests/test_httpcli.py
|
||||||
|
"""
|
||||||
202
tests/test_httpcli.py
Normal file
202
tests/test_httpcli.py
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# coding: utf-8
|
||||||
|
from __future__ import print_function, unicode_literals
|
||||||
|
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import shutil
|
||||||
|
import pprint
|
||||||
|
import tarfile
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from argparse import Namespace
|
||||||
|
from copyparty.authsrv import AuthSrv
|
||||||
|
from copyparty.httpcli import HttpCli
|
||||||
|
|
||||||
|
from tests import util as tu
|
||||||
|
|
||||||
|
|
||||||
|
def hdr(query):
|
||||||
|
h = "GET /{} HTTP/1.1\r\nCookie: cppwd=o\r\nConnection: close\r\n\r\n"
|
||||||
|
return h.format(query).encode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
class Cfg(Namespace):
|
||||||
|
def __init__(self, a=[], v=[], c=None):
|
||||||
|
super(Cfg, self).__init__(
|
||||||
|
a=a,
|
||||||
|
v=v,
|
||||||
|
c=c,
|
||||||
|
ed=False,
|
||||||
|
no_zip=False,
|
||||||
|
no_scandir=False,
|
||||||
|
no_sendfile=True,
|
||||||
|
nih=True,
|
||||||
|
mtp=[],
|
||||||
|
mte="a",
|
||||||
|
**{k: False for k in "e2d e2ds e2dsa e2t e2ts e2tsr".split()}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestHttpCli(unittest.TestCase):
|
||||||
|
def test(self):
|
||||||
|
td = os.path.join(tu.get_ramdisk(), "vfs")
|
||||||
|
try:
|
||||||
|
shutil.rmtree(td)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
os.mkdir(td)
|
||||||
|
os.chdir(td)
|
||||||
|
|
||||||
|
self.dtypes = ["ra", "ro", "rx", "wa", "wo", "wx", "aa", "ao", "ax"]
|
||||||
|
self.can_read = ["ra", "ro", "aa", "ao"]
|
||||||
|
self.can_write = ["wa", "wo", "aa", "ao"]
|
||||||
|
self.fn = "g{:x}g".format(int(time.time() * 3))
|
||||||
|
|
||||||
|
allfiles = []
|
||||||
|
allvols = []
|
||||||
|
for top in self.dtypes:
|
||||||
|
allvols.append(top)
|
||||||
|
allfiles.append("/".join([top, self.fn]))
|
||||||
|
for s1 in self.dtypes:
|
||||||
|
p = "/".join([top, s1])
|
||||||
|
allvols.append(p)
|
||||||
|
allfiles.append(p + "/" + self.fn)
|
||||||
|
allfiles.append(p + "/n/" + self.fn)
|
||||||
|
for s2 in self.dtypes:
|
||||||
|
p = "/".join([top, s1, "n", s2])
|
||||||
|
os.makedirs(p)
|
||||||
|
allvols.append(p)
|
||||||
|
allfiles.append(p + "/" + self.fn)
|
||||||
|
|
||||||
|
for fp in allfiles:
|
||||||
|
with open(fp, "w") as f:
|
||||||
|
f.write("ok {}\n".format(fp))
|
||||||
|
|
||||||
|
for top in self.dtypes:
|
||||||
|
vcfg = []
|
||||||
|
for vol in allvols:
|
||||||
|
if not vol.startswith(top):
|
||||||
|
continue
|
||||||
|
|
||||||
|
mode = vol[-2]
|
||||||
|
usr = vol[-1]
|
||||||
|
if usr == "a":
|
||||||
|
usr = ""
|
||||||
|
|
||||||
|
if "/" not in vol:
|
||||||
|
vol += "/"
|
||||||
|
|
||||||
|
top, sub = vol.split("/", 1)
|
||||||
|
vcfg.append("{0}/{1}:{1}:{2}{3}".format(top, sub, mode, usr))
|
||||||
|
|
||||||
|
pprint.pprint(vcfg)
|
||||||
|
|
||||||
|
self.args = Cfg(v=vcfg, a=["o:o", "x:x"])
|
||||||
|
self.auth = AuthSrv(self.args, self.log)
|
||||||
|
vfiles = [x for x in allfiles if x.startswith(top)]
|
||||||
|
for fp in vfiles:
|
||||||
|
rok, wok = self.can_rw(fp)
|
||||||
|
furl = fp.split("/", 1)[1]
|
||||||
|
durl = furl.rsplit("/", 1)[0] if "/" in furl else ""
|
||||||
|
|
||||||
|
# file download
|
||||||
|
h, ret = self.curl(furl)
|
||||||
|
res = "ok " + fp in ret
|
||||||
|
print("[{}] {} {} = {}".format(fp, rok, wok, res))
|
||||||
|
if rok != res:
|
||||||
|
print("\033[33m{}\n# {}\033[0m".format(ret, furl))
|
||||||
|
self.fail()
|
||||||
|
|
||||||
|
# file browser: html
|
||||||
|
h, ret = self.curl(durl)
|
||||||
|
res = "'{}'".format(self.fn) in ret
|
||||||
|
print(res)
|
||||||
|
if rok != res:
|
||||||
|
print("\033[33m{}\n# {}\033[0m".format(ret, durl))
|
||||||
|
self.fail()
|
||||||
|
|
||||||
|
# file browser: json
|
||||||
|
url = durl + "?ls"
|
||||||
|
h, ret = self.curl(url)
|
||||||
|
res = '"{}"'.format(self.fn) in ret
|
||||||
|
print(res)
|
||||||
|
if rok != res:
|
||||||
|
print("\033[33m{}\n# {}\033[0m".format(ret, url))
|
||||||
|
self.fail()
|
||||||
|
|
||||||
|
# tar
|
||||||
|
url = durl + "?tar"
|
||||||
|
h, b = self.curl(url, True)
|
||||||
|
# with open(os.path.join(td, "tar"), "wb") as f:
|
||||||
|
# f.write(b)
|
||||||
|
try:
|
||||||
|
tar = tarfile.open(fileobj=io.BytesIO(b)).getnames()
|
||||||
|
except:
|
||||||
|
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]]
|
||||||
|
tar_ng = [x[0] for x in tar if not x[1]]
|
||||||
|
self.assertEqual([], tar_ng)
|
||||||
|
|
||||||
|
if durl.split("/")[-1] in self.can_read:
|
||||||
|
ref = [x for x in vfiles if self.in_dive(top + "/" + durl, x)]
|
||||||
|
for f in ref:
|
||||||
|
print("{}: {}".format("ok" if f in tar_ok else "NG", f))
|
||||||
|
ref.sort()
|
||||||
|
tar_ok.sort()
|
||||||
|
self.assertEqual(ref, tar_ok)
|
||||||
|
|
||||||
|
# stash
|
||||||
|
h, ret = self.put(url)
|
||||||
|
res = h.startswith("HTTP/1.1 200 ")
|
||||||
|
self.assertEqual(res, wok)
|
||||||
|
|
||||||
|
def can_rw(self, fp):
|
||||||
|
# lowest non-neutral folder declares permissions
|
||||||
|
expect = fp.split("/")[:-1]
|
||||||
|
for x in reversed(expect):
|
||||||
|
if x != "n":
|
||||||
|
expect = x
|
||||||
|
break
|
||||||
|
|
||||||
|
return [expect in self.can_read, expect in self.can_write]
|
||||||
|
|
||||||
|
def in_dive(self, top, fp):
|
||||||
|
# archiver bails at first inaccessible subvolume
|
||||||
|
top = top.strip("/").split("/")
|
||||||
|
fp = fp.split("/")
|
||||||
|
for f1, f2 in zip(top, fp):
|
||||||
|
if f1 != f2:
|
||||||
|
return False
|
||||||
|
|
||||||
|
for f in fp[len(top) :]:
|
||||||
|
if f == self.fn:
|
||||||
|
return True
|
||||||
|
if f not in self.can_read and f != "n":
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def put(self, url):
|
||||||
|
buf = "PUT /{0} HTTP/1.1\r\nCookie: cppwd=o\r\nConnection: close\r\nContent-Length: {1}\r\n\r\nok {0}\n"
|
||||||
|
buf = buf.format(url, len(url) + 4).encode("utf-8")
|
||||||
|
conn = tu.VHttpConn(self.args, self.auth, self.log, buf)
|
||||||
|
HttpCli(conn).run()
|
||||||
|
return conn.s._reply.decode("utf-8").split("\r\n\r\n", 1)
|
||||||
|
|
||||||
|
def curl(self, url, binary=False):
|
||||||
|
conn = tu.VHttpConn(self.args, self.auth, self.log, hdr(url))
|
||||||
|
HttpCli(conn).run()
|
||||||
|
if binary:
|
||||||
|
h, b = conn.s._reply.split(b"\r\n\r\n", 1)
|
||||||
|
return [h.decode("utf-8"), b]
|
||||||
|
|
||||||
|
return conn.s._reply.decode("utf-8").split("\r\n\r\n", 1)
|
||||||
|
|
||||||
|
def log(self, src, msg, c=0):
|
||||||
|
# print(repr(msg))
|
||||||
|
pass
|
||||||
@@ -3,18 +3,18 @@
|
|||||||
from __future__ import print_function, unicode_literals
|
from __future__ import print_function, unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
|
||||||
import json
|
import json
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
import subprocess as sp # nosec
|
|
||||||
|
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from copyparty.authsrv import AuthSrv
|
from copyparty.authsrv import AuthSrv
|
||||||
from copyparty import util
|
from copyparty import util
|
||||||
|
|
||||||
|
from tests import util as tu
|
||||||
|
|
||||||
|
|
||||||
class Cfg(Namespace):
|
class Cfg(Namespace):
|
||||||
def __init__(self, a=[], v=[], c=None):
|
def __init__(self, a=[], v=[], c=None):
|
||||||
@@ -51,52 +51,11 @@ class TestVFS(unittest.TestCase):
|
|||||||
real = [x[0] for x in real]
|
real = [x[0] for x in real]
|
||||||
return fsdir, real, virt
|
return fsdir, real, virt
|
||||||
|
|
||||||
def runcmd(self, *argv):
|
|
||||||
p = sp.Popen(argv, stdout=sp.PIPE, stderr=sp.PIPE)
|
|
||||||
stdout, stderr = p.communicate()
|
|
||||||
stdout = stdout.decode("utf-8")
|
|
||||||
stderr = stderr.decode("utf-8")
|
|
||||||
return [p.returncode, stdout, stderr]
|
|
||||||
|
|
||||||
def chkcmd(self, *argv):
|
|
||||||
ok, sout, serr = self.runcmd(*argv)
|
|
||||||
if ok != 0:
|
|
||||||
raise Exception(serr)
|
|
||||||
|
|
||||||
return sout, serr
|
|
||||||
|
|
||||||
def get_ramdisk(self):
|
|
||||||
for vol in ["/dev/shm", "/Volumes/cptd"]: # nosec (singleton test)
|
|
||||||
if os.path.exists(vol):
|
|
||||||
return vol
|
|
||||||
|
|
||||||
if os.path.exists("/Volumes"):
|
|
||||||
devname, _ = self.chkcmd("hdiutil", "attach", "-nomount", "ram://8192")
|
|
||||||
devname = devname.strip()
|
|
||||||
print("devname: [{}]".format(devname))
|
|
||||||
for _ in range(10):
|
|
||||||
try:
|
|
||||||
_, _ = self.chkcmd(
|
|
||||||
"diskutil", "eraseVolume", "HFS+", "cptd", devname
|
|
||||||
)
|
|
||||||
return "/Volumes/cptd"
|
|
||||||
except Exception as ex:
|
|
||||||
print(repr(ex))
|
|
||||||
time.sleep(0.25)
|
|
||||||
|
|
||||||
raise Exception("ramdisk creation failed")
|
|
||||||
|
|
||||||
ret = os.path.join(tempfile.gettempdir(), "copyparty-test")
|
|
||||||
try:
|
|
||||||
os.mkdir(ret)
|
|
||||||
finally:
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def log(self, src, msg, c=0):
|
def log(self, src, msg, c=0):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
td = os.path.join(self.get_ramdisk(), "vfs")
|
td = os.path.join(tu.get_ramdisk(), "vfs")
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(td)
|
shutil.rmtree(td)
|
||||||
except OSError:
|
except OSError:
|
||||||
@@ -268,7 +227,7 @@ class TestVFS(unittest.TestCase):
|
|||||||
self.assertEqual(list(v1), list(v2))
|
self.assertEqual(list(v1), list(v2))
|
||||||
|
|
||||||
# config file parser
|
# config file parser
|
||||||
cfg_path = os.path.join(self.get_ramdisk(), "test.cfg")
|
cfg_path = os.path.join(tu.get_ramdisk(), "test.cfg")
|
||||||
with open(cfg_path, "wb") as f:
|
with open(cfg_path, "wb") as f:
|
||||||
f.write(
|
f.write(
|
||||||
dedent(
|
dedent(
|
||||||
|
|||||||
97
tests/util.py
Normal file
97
tests/util.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
|
import jinja2
|
||||||
|
import tempfile
|
||||||
|
import subprocess as sp
|
||||||
|
|
||||||
|
from copyparty.util import Unrecv
|
||||||
|
|
||||||
|
|
||||||
|
J2_ENV = jinja2.Environment(loader=jinja2.BaseLoader)
|
||||||
|
J2_FILES = J2_ENV.from_string("{{ files|join('\n') }}")
|
||||||
|
|
||||||
|
|
||||||
|
def runcmd(*argv):
|
||||||
|
p = sp.Popen(argv, stdout=sp.PIPE, stderr=sp.PIPE)
|
||||||
|
stdout, stderr = p.communicate()
|
||||||
|
stdout = stdout.decode("utf-8")
|
||||||
|
stderr = stderr.decode("utf-8")
|
||||||
|
return [p.returncode, stdout, stderr]
|
||||||
|
|
||||||
|
|
||||||
|
def chkcmd(*argv):
|
||||||
|
ok, sout, serr = runcmd(*argv)
|
||||||
|
if ok != 0:
|
||||||
|
raise Exception(serr)
|
||||||
|
|
||||||
|
return sout, serr
|
||||||
|
|
||||||
|
|
||||||
|
def get_ramdisk():
|
||||||
|
for vol in ["/dev/shm", "/Volumes/cptd"]: # nosec (singleton test)
|
||||||
|
if os.path.exists(vol):
|
||||||
|
return vol
|
||||||
|
|
||||||
|
if os.path.exists("/Volumes"):
|
||||||
|
devname, _ = chkcmd("hdiutil", "attach", "-nomount", "ram://32768")
|
||||||
|
devname = devname.strip()
|
||||||
|
print("devname: [{}]".format(devname))
|
||||||
|
for _ in range(10):
|
||||||
|
try:
|
||||||
|
_, _ = chkcmd("diskutil", "eraseVolume", "HFS+", "cptd", devname)
|
||||||
|
return "/Volumes/cptd"
|
||||||
|
except Exception as ex:
|
||||||
|
print(repr(ex))
|
||||||
|
time.sleep(0.25)
|
||||||
|
|
||||||
|
raise Exception("ramdisk creation failed")
|
||||||
|
|
||||||
|
ret = os.path.join(tempfile.gettempdir(), "copyparty-test")
|
||||||
|
try:
|
||||||
|
os.mkdir(ret)
|
||||||
|
finally:
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
class NullBroker(object):
|
||||||
|
def put(*args):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class VSock(object):
|
||||||
|
def __init__(self, buf):
|
||||||
|
self._query = buf
|
||||||
|
self._reply = b""
|
||||||
|
self.sendall = self.send
|
||||||
|
|
||||||
|
def recv(self, sz):
|
||||||
|
ret = self._query[:sz]
|
||||||
|
self._query = self._query[sz:]
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def send(self, buf):
|
||||||
|
self._reply += buf
|
||||||
|
return len(buf)
|
||||||
|
|
||||||
|
|
||||||
|
class VHttpSrv(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.broker = NullBroker()
|
||||||
|
|
||||||
|
aliases = ["splash", "browser", "browser2", "msg", "md", "mde"]
|
||||||
|
self.j2 = {x: J2_FILES for x in aliases}
|
||||||
|
|
||||||
|
|
||||||
|
class VHttpConn(object):
|
||||||
|
def __init__(self, args, auth, log, buf):
|
||||||
|
self.s = VSock(buf)
|
||||||
|
self.sr = Unrecv(self.s)
|
||||||
|
self.addr = ("127.0.0.1", "42069")
|
||||||
|
self.args = args
|
||||||
|
self.auth = auth
|
||||||
|
self.log_func = log
|
||||||
|
self.log_src = "a"
|
||||||
|
self.hsrv = VHttpSrv()
|
||||||
|
self.nbyte = 0
|
||||||
|
self.workload = 0
|
||||||
|
self.t0 = time.time()
|
||||||
Reference in New Issue
Block a user