mirror of
https://github.com/9001/copyparty.git
synced 2025-08-18 01:22:13 -06:00
add logout on inactivity + related errorhandling
This commit is contained in:
parent
00b5db52cf
commit
b50d090946
|
@ -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")
|
||||
|
|
|
@ -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 ┐( ´ -`)┌</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 ~┻━┻</h1><p>you\'ll have to log in or <a href="/?h">go home</a></p>'
|
||||
rc = 403
|
||||
else:
|
||||
m = '<h1>404 not found ┐( ´ -`)┌</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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue