mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
fix filekeys inside symlinked volumes
This commit is contained in:
parent
75cdf17df4
commit
1c3894743a
|
@ -634,6 +634,7 @@ def run_argparse(argv: list[str], formatter: Any, retry: bool) -> argparse.Names
|
|||
ap2.add_argument("--no-htp", action="store_true", help="disable httpserver threadpool, create threads as-needed instead")
|
||||
ap2.add_argument("--stackmon", metavar="P,S", type=u, help="write stacktrace to Path every S second")
|
||||
ap2.add_argument("--log-thrs", metavar="SEC", type=float, help="list active threads every SEC")
|
||||
ap2.add_argument("--log-fk", metavar="REGEX", type=u, default="", help="log filekey params for files where path matches REGEX; '.' (a single dot) = all files")
|
||||
# fmt: on
|
||||
|
||||
ap2 = ap.add_argument_group("help sections")
|
||||
|
|
|
@ -707,7 +707,7 @@ class AuthSrv(object):
|
|||
raise Exception('invalid mountpoint "{}"'.format(vol_dst))
|
||||
|
||||
# cfg files override arguments and previous files
|
||||
vol_src = bos.path.abspath(vol_src)
|
||||
vol_src = absreal(vol_src)
|
||||
vol_dst = vol_dst.strip("/")
|
||||
self._map_volume(vol_src, vol_dst, mount, daxs, mflags)
|
||||
continue
|
||||
|
@ -818,7 +818,7 @@ class AuthSrv(object):
|
|||
src = uncyg(src)
|
||||
|
||||
# print("\n".join([src, dst, perms]))
|
||||
src = bos.path.abspath(src)
|
||||
src = absreal(src)
|
||||
dst = dst.strip("/")
|
||||
self._map_volume(src, dst, mount, daxs, mflags)
|
||||
|
||||
|
@ -847,7 +847,7 @@ class AuthSrv(object):
|
|||
if not mount:
|
||||
# -h says our defaults are CWD at root and read/write for everyone
|
||||
axs = AXS(["*"], ["*"], None, None)
|
||||
vfs = VFS(self.log_func, bos.path.abspath("."), "", axs, {})
|
||||
vfs = VFS(self.log_func, absreal("."), "", axs, {})
|
||||
elif "" not in mount:
|
||||
# there's volumes but no root; make root inaccessible
|
||||
vfs = VFS(self.log_func, "", "", AXS(), {})
|
||||
|
@ -1029,10 +1029,15 @@ class AuthSrv(object):
|
|||
vol.flags["dathumb"] = True
|
||||
vol.flags["dithumb"] = True
|
||||
|
||||
have_fk = False
|
||||
for vol in vfs.all_vols.values():
|
||||
fk = vol.flags.get("fk")
|
||||
if fk:
|
||||
vol.flags["fk"] = int(fk) if fk is not True else 8
|
||||
have_fk = True
|
||||
|
||||
if have_fk and re.match("^[0-9\.]+$", self.args.fk_salt):
|
||||
self.log("filekey salt: {}".format(self.args.fk_salt))
|
||||
|
||||
for vol in vfs.all_vols.values():
|
||||
if "pk" in vol.flags and "gz" not in vol.flags and "xz" not in vol.flags:
|
||||
|
|
|
@ -42,6 +42,7 @@ from .util import (
|
|||
exclude_dotfiles,
|
||||
fsenc,
|
||||
gen_filekey,
|
||||
gen_filekey_dbg,
|
||||
gencookie,
|
||||
get_df,
|
||||
get_spd,
|
||||
|
@ -108,6 +109,7 @@ class HttpCli(object):
|
|||
self.u2fh = conn.u2fh # mypy404
|
||||
self.log_func = conn.log_func # mypy404
|
||||
self.log_src = conn.log_src # mypy404
|
||||
self.gen_fk = self._gen_fk if self.args.log_fk else gen_filekey
|
||||
self.tls: bool = hasattr(self.s, "cipher")
|
||||
|
||||
# placeholders; assigned by run()
|
||||
|
@ -177,6 +179,9 @@ class HttpCli(object):
|
|||
if rem.startswith("/") or rem.startswith("../") or "/../" in rem:
|
||||
raise Exception("that was close")
|
||||
|
||||
def _gen_fk(self, salt: str, fspath: str, fsize: int, inode: int) -> str:
|
||||
return gen_filekey_dbg(salt, fspath, fsize, inode, self.log, self.args.log_fk)
|
||||
|
||||
def j2s(self, name: str, **ka: Any) -> str:
|
||||
tpl = self.conn.hsrv.j2[name]
|
||||
ka["ts"] = self.conn.hsrv.cachebuster()
|
||||
|
@ -711,7 +716,7 @@ class HttpCli(object):
|
|||
reader, remains = self.get_body_reader()
|
||||
vfs, rem = self.asrv.vfs.get(self.vpath, self.uname, False, True)
|
||||
lim = vfs.get_dbv(rem)[0].lim
|
||||
fdir = os.path.join(vfs.realpath, rem)
|
||||
fdir = vfs.canonical(rem)
|
||||
if lim:
|
||||
fdir, rem = lim.all(self.ip, rem, remains, fdir)
|
||||
|
||||
|
@ -813,7 +818,7 @@ class HttpCli(object):
|
|||
|
||||
vsuf = ""
|
||||
if self.can_read and "fk" in vfs.flags:
|
||||
vsuf = "?k=" + gen_filekey(
|
||||
vsuf = "?k=" + self.gen_fk(
|
||||
self.args.fk_salt,
|
||||
path,
|
||||
post_sz,
|
||||
|
@ -950,7 +955,7 @@ class HttpCli(object):
|
|||
|
||||
if rem:
|
||||
try:
|
||||
dst = os.path.join(vfs.realpath, rem)
|
||||
dst = vfs.canonical(rem)
|
||||
if not bos.path.isdir(dst):
|
||||
bos.makedirs(dst)
|
||||
except OSError as ex:
|
||||
|
@ -1185,7 +1190,7 @@ class HttpCli(object):
|
|||
sanitized = sanitize_fn(new_dir, "", [])
|
||||
|
||||
if not nullwrite:
|
||||
fdir = os.path.join(vfs.realpath, rem)
|
||||
fdir = vfs.canonical(rem)
|
||||
fn = os.path.join(fdir, sanitized)
|
||||
|
||||
if not bos.path.isdir(fdir):
|
||||
|
@ -1224,7 +1229,7 @@ class HttpCli(object):
|
|||
sanitized = sanitize_fn(new_file, "", [])
|
||||
|
||||
if not nullwrite:
|
||||
fdir = os.path.join(vfs.realpath, rem)
|
||||
fdir = vfs.canonical(rem)
|
||||
fn = os.path.join(fdir, sanitized)
|
||||
|
||||
if bos.path.exists(fn):
|
||||
|
@ -1245,7 +1250,7 @@ class HttpCli(object):
|
|||
|
||||
upload_vpath = self.vpath
|
||||
lim = vfs.get_dbv(rem)[0].lim
|
||||
fdir_base = os.path.join(vfs.realpath, rem)
|
||||
fdir_base = vfs.canonical(rem)
|
||||
if lim:
|
||||
fdir_base, rem = lim.all(self.ip, rem, -1, fdir_base)
|
||||
upload_vpath = "{}/{}".format(vfs.vpath, rem).strip("/")
|
||||
|
@ -1286,7 +1291,7 @@ class HttpCli(object):
|
|||
else:
|
||||
open_args = {}
|
||||
tnam = fname = os.devnull
|
||||
fdir = ""
|
||||
fdir = abspath = ""
|
||||
|
||||
if lim:
|
||||
lim.chk_bup(self.ip)
|
||||
|
@ -1318,12 +1323,15 @@ class HttpCli(object):
|
|||
lim.chk_bup(self.ip)
|
||||
lim.chk_nup(self.ip)
|
||||
except:
|
||||
bos.unlink(tabspath)
|
||||
bos.unlink(abspath)
|
||||
if not nullwrite:
|
||||
bos.unlink(tabspath)
|
||||
bos.unlink(abspath)
|
||||
fname = os.devnull
|
||||
raise
|
||||
|
||||
atomic_move(tabspath, abspath)
|
||||
if not nullwrite:
|
||||
atomic_move(tabspath, abspath)
|
||||
|
||||
files.append(
|
||||
(sz, sha_hex, sha_b64, p_file or "(discarded)", fname, abspath)
|
||||
)
|
||||
|
@ -1373,9 +1381,9 @@ class HttpCli(object):
|
|||
for sz, sha_hex, sha_b64, ofn, lfn, ap in files:
|
||||
vsuf = ""
|
||||
if self.can_read and "fk" in vfs.flags:
|
||||
vsuf = "?k=" + gen_filekey(
|
||||
vsuf = "?k=" + self.gen_fk(
|
||||
self.args.fk_salt,
|
||||
abspath,
|
||||
ap,
|
||||
sz,
|
||||
0 if ANYWIN or not ap else bos.stat(ap).st_ino,
|
||||
)[: vfs.flags["fk"]]
|
||||
|
@ -1453,7 +1461,7 @@ class HttpCli(object):
|
|||
raise Pebkac(411)
|
||||
|
||||
rp, fn = vsplit(rem)
|
||||
fp = os.path.join(vfs.realpath, rp)
|
||||
fp = vfs.canonical(rp)
|
||||
lim = vfs.get_dbv(rem)[0].lim
|
||||
if lim:
|
||||
fp, rp = lim.all(self.ip, rp, clen, fp)
|
||||
|
@ -2310,7 +2318,7 @@ class HttpCli(object):
|
|||
|
||||
if not is_dir and (self.can_read or self.can_get):
|
||||
if not self.can_read and "fk" in vn.flags:
|
||||
correct = gen_filekey(
|
||||
correct = self.gen_fk(
|
||||
self.args.fk_salt, abspath, st.st_size, 0 if ANYWIN else st.st_ino
|
||||
)[: vn.flags["fk"]]
|
||||
got = self.uparam.get("k")
|
||||
|
@ -2534,7 +2542,7 @@ class HttpCli(object):
|
|||
if add_fk:
|
||||
href = "{}?k={}".format(
|
||||
quotep(href),
|
||||
gen_filekey(
|
||||
self.gen_fk(
|
||||
self.args.fk_salt, fspath, sz, 0 if ANYWIN else inf.st_ino
|
||||
)[:add_fk],
|
||||
)
|
||||
|
|
|
@ -6,6 +6,7 @@ import base64
|
|||
import calendar
|
||||
import gzip
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import signal
|
||||
import socket
|
||||
|
@ -113,6 +114,9 @@ class SvcHub(object):
|
|||
if not args.hardlink and args.never_symlink:
|
||||
args.no_dedup = True
|
||||
|
||||
if args.log_fk:
|
||||
args.log_fk = re.compile(args.log_fk)
|
||||
|
||||
# initiate all services to manage
|
||||
self.asrv = AuthSrv(self.args, self.log)
|
||||
if args.ls:
|
||||
|
|
|
@ -46,7 +46,7 @@ try:
|
|||
from collections.abc import Callable, Iterable
|
||||
|
||||
import typing
|
||||
from typing import Any, Generator, Optional, Protocol, Union
|
||||
from typing import Any, Generator, Optional, Pattern, Protocol, Union
|
||||
|
||||
class RootLogger(Protocol):
|
||||
def __call__(self, src: str, msg: str, c: Union[int, str] = 0) -> None:
|
||||
|
@ -932,6 +932,24 @@ def gen_filekey(salt: str, fspath: str, fsize: int, inode: int) -> str:
|
|||
).decode("ascii")
|
||||
|
||||
|
||||
def gen_filekey_dbg(
|
||||
salt: str,
|
||||
fspath: str,
|
||||
fsize: int,
|
||||
inode: int,
|
||||
log: "NamedLogger",
|
||||
log_ptn: Optional[Pattern[str]],
|
||||
) -> str:
|
||||
ret = gen_filekey(salt, fspath, fsize, inode)
|
||||
|
||||
assert log_ptn
|
||||
if log_ptn.search(fspath):
|
||||
t = "fk({}) salt({}) size({}) inode({}) fspath({})"
|
||||
log(t.format(ret[:8], salt, fsize, inode, fspath))
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def gencookie(k: str, v: str, dur: Optional[int]) -> str:
|
||||
v = v.replace(";", "")
|
||||
if dur:
|
||||
|
|
|
@ -106,7 +106,7 @@ class Cfg(Namespace):
|
|||
ex = "re_maxage rproxy rsp_slp s_wr_slp theme themes turbo df"
|
||||
ka.update(**{k: 0 for k in ex.split()})
|
||||
|
||||
ex = "doctitle favico html_head mth textfiles"
|
||||
ex = "doctitle favico html_head mth textfiles log_fk"
|
||||
ka.update(**{k: "" for k in ex.split()})
|
||||
|
||||
super(Cfg, self).__init__(
|
||||
|
|
Loading…
Reference in a new issue