add logout on inactivity + related errorhandling

This commit is contained in:
ed 2022-05-01 22:12:25 +02:00
parent 00b5db52cf
commit b50d090946
7 changed files with 110 additions and 60 deletions

View file

@ -487,6 +487,7 @@ def run_argparse(argv, formatter):
ap2.add_argument("--vague-403", action="store_true", help="send 404 instead of 403 (security through ambiguity, very enterprise)")
ap2.add_argument("--force-js", action="store_true", help="don't send folder listings as HTML, force clients to use the embedded json instead -- slight protection against misbehaving search engines which ignore --no-robots")
ap2.add_argument("--no-robots", action="store_true", help="adds http and html headers asking search engines to not index anything")
ap2.add_argument("--logout", metavar="H", type=float, default="8086", help="logout clients after H hours of inactivity (0.0028=10sec, 0.1=6min, 24=day, 168=week, 720=month, 8760=year)")
ap2 = ap.add_argument_group('yolo options')
ap2.add_argument("--ign-ebind", action="store_true", help="continue running even if it's impossible to listen on some of the requested endpoints")

View file

@ -143,6 +143,10 @@ class HttpCli(object):
if self.args.rsp_slp:
time.sleep(self.args.rsp_slp)
self.ua = self.headers.get("user-agent", "")
self.is_rclone = self.ua.startswith("rclone/")
self.is_ancient = self.ua.startswith("Mozilla/4.")
v = self.headers.get("connection", "").lower()
self.keepalive = not v.startswith("close") and self.http_ver != "HTTP/1.0"
self.is_https = (self.headers.get("x-forwarded-proto", "").lower() == "https" or self.tls)
@ -241,11 +245,12 @@ class HttpCli(object):
self.dvol = self.asrv.vfs.adel[self.uname]
self.gvol = self.asrv.vfs.aget[self.uname]
if pwd and "pw" in self.ouparam and pwd != cookies.get("cppwd"):
# resend auth cookie if more than 1/3 of the lifetime has passed
# (rate-limited to prevent thrashing browser state, not for performance)
if pwd and self.conn.pwd_cookie_upd < self.t0 - 20 * 60 * self.args.logout:
self.out_headerlist.append(("Set-Cookie", self.get_pwd_cookie(pwd)[0]))
self.conn.pwd_cookie_upd = self.t0
self.ua = self.headers.get("user-agent", "")
self.is_rclone = self.ua.startswith("rclone/")
if self.is_rclone:
uparam["raw"] = False
uparam["dots"] = False
@ -1007,9 +1012,15 @@ class HttpCli(object):
pwd = self.parser.require("cppwd", 64)
self.parser.drop()
self.out_headerlist = [
x
for x in self.out_headerlist
if x[0] != "Set-Cookie" or "cppwd=" not in x[1]
]
dst = "/"
if self.vpath:
dst = "/" + quotep(self.vpath)
dst += quotep(self.vpath)
ck, msg = self.get_pwd_cookie(pwd)
html = self.j2("msg", h1=msg, h2='<a href="' + dst + '">ack</a>', redir=dst)
@ -1019,14 +1030,14 @@ class HttpCli(object):
def get_pwd_cookie(self, pwd):
if pwd in self.asrv.iacct:
msg = "login ok"
dur = 60 * 60 * 24 * 365
dur = int(60 * 60 * self.args.logout)
else:
msg = "naw dude"
pwd = "x" # nosec
dur = None
r = gencookie("cppwd", pwd, dur)
if self.headers.get("user-agent", "").startswith("Mozilla/4."):
if self.is_ancient:
r = r.rsplit(" ", 1)[0]
return [r, msg]
@ -1818,15 +1829,17 @@ class HttpCli(object):
self.redirect("", "?h#cc")
def tx_404(self, is_403=False):
rc = 404
if self.args.vague_403:
m = '<h1>404 not found &nbsp;┐( ´ -`)┌</h1><p>or maybe you don\'t have access -- try logging in or <a href="/?h">go home</a></p>'
elif is_403:
m = '<h1>403 forbiddena &nbsp;~┻━┻</h1><p>you\'ll have to log in or <a href="/?h">go home</a></p>'
rc = 403
else:
m = '<h1>404 not found &nbsp;┐( ´ -`)┌</h1><p><a href="/?h">go home</a></p>'
html = self.j2("splash", this=self, qvpath=quotep(self.vpath), msg=m)
self.reply(html.encode("utf-8"), status=404)
self.reply(html.encode("utf-8"), status=rc)
return True
def scanvol(self):

View file

@ -46,6 +46,7 @@ class HttpConn(object):
self.stopping = False
self.nreq = 0
self.nbyte = 0
self.pwd_cookie_upd = 0
self.u2idx = None
self.log_func = hsrv.log
self.lf_url = re.compile(self.args.lf_url) if self.args.lf_url else None

View file

@ -3,6 +3,7 @@
function dbg(msg) {
ebi('path').innerHTML = msg;
}
var XHR = XMLHttpRequest;
// toolbar
@ -1562,12 +1563,37 @@ function evau_error(e) {
err = 'Unknown Errol';
break;
}
if (eplaya.error.message)
err += '\n\n' + eplaya.error.message;
var em = '' + eplaya.error.message,
mfile = '\n\nFile: «' + uricom_dec(eplaya.src.split('/').pop())[0] + '»',
e404 = 'Could not play audio; error 404: File not found.',
e403 = 'Could not play audio; error 403: Access denied.\n\nTry pressing F5 to reload, maybe you got logged out';
err += '\n\nFile: «' + uricom_dec(eplaya.src.split('/').pop())[0] + '»';
if (em)
err += '\n\n' + em;
toast.warn(15, esc(basenames(err)));
if (em.startsWith('403: '))
err = e403;
if (em.startsWith('404: '))
err = e404;
toast.warn(15, esc(basenames(err + mfile)));
if (em.startsWith('MEDIA_ELEMENT_ERROR:')) {
// chromish for 40x
var xhr = new XHR();
xhr.open('HEAD', eplaya.src, true);
xhr.onreadystatechange = function () {
if (this.readyState != XHR.DONE || this.status < 400)
return;
err = this.status == 403 ? e403 : this.status == 404 ? e404 :
'Could not play audio; server error ' + this.status;
toast.warn(15, esc(basenames(err + mfile)));
};
xhr.send();
}
}
@ -2147,7 +2173,7 @@ var fileman = (function () {
var dst = base + uricom_enc(f[0].inew.value, false);
function rename_cb() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200) {
@ -2160,7 +2186,7 @@ var fileman = (function () {
return rn_apply();
}
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.open('GET', f[0].src + '?move=' + dst, true);
xhr.onreadystatechange = rename_cb;
xhr.send();
@ -2182,7 +2208,7 @@ var fileman = (function () {
return toast.err(3, 'select at least 1 item to delete');
function deleter() {
var xhr = new XMLHttpRequest(),
var xhr = new XHR(),
vp = vps.shift();
if (!vp) {
@ -2197,7 +2223,7 @@ var fileman = (function () {
xhr.send();
}
function delete_cb() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200) {
@ -2290,7 +2316,7 @@ var fileman = (function () {
return;
function paster() {
var xhr = new XMLHttpRequest(),
var xhr = new XHR(),
vp = req.shift();
if (!vp) {
@ -2308,7 +2334,7 @@ var fileman = (function () {
xhr.send();
}
function paste_cb() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200) {
@ -2461,7 +2487,7 @@ var showfile = (function () {
};
r.show = function (url, no_push) {
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.url = url;
xhr.no_push = no_push;
xhr.ts = Date.now();
@ -2471,13 +2497,11 @@ var showfile = (function () {
};
function load_cb() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200) {
toast.err(0, "recvtree, http " + this.status + ": " + this.responseText);
if (!xhrchk(this, "could not load textfile:\n\nerror ", "404, file not found"))
return;
}
render([this.url, '', this.responseText], this.no_push);
}
@ -3464,7 +3488,7 @@ document.onkeydown = function (e) {
srch_msg(false, "searching...");
clearTimeout(search_timeout);
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.open('POST', '/?srch', true);
xhr.setRequestHeader('Content-Type', 'text/plain');
xhr.onreadystatechange = xhr_search_results;
@ -3474,7 +3498,7 @@ document.onkeydown = function (e) {
}
function xhr_search_results() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200) {
@ -3802,7 +3826,7 @@ var treectl = (function () {
};
function get_tree(top, dst, rst) {
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.top = top;
xhr.dst = dst;
xhr.rst = rst;
@ -3814,13 +3838,11 @@ var treectl = (function () {
}
function recvtree() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200) {
toast.err(0, "recvtree, http " + this.status + ": " + this.responseText);
if (!xhrchk(this, "could not list subfolders:\n\nerror ", "404, folder not found"))
return;
}
var cur = ebi('treeul').getAttribute('ts');
if (cur && parseInt(cur) > this.ts) {
@ -3973,7 +3995,7 @@ var treectl = (function () {
}
r.reqls = function (url, hpush, no_tree) {
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.top = url;
xhr.hpush = hpush;
xhr.ts = Date.now();
@ -4002,13 +4024,11 @@ var treectl = (function () {
}
function recvls() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200) {
toast.err(0, "recvls, http " + this.status + ": " + this.responseText);
if (!xhrchk(this, "could not list files in folder:\n\nerror ", "404, folder not found"))
return;
}
var cur = ebi('files').getAttribute('ts');
if (cur && parseInt(cur) > this.ts) {
@ -4137,7 +4157,7 @@ var treectl = (function () {
r.hydrate = function () {
qsr('#bbsw');
if (ls0 === null) {
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.open('GET', '/?am_js', true);
xhr.send();
@ -4898,7 +4918,7 @@ var msel = (function () {
fd.append("act", "mkdir");
fd.append("name", tb.value);
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.vp = get_evpath();
xhr.dn = tb.value;
xhr.open('POST', xhr.vp, true);
@ -4910,7 +4930,7 @@ var msel = (function () {
};
function cb() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.vp !== get_evpath()) {
@ -4918,6 +4938,8 @@ var msel = (function () {
return;
}
xhrchk(this, "could not create subfolder:\n\nerror ", "404, parent folder not found");
if (this.status !== 200) {
sf.textContent = 'error: ' + this.responseText;
return;
@ -4947,7 +4969,7 @@ var msel = (function () {
clmod(sf, 'vis', 1);
sf.textContent = 'sending...';
var xhr = new XMLHttpRequest(),
var xhr = new XHR(),
ct = 'application/x-www-form-urlencoded;charset=UTF-8';
xhr.msg = tb.value;
@ -4963,9 +4985,11 @@ var msel = (function () {
};
function cb() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
xhrchk(this, "could not send message:\n\nerror ", "404, parent folder not found");
if (this.status !== 200) {
sf.textContent = 'error: ' + this.responseText;
return;
@ -5080,15 +5104,11 @@ var unpost = (function () {
html = [];
function unpost_load_cb() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200) {
var msg = this.responseText;
toast.err(9, 'unpost-load failed:\n' + msg);
ebi('op_unpost').innerHTML = html.join('\n');
return;
}
if (!xhrchk(this, "unpost-load failed:\n\nerror ", "404, file not found??"))
return ebi('op_unpost').innerHTML = 'failed to load unpost list from server';
var res = JSON.parse(this.responseText);
if (res.length) {
@ -5128,7 +5148,7 @@ var unpost = (function () {
if (filt.value)
q += '&filter=' + uricom_enc(filt.value, true);
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.open('GET', q, true);
xhr.onreadystatechange = unpost_load_cb;
xhr.send();
@ -5137,7 +5157,7 @@ var unpost = (function () {
};
function unpost_delete_cb() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200) {
@ -5188,7 +5208,7 @@ var unpost = (function () {
toast.inf(0, "deleting " + req.length + " files...");
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.n = n;
xhr.n2 = n2;
xhr.open('POST', '/?delete', true);

View file

@ -255,7 +255,7 @@ function Modpoll() {
console.log('modpoll...');
var url = (document.location + '').split('?')[0] + '?raw&_=' + Date.now();
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.open('GET', url, true);
xhr.responseType = 'text';
xhr.onreadystatechange = r.cb;
@ -268,7 +268,7 @@ function Modpoll() {
return;
}
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200) {
@ -336,7 +336,7 @@ function save(e) {
fd.append("body", txt);
var url = (document.location + '').split('?')[0];
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.open('POST', url, true);
xhr.responseType = 'text';
xhr.onreadystatechange = save_cb;
@ -356,7 +356,7 @@ function save(e) {
}
function save_cb() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200)
@ -397,7 +397,7 @@ function save_cb() {
function run_savechk(lastmod, txt, btn, ntry) {
// download the saved doc from the server and compare
var url = (document.location + '').split('?')[0] + '?raw&_=' + Date.now();
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.open('GET', url, true);
xhr.responseType = 'text';
xhr.onreadystatechange = savechk_cb;
@ -409,7 +409,7 @@ function run_savechk(lastmod, txt, btn, ntry) {
}
function savechk_cb() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200)

View file

@ -114,7 +114,7 @@ function save(mde) {
fd.append("body", txt);
var url = (document.location + '').split('?')[0];
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.open('POST', url, true);
xhr.responseType = 'text';
xhr.onreadystatechange = save_cb;
@ -133,7 +133,7 @@ function save(mde) {
}
function save_cb() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200)
@ -170,7 +170,7 @@ function save_cb() {
// download the saved doc from the server and compare
var url = (document.location + '').split('?')[0] + '?raw';
var xhr = new XMLHttpRequest();
var xhr = new XHR();
xhr.open('GET', url, true);
xhr.responseType = 'text';
xhr.onreadystatechange = save_chk;
@ -182,7 +182,7 @@ function save_cb() {
}
function save_chk() {
if (this.readyState != XMLHttpRequest.DONE)
if (this.readyState != XHR.DONE)
return;
if (this.status !== 200)

View file

@ -14,7 +14,8 @@ var is_touch = 'ontouchstart' in window,
var ebi = document.getElementById.bind(document),
QS = document.querySelector.bind(document),
QSA = document.querySelectorAll.bind(document),
mknod = document.createElement.bind(document);
mknod = document.createElement.bind(document),
XHR = XMLHttpRequest;
function qsr(sel) {
@ -1386,3 +1387,17 @@ var favico = (function () {
r.to = setTimeout(r.init, 100);
return r;
})();
function xhrchk(xhr, prefix, e404) {
if (xhr.status < 400 && xhr.status >= 200)
return true;
if (xhr.status == 403)
return toast.err(0, prefix + "403, access denied\n\ntry pressing F5, maybe you got logged out");
if (xhr.status == 404)
return toast.err(0, prefix + e404);
return toast.err(0, prefix + xhr.status + ": " + xhr.responseText);
}