Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7770904e6 | ||
|
|
1690889ed8 | ||
|
|
842817d9e3 | ||
|
|
5fc04152bd | ||
|
|
1be85bdb26 | ||
|
|
2eafaa88a2 | ||
|
|
900cc463c3 | ||
|
|
97b999c463 |
@@ -1,6 +1,6 @@
|
|||||||
# Maintainer: icxes <dev.null@need.moe>
|
# Maintainer: icxes <dev.null@need.moe>
|
||||||
pkgname=copyparty
|
pkgname=copyparty
|
||||||
pkgver="1.9.22"
|
pkgver="1.9.24"
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, FTP, zeroconf, media indexer, thumbnails++"
|
pkgdesc="File server with accelerated resumable uploads, dedup, WebDAV, FTP, zeroconf, media indexer, thumbnails++"
|
||||||
arch=("any")
|
arch=("any")
|
||||||
@@ -21,7 +21,7 @@ optdepends=("ffmpeg: thumbnails for videos, images (slower) and audio, music tag
|
|||||||
)
|
)
|
||||||
source=("https://github.com/9001/${pkgname}/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz")
|
source=("https://github.com/9001/${pkgname}/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz")
|
||||||
backup=("etc/${pkgname}.d/init" )
|
backup=("etc/${pkgname}.d/init" )
|
||||||
sha256sums=("a54743b0a34f7d8b201b47940772f1830a924d45fe476b70ea96f93793ec028e")
|
sha256sums=("759fbc7b3063c5e39c49a9524200568ca30c664c8323b1e396d5e58378dc8b80")
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
cd "${srcdir}/${pkgname}-${pkgver}"
|
cd "${srcdir}/${pkgname}-${pkgver}"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"url": "https://github.com/9001/copyparty/releases/download/v1.9.22/copyparty-sfx.py",
|
"url": "https://github.com/9001/copyparty/releases/download/v1.9.24/copyparty-sfx.py",
|
||||||
"version": "1.9.22",
|
"version": "1.9.24",
|
||||||
"hash": "sha256-FfGJGCeRuv8YF7xfi5whmnr4M3+Qcdx/ysSZKJNsysM="
|
"hash": "sha256-GuKeNrH9rcsUlM7c/cQ0QKlpteu+cGfGmzxRp4ACclw="
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
VERSION = (1, 9, 23)
|
VERSION = (1, 9, 25)
|
||||||
CODENAME = "prometheable"
|
CODENAME = "prometheable"
|
||||||
BUILD_DT = (2023, 12, 1)
|
BUILD_DT = (2023, 12, 1)
|
||||||
|
|
||||||
|
|||||||
@@ -957,7 +957,6 @@ class AuthSrv(object):
|
|||||||
err = ""
|
err = ""
|
||||||
try:
|
try:
|
||||||
self._l(ln, 5, "volume access config:")
|
self._l(ln, 5, "volume access config:")
|
||||||
assert vp
|
|
||||||
sk, sv = ln.split(":")
|
sk, sv = ln.split(":")
|
||||||
if re.sub("[rwmdgGha]", "", sk) or not sk:
|
if re.sub("[rwmdgGha]", "", sk) or not sk:
|
||||||
err = "invalid accs permissions list; "
|
err = "invalid accs permissions list; "
|
||||||
@@ -975,7 +974,6 @@ class AuthSrv(object):
|
|||||||
err = ""
|
err = ""
|
||||||
try:
|
try:
|
||||||
self._l(ln, 6, "volume-specific config:")
|
self._l(ln, 6, "volume-specific config:")
|
||||||
assert vp
|
|
||||||
zd = split_cfg_ln(ln)
|
zd = split_cfg_ln(ln)
|
||||||
fstr = ""
|
fstr = ""
|
||||||
for sk, sv in zd.items():
|
for sk, sv in zd.items():
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ class HttpCli(object):
|
|||||||
|
|
||||||
if self.args.ipa_re and not self.args.ipa_re.match(self.conn.addr[0]):
|
if self.args.ipa_re and not self.args.ipa_re.match(self.conn.addr[0]):
|
||||||
self.log("client rejected (--ipa)", 3)
|
self.log("client rejected (--ipa)", 3)
|
||||||
|
self.terse_reply(b"", 500)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -372,22 +373,33 @@ class HttpCli(object):
|
|||||||
self.trailing_slash = vpath.endswith("/")
|
self.trailing_slash = vpath.endswith("/")
|
||||||
vpath = undot(vpath)
|
vpath = undot(vpath)
|
||||||
|
|
||||||
zs = unquotep(arglist)
|
ptn = self.conn.hsrv.ptn_cc
|
||||||
m = self.conn.hsrv.ptn_cc.search(zs)
|
|
||||||
if m:
|
|
||||||
hit = zs[m.span()[0] :]
|
|
||||||
t = "malicious user; Cc in query [{}] => [{!r}]"
|
|
||||||
self.log(t.format(self.req, hit), 1)
|
|
||||||
return False
|
|
||||||
|
|
||||||
for k in arglist.split("&"):
|
for k in arglist.split("&"):
|
||||||
if "=" in k:
|
if "=" in k:
|
||||||
k, zs = k.split("=", 1)
|
k, zs = k.split("=", 1)
|
||||||
# x-www-form-urlencoded (url query part) uses
|
# x-www-form-urlencoded (url query part) uses
|
||||||
# either + or %20 for 0x20 so handle both
|
# either + or %20 for 0x20 so handle both
|
||||||
uparam[k.lower()] = unquotep(zs.strip().replace("+", " "))
|
sv = unquotep(zs.strip().replace("+", " "))
|
||||||
else:
|
else:
|
||||||
uparam[k.lower()] = ""
|
sv = ""
|
||||||
|
|
||||||
|
k = k.lower()
|
||||||
|
uparam[k] = sv
|
||||||
|
|
||||||
|
if k in ("doc", "move", "tree"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
zs = "%s=%s" % (k, sv)
|
||||||
|
m = ptn.search(zs)
|
||||||
|
if not m:
|
||||||
|
continue
|
||||||
|
|
||||||
|
hit = zs[m.span()[0] :]
|
||||||
|
t = "malicious user; Cc in query [{}] => [{!r}]"
|
||||||
|
self.log(t.format(self.req, hit), 1)
|
||||||
|
self.cbonk(self.conn.hsrv.gmal, self.req, "cc_q", "Cc in query")
|
||||||
|
self.terse_reply(b"", 500)
|
||||||
|
return False
|
||||||
|
|
||||||
if self.is_vproxied:
|
if self.is_vproxied:
|
||||||
if vpath.startswith(self.args.R):
|
if vpath.startswith(self.args.R):
|
||||||
@@ -426,7 +438,7 @@ class HttpCli(object):
|
|||||||
|
|
||||||
if relchk(self.vpath) and (self.vpath != "*" or self.mode != "OPTIONS"):
|
if relchk(self.vpath) and (self.vpath != "*" or self.mode != "OPTIONS"):
|
||||||
self.log("invalid relpath [{}]".format(self.vpath))
|
self.log("invalid relpath [{}]".format(self.vpath))
|
||||||
self.cbonk(self.conn.hsrv.g422, self.vpath, "bad_vp", "invalid relpaths")
|
self.cbonk(self.conn.hsrv.gmal, self.req, "bad_vp", "invalid relpaths")
|
||||||
return self.tx_404() and self.keepalive
|
return self.tx_404() and self.keepalive
|
||||||
|
|
||||||
zso = self.headers.get("authorization")
|
zso = self.headers.get("authorization")
|
||||||
@@ -542,6 +554,7 @@ class HttpCli(object):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if pex.code == 999:
|
if pex.code == 999:
|
||||||
|
self.terse_reply(b"", 500)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
post = self.mode in ["POST", "PUT"] or "content-length" in self.headers
|
post = self.mode in ["POST", "PUT"] or "content-length" in self.headers
|
||||||
@@ -626,8 +639,7 @@ class HttpCli(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
self.log("banned for {:.0f} sec".format(rt), 6)
|
self.log("banned for {:.0f} sec".format(rt), 6)
|
||||||
zb = b"HTTP/1.0 403 Forbidden\r\n\r\nthank you for playing"
|
self.terse_reply(b"thank you for playing", 403)
|
||||||
self.s.sendall(zb)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def permit_caching(self) -> None:
|
def permit_caching(self) -> None:
|
||||||
@@ -681,6 +693,7 @@ class HttpCli(object):
|
|||||||
hit = zs[m.span()[0] :]
|
hit = zs[m.span()[0] :]
|
||||||
t = "malicious user; Cc in out-hdr {!r} => [{!r}]"
|
t = "malicious user; Cc in out-hdr {!r} => [{!r}]"
|
||||||
self.log(t.format(zs, hit), 1)
|
self.log(t.format(zs, hit), 1)
|
||||||
|
self.cbonk(self.conn.hsrv.gmal, zs, "cc_hdr", "Cc in out-hdr")
|
||||||
raise Pebkac(999)
|
raise Pebkac(999)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -757,6 +770,19 @@ class HttpCli(object):
|
|||||||
self.log(body.rstrip())
|
self.log(body.rstrip())
|
||||||
self.reply(body.encode("utf-8") + b"\r\n", *list(args), **kwargs)
|
self.reply(body.encode("utf-8") + b"\r\n", *list(args), **kwargs)
|
||||||
|
|
||||||
|
def terse_reply(self, body: bytes, status: int = 200) -> None:
|
||||||
|
self.keepalive = False
|
||||||
|
|
||||||
|
lines = [
|
||||||
|
"%s %s %s" % (self.http_ver or "HTTP/1.1", status, HTTPCODE[status]),
|
||||||
|
"Connection: Close",
|
||||||
|
]
|
||||||
|
|
||||||
|
if body:
|
||||||
|
lines.append("Content-Length: " + unicode(len(body)))
|
||||||
|
|
||||||
|
self.s.sendall("\r\n".join(lines).encode("utf-8") + b"\r\n\r\n" + body)
|
||||||
|
|
||||||
def urlq(self, add: dict[str, str], rm: list[str]) -> str:
|
def urlq(self, add: dict[str, str], rm: list[str]) -> str:
|
||||||
"""
|
"""
|
||||||
generates url query based on uparam (b, pw, all others)
|
generates url query based on uparam (b, pw, all others)
|
||||||
@@ -926,6 +952,7 @@ class HttpCli(object):
|
|||||||
if not static_path.startswith(path_base):
|
if not static_path.startswith(path_base):
|
||||||
t = "malicious user; attempted path traversal [{}] => [{}]"
|
t = "malicious user; attempted path traversal [{}] => [{}]"
|
||||||
self.log(t.format(self.vpath, static_path), 1)
|
self.log(t.format(self.vpath, static_path), 1)
|
||||||
|
self.cbonk(self.conn.hsrv.gmal, self.req, "trav", "path traversal")
|
||||||
|
|
||||||
self.tx_404()
|
self.tx_404()
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ class HttpSrv(object):
|
|||||||
self.g404 = Garda(self.args.ban_404)
|
self.g404 = Garda(self.args.ban_404)
|
||||||
self.g403 = Garda(self.args.ban_403)
|
self.g403 = Garda(self.args.ban_403)
|
||||||
self.g422 = Garda(self.args.ban_422, False)
|
self.g422 = Garda(self.args.ban_422, False)
|
||||||
|
self.gmal = Garda(self.args.ban_422)
|
||||||
self.gurl = Garda(self.args.ban_url)
|
self.gurl = Garda(self.args.ban_url)
|
||||||
self.bans: dict[str, int] = {}
|
self.bans: dict[str, int] = {}
|
||||||
self.aclose: dict[str, int] = {}
|
self.aclose: dict[str, int] = {}
|
||||||
|
|||||||
@@ -138,7 +138,8 @@ class SvcHub(object):
|
|||||||
self.gpwd = Garda(self.args.ban_pw)
|
self.gpwd = Garda(self.args.ban_pw)
|
||||||
self.g404 = Garda(self.args.ban_404)
|
self.g404 = Garda(self.args.ban_404)
|
||||||
self.g403 = Garda(self.args.ban_403)
|
self.g403 = Garda(self.args.ban_403)
|
||||||
self.g422 = Garda(self.args.ban_422)
|
self.g422 = Garda(self.args.ban_422, False)
|
||||||
|
self.gmal = Garda(self.args.ban_422)
|
||||||
self.gurl = Garda(self.args.ban_url)
|
self.gurl = Garda(self.args.ban_url)
|
||||||
|
|
||||||
self.log_div = 10 ** (6 - args.log_tdec)
|
self.log_div = 10 ** (6 - args.log_tdec)
|
||||||
|
|||||||
@@ -3656,7 +3656,7 @@ var fileman = (function () {
|
|||||||
(function (a) {
|
(function (a) {
|
||||||
f[a].inew.onkeydown = function (e) {
|
f[a].inew.onkeydown = function (e) {
|
||||||
rn_ok(a, true);
|
rn_ok(a, true);
|
||||||
if (e.key == 'Enter')
|
if (e.key.endsWith('Enter'))
|
||||||
return rn_apply();
|
return rn_apply();
|
||||||
};
|
};
|
||||||
QS('.rn_dec' + k).onclick = function (e) {
|
QS('.rn_dec' + k).onclick = function (e) {
|
||||||
@@ -3751,7 +3751,7 @@ var fileman = (function () {
|
|||||||
if (e.key == 'Escape')
|
if (e.key == 'Escape')
|
||||||
return rn_cancel();
|
return rn_cancel();
|
||||||
|
|
||||||
if (e.key == 'Enter')
|
if (e.key.endsWith('Enter'))
|
||||||
return rn_apply();
|
return rn_apply();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -4462,6 +4462,7 @@ var thegrid = (function () {
|
|||||||
filecols.uivis();
|
filecols.uivis();
|
||||||
|
|
||||||
aligngriditems();
|
aligngriditems();
|
||||||
|
restore_scroll();
|
||||||
};
|
};
|
||||||
|
|
||||||
r.setdirty = function () {
|
r.setdirty = function () {
|
||||||
@@ -4999,7 +5000,7 @@ document.onkeydown = function (e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k == 'Enter' && ae && (ae.onclick || ae.hasAttribute('tabIndex')))
|
if (k.endsWith('Enter') && ae && (ae.onclick || ae.hasAttribute('tabIndex')))
|
||||||
return ev(e) && ae.click() || true;
|
return ev(e) && ae.click() || true;
|
||||||
|
|
||||||
if (aet && aet != 'a' && aet != 'tr' && aet != 'pre')
|
if (aet && aet != 'a' && aet != 'tr' && aet != 'pre')
|
||||||
@@ -5197,7 +5198,7 @@ document.onkeydown = function (e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ev_search_keydown(e) {
|
function ev_search_keydown(e) {
|
||||||
if (e.key == 'Enter')
|
if (e.key.endsWith('Enter'))
|
||||||
do_search();
|
do_search();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7767,10 +7768,36 @@ ebi('path').onclick = function (e) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var scroll_y = -1;
|
||||||
|
var scroll_vp = '\n';
|
||||||
|
var scroll_obj = null;
|
||||||
|
function persist_scroll() {
|
||||||
|
var obj = scroll_obj;
|
||||||
|
if (!obj) {
|
||||||
|
var o1 = document.getElementsByTagName('html')[0];
|
||||||
|
var o2 = document.body;
|
||||||
|
obj = o1.scrollTop > o2.scrollTop ? o1 : o2;
|
||||||
|
}
|
||||||
|
var y = obj.scrollTop;
|
||||||
|
if (y > 0)
|
||||||
|
scroll_obj = obj;
|
||||||
|
|
||||||
|
scroll_y = y;
|
||||||
|
scroll_vp = get_evpath();
|
||||||
|
}
|
||||||
|
function restore_scroll() {
|
||||||
|
if (get_evpath() == scroll_vp && scroll_obj && scroll_obj.scrollTop < 1)
|
||||||
|
scroll_obj.scrollTop = scroll_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ebi('files').onclick = ebi('docul').onclick = function (e) {
|
ebi('files').onclick = ebi('docul').onclick = function (e) {
|
||||||
if (!treectl.csel && e && (ctrl(e) || e.shiftKey))
|
if (!treectl.csel && e && (ctrl(e) || e.shiftKey))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (!showfile.active())
|
||||||
|
persist_scroll();
|
||||||
|
|
||||||
var tgt = e.target.closest('a[id]');
|
var tgt = e.target.closest('a[id]');
|
||||||
if (tgt && tgt.getAttribute('id').indexOf('f-') === 0 && tgt.textContent.endsWith('/')) {
|
if (tgt && tgt.getAttribute('id').indexOf('f-') === 0 && tgt.textContent.endsWith('/')) {
|
||||||
var el = treectl.find(tgt.textContent.slice(0, -1));
|
var el = treectl.find(tgt.textContent.slice(0, -1));
|
||||||
|
|||||||
@@ -1009,7 +1009,7 @@ var set_lno = (function () {
|
|||||||
md_home(ev.shiftKey);
|
md_home(ev.shiftKey);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!ev.shiftKey && (ev.code == "Enter" || kc == 13)) {
|
if (!ev.shiftKey && (ev.code.endsWith("Enter") || kc == 13)) {
|
||||||
return md_newline();
|
return md_newline();
|
||||||
}
|
}
|
||||||
if (!ev.shiftKey && kc == 8) {
|
if (!ev.shiftKey && kc == 8) {
|
||||||
|
|||||||
@@ -1482,6 +1482,7 @@ var modal = (function () {
|
|||||||
a.onclick = ng;
|
a.onclick = ng;
|
||||||
|
|
||||||
a = ebi('modal-ok');
|
a = ebi('modal-ok');
|
||||||
|
a.addEventListener('blur', onblur);
|
||||||
a.onclick = ok;
|
a.onclick = ok;
|
||||||
|
|
||||||
var inp = ebi('modali');
|
var inp = ebi('modali');
|
||||||
@@ -1500,6 +1501,10 @@ var modal = (function () {
|
|||||||
|
|
||||||
r.hide = function () {
|
r.hide = function () {
|
||||||
timer.rm(onfocus);
|
timer.rm(onfocus);
|
||||||
|
try {
|
||||||
|
ebi('modal-ok').removeEventListener('blur', onblur);
|
||||||
|
}
|
||||||
|
catch (ex) { }
|
||||||
document.removeEventListener('selectionchange', onselch);
|
document.removeEventListener('selectionchange', onselch);
|
||||||
document.removeEventListener('focus', onfocus);
|
document.removeEventListener('focus', onfocus);
|
||||||
document.removeEventListener('keydown', onkey);
|
document.removeEventListener('keydown', onkey);
|
||||||
@@ -1522,24 +1527,35 @@ var modal = (function () {
|
|||||||
cb_ng(null);
|
cb_ng(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
var onselch = function (e) {
|
var onselch = function () {
|
||||||
r.nofocus = 30;
|
try {
|
||||||
|
if (window.getSelection() + '')
|
||||||
|
r.nofocus = 15;
|
||||||
|
}
|
||||||
|
catch (ex) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
var onblur = function () {
|
||||||
|
r.nofocus = 3;
|
||||||
};
|
};
|
||||||
|
|
||||||
var onfocus = function (e) {
|
var onfocus = function (e) {
|
||||||
|
if (MOBILE)
|
||||||
|
return;
|
||||||
|
|
||||||
var ctr = ebi('modalc');
|
var ctr = ebi('modalc');
|
||||||
if (!ctr || !ctr.contains || !document.activeElement || ctr.contains(document.activeElement))
|
if (!ctr || !ctr.contains || !document.activeElement || ctr.contains(document.activeElement))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
if (--r.nofocus > 0)
|
if (--r.nofocus >= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ctr = ebi('modal-ok'))
|
if (ctr = ebi('modal-ok'))
|
||||||
ctr.focus();
|
ctr.focus();
|
||||||
}, 20);
|
}, 20);
|
||||||
ev(e);
|
ev(e);
|
||||||
}
|
};
|
||||||
|
|
||||||
var onkey = function (e) {
|
var onkey = function (e) {
|
||||||
var k = e.code,
|
var k = e.code,
|
||||||
@@ -1550,7 +1566,7 @@ var modal = (function () {
|
|||||||
if (k == 'Space' && ae && (ae === eok || ae === eng))
|
if (k == 'Space' && ae && (ae === eok || ae === eng))
|
||||||
k = 'Enter';
|
k = 'Enter';
|
||||||
|
|
||||||
if (k == 'Enter') {
|
if (k.endsWith('Enter')) {
|
||||||
if (ae && ae == eng)
|
if (ae && ae == eng)
|
||||||
return ng(e);
|
return ng(e);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,27 @@
|
|||||||
|
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||||
|
# 2023-1201-0210 `v1.9.24` header auth
|
||||||
|
|
||||||
|
## new features
|
||||||
|
* initial work on #62 (support identity providers, oauth/SSO/...); see [readme](https://github.com/9001/copyparty#identity-providers)
|
||||||
|
* only authentication so far; no authorization yet, and users must exist in the copyparty config with bogus passwords
|
||||||
|
* new option `--ipa` rejects connections from clients outside of a given allowlist of IP prefixes
|
||||||
|
* environment variables can be used almost everywhere that takes a filesystem path; should make it way more comfy to write configs for docker / systemd
|
||||||
|
* #59 added a basic [docker-compose yaml](https://github.com/9001/copyparty/blob/hovudstraum/docs/examples/docker/basic-docker-compose) and an example config
|
||||||
|
* probably much room for improvement on everything docker still
|
||||||
|
|
||||||
|
## bugfixes
|
||||||
|
* the nftables-based port-forwarding in the [systemd example](https://github.com/9001/copyparty/tree/hovudstraum/contrib/systemd) was buggy; replaced with CAP_NET_BIND_SERVICE
|
||||||
|
* palemoon-specific js crash if a text selection was dragged
|
||||||
|
* text selection in messageboxes was jank
|
||||||
|
|
||||||
|
## other changes
|
||||||
|
* improved [systemd example](https://github.com/9001/copyparty/tree/hovudstraum/contrib/systemd) with hardening and a better example config
|
||||||
|
* logfiles are flushed for every line written; can be disabled with `--no-logflush` for ~3% more performance best-case
|
||||||
|
* iphones probably won't broadcast cover-art to car stereos over bluetooth anymore since the thingamajig in iOS that's in charge of that doesn't have cookie-access, and strapping in the auth is too funky so let's stop doing that b7723ac245b8b3e38d6410891ef1aa92d4772114
|
||||||
|
* can be remedied by enabling filekeys and granting unauthenticated people access that way, but that's too much effort for anyone to bother with I'm sure
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||||
# 2023-1125-1417 `v1.9.21` in a bind
|
# 2023-1125-1417 `v1.9.21` in a bind
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class Cfg(Namespace):
|
|||||||
ex = "dotpart no_rescan no_sendfile no_voldump plain_ip"
|
ex = "dotpart no_rescan no_sendfile no_voldump plain_ip"
|
||||||
ka.update(**{k: True for k in ex.split()})
|
ka.update(**{k: True for k in ex.split()})
|
||||||
|
|
||||||
ex = "ah_cli ah_gen css_browser hist js_browser no_forget no_hash no_idx nonsus_urls"
|
ex = "ah_cli ah_gen css_browser hist ipa_re js_browser no_forget no_hash no_idx nonsus_urls"
|
||||||
ka.update(**{k: None for k in ex.split()})
|
ka.update(**{k: None for k in ex.split()})
|
||||||
|
|
||||||
ex = "s_thead s_tbody th_convt"
|
ex = "s_thead s_tbody th_convt"
|
||||||
@@ -124,7 +124,7 @@ class Cfg(Namespace):
|
|||||||
ex = "df loris re_maxage rproxy rsp_jtr rsp_slp s_wr_slp theme themes turbo"
|
ex = "df loris re_maxage rproxy rsp_jtr rsp_slp s_wr_slp theme themes turbo"
|
||||||
ka.update(**{k: 0 for k in ex.split()})
|
ka.update(**{k: 0 for k in ex.split()})
|
||||||
|
|
||||||
ex = "ah_alg bname doctitle favico html_head lg_sbf log_fk md_sbf name textfiles unlist vname R RS SR"
|
ex = "ah_alg bname doctitle favico hdr_au_usr html_head lg_sbf log_fk md_sbf name textfiles unlist vname R RS SR"
|
||||||
ka.update(**{k: "" for k in ex.split()})
|
ka.update(**{k: "" for k in ex.split()})
|
||||||
|
|
||||||
ex = "on403 on404 xad xar xau xban xbd xbr xbu xiu xm"
|
ex = "on403 on404 xad xar xau xban xbd xbr xbu xiu xm"
|
||||||
|
|||||||
Reference in New Issue
Block a user