mirror of
https://github.com/9001/copyparty.git
synced 2026-04-12 15:22:32 -06:00
support .hidden file for dotfiles exclusion (#1351)
similar to many desktop file managers (Dolphin, Nautilus, Thunar), the filenames in `.hidden` are cosmetically hidden in directory listings the files are still directly accessible, and will be included in download-as-zip/tar, and still appear in many other places in the UI --------- Co-authored-by: ed <s@ocv.me>
This commit is contained in:
parent
1f8ebd57dc
commit
beb634dc54
|
|
@ -24,6 +24,7 @@ from .util import (
|
|||
ODict,
|
||||
Pebkac,
|
||||
exclude_dotfiles,
|
||||
exclude_dothidden,
|
||||
fsenc,
|
||||
ipnorm,
|
||||
pybin,
|
||||
|
|
@ -350,7 +351,10 @@ class FtpFs(AbstractedFS):
|
|||
vfs_ls.extend(vfs_virt.keys())
|
||||
|
||||
if self.uname not in vfs.axs.udot:
|
||||
vfs_ls = exclude_dotfiles(vfs_ls)
|
||||
if "dothidden" in vfs.flags and ".hidden" in [x[0] for x in vfs_ls]:
|
||||
vfs_ls = exclude_dothidden(vfs_ls, fsroot)
|
||||
else:
|
||||
vfs_ls = exclude_dotfiles(vfs_ls)
|
||||
|
||||
vfs_ls.sort()
|
||||
return vfs_ls
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ from .util import (
|
|||
eol_conv,
|
||||
exclude_dotfiles,
|
||||
exclude_dotfiles_ls,
|
||||
exclude_dothidden,
|
||||
exclude_dothidden_ls,
|
||||
formatdate,
|
||||
fsenc,
|
||||
gen_content_disposition,
|
||||
|
|
@ -81,6 +83,7 @@ from .util import (
|
|||
has_resource,
|
||||
hashcopy,
|
||||
hidedir,
|
||||
load_dothidden,
|
||||
html_bescape,
|
||||
html_escape,
|
||||
html_sh_esc,
|
||||
|
|
@ -1843,7 +1846,7 @@ class HttpCli(object):
|
|||
raise Pebkac(401, "authenticate")
|
||||
|
||||
elif depth == "1":
|
||||
_, vfs_ls, vfs_virt = vn.ls(
|
||||
fsroot, vfs_ls, vfs_virt = vn.ls(
|
||||
rem,
|
||||
self.uname,
|
||||
not self.args.no_scandir,
|
||||
|
|
@ -1854,13 +1857,20 @@ class HttpCli(object):
|
|||
if not self.can_read:
|
||||
vfs_ls = []
|
||||
if not self.can_dot:
|
||||
vfs_ls = exclude_dotfiles_ls(vfs_ls)
|
||||
if "dothidden" in vn.flags and ".hidden" in [x[0] for x in vfs_ls]:
|
||||
vfs_ls = exclude_dothidden_ls(vfs_ls, fsroot)
|
||||
self.dothid = True
|
||||
else:
|
||||
vfs_ls = exclude_dotfiles_ls(vfs_ls)
|
||||
fgen = [{"vp": vp, "st": st} for vp, st in vfs_ls]
|
||||
|
||||
if vfs_virt:
|
||||
zsl = list(vfs_virt)
|
||||
if not self.can_dot:
|
||||
zsl = exclude_dotfiles(zsl)
|
||||
if "dothidden" in vn.flags and getattr(self, "dothid", False):
|
||||
zsl = exclude_dothidden(zsl, fsroot)
|
||||
else:
|
||||
zsl = exclude_dotfiles(zsl)
|
||||
fgen += [{"vp": v, "st": vst} for v in zsl]
|
||||
|
||||
else:
|
||||
|
|
@ -5859,6 +5869,7 @@ class HttpCli(object):
|
|||
dk_sz = vn.flags.get("dk")
|
||||
except:
|
||||
dk_sz = None
|
||||
vn = vfs
|
||||
vfs_ls = []
|
||||
vfs_virt = {}
|
||||
for v in self.rvol:
|
||||
|
|
@ -5869,7 +5880,11 @@ class HttpCli(object):
|
|||
dirs = [x[0] for x in vfs_ls if stat.S_ISDIR(x[1].st_mode)]
|
||||
|
||||
if not dots:
|
||||
dirs = exclude_dotfiles(dirs)
|
||||
if "dothidden" in vn.flags and ".hidden" in [x[0] for x in vfs_ls]:
|
||||
dirs = exclude_dothidden(dirs, fsroot)
|
||||
self.dothid = True
|
||||
else:
|
||||
dirs = exclude_dotfiles(dirs)
|
||||
|
||||
dirs = [quotep(x) for x in dirs if x != excl]
|
||||
|
||||
|
|
@ -5899,7 +5914,10 @@ class HttpCli(object):
|
|||
x += "\n"
|
||||
dirs.append(quotep(x))
|
||||
if not dots:
|
||||
dirs = exclude_dotfiles(dirs)
|
||||
if "dothidden" in vn.flags and getattr(self, "dothid", False):
|
||||
dirs = exclude_dothidden(dirs, fsroot)
|
||||
else:
|
||||
dirs = exclude_dotfiles(dirs)
|
||||
|
||||
ret["a"] = dirs
|
||||
return ret
|
||||
|
|
@ -7149,7 +7167,10 @@ class HttpCli(object):
|
|||
if not self.can_dot or (
|
||||
"dots" not in self.uparam and (is_ls or "dots" not in self.cookies)
|
||||
):
|
||||
ls_names = exclude_dotfiles(ls_names)
|
||||
if "dothidden" in vf and ".hidden" in ls_names:
|
||||
ls_names = exclude_dothidden(ls_names, fsroot)
|
||||
else:
|
||||
ls_names = exclude_dotfiles(ls_names)
|
||||
|
||||
add_dk = vf.get("dk")
|
||||
add_fk = vf.get("fk")
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ from .util import (
|
|||
Daemon,
|
||||
ODict,
|
||||
exclude_dotfiles,
|
||||
exclude_dothidden,
|
||||
min_ex,
|
||||
runhook,
|
||||
set_fperms,
|
||||
|
|
@ -318,7 +319,11 @@ class Tftpd(object):
|
|||
ls = virs + reals
|
||||
|
||||
if "*" not in vn.axs.udot:
|
||||
names = set(exclude_dotfiles([x[2] for x in ls]))
|
||||
zsl = [x[2] for x in ls]
|
||||
if "dothidden" in vn.flags and ".hidden" in zsl:
|
||||
names = set(exclude_dothidden(zsl, fsroot))
|
||||
else:
|
||||
names = set(exclude_dotfiles(zsl))
|
||||
ls = [x for x in ls if x[2] in names]
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -2396,6 +2396,33 @@ def exclude_dotfiles_ls(
|
|||
return [x for x in vfs_ls if not x[0].split("/")[-1].startswith(".")]
|
||||
|
||||
|
||||
def exclude_dothidden(filepaths: list[str], fsroot: Any) -> list[str]:
|
||||
ret = [x for x in filepaths if not x.split("/")[-1].startswith(".")]
|
||||
filt = load_dothidden(fsroot)
|
||||
if filt:
|
||||
ret = [x for x in ret if x.split("/")[-1] not in filt]
|
||||
return ret
|
||||
|
||||
|
||||
def exclude_dothidden_ls(
|
||||
vfs_ls: list[tuple[str, os.stat_result]], fsroot: Any
|
||||
) -> list[tuple[str, os.stat_result]]:
|
||||
ret = [x for x in vfs_ls if not x[0].split("/")[-1].startswith(".")]
|
||||
filt = load_dothidden(fsroot)
|
||||
if filt:
|
||||
ret = [x for x in ret if x[0].split("/")[-1] not in filt]
|
||||
return ret
|
||||
|
||||
|
||||
def load_dothidden(dpath: str) -> list[str]:
|
||||
try:
|
||||
with open(os.path.join(dpath, ".hidden"), "rb") as f:
|
||||
zsl = f.read().decode("utf-8").splitlines()
|
||||
return [x.strip() for x in zsl]
|
||||
except OSError:
|
||||
return []
|
||||
|
||||
|
||||
def odfusion(
|
||||
base: Union[ODict[str, bool], ODict["LiteralString", bool]], oth: str
|
||||
) -> ODict[str, bool]:
|
||||
|
|
|
|||
Loading…
Reference in a new issue