mirror of
https://github.com/9001/copyparty.git
synced 2026-04-02 22:08:38 +10:00
list dotfiles only for specific volumes or users (#66):
* permission `.` grants dotfile visibility if user has `r` too * `-ed` will grant dotfiles to all `r` accounts (same as before) * volflag `dots` likewise also drops compatibility for pre-0.12.0 `-v` syntax (`-v .::red` will no longer translate to `-v .::r,ed`)
This commit is contained in:
111
tests/test_dots.py
Normal file
111
tests/test_dots.py
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding: utf-8
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import io
|
||||
import os
|
||||
import shutil
|
||||
import tarfile
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from copyparty.authsrv import AuthSrv
|
||||
from copyparty.httpcli import HttpCli
|
||||
from copyparty.up2k import Up2k
|
||||
from copyparty.u2idx import U2idx
|
||||
from tests import util as tu
|
||||
from tests.util import Cfg
|
||||
|
||||
|
||||
def hdr(query, uname):
|
||||
h = "GET /%s HTTP/1.1\r\nPW: %s\r\nConnection: close\r\n\r\n"
|
||||
return (h % (query, uname)).encode("utf-8")
|
||||
|
||||
|
||||
class TestHttpCli(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.td = tu.get_ramdisk()
|
||||
|
||||
def tearDown(self):
|
||||
os.chdir(tempfile.gettempdir())
|
||||
shutil.rmtree(self.td)
|
||||
|
||||
def test(self):
|
||||
td = os.path.join(self.td, "vfs")
|
||||
os.mkdir(td)
|
||||
os.chdir(td)
|
||||
|
||||
# topDir volA volA/*dirA .volB .volB/*dirB
|
||||
spaths = " t .t a a/da a/.da .b .b/db .b/.db"
|
||||
for n, dirpath in enumerate(spaths.split(" ")):
|
||||
if dirpath:
|
||||
os.makedirs(dirpath)
|
||||
|
||||
for pfx in "f", ".f":
|
||||
filepath = pfx + str(n)
|
||||
if dirpath:
|
||||
filepath = os.path.join(dirpath, filepath)
|
||||
|
||||
with open(filepath, "wb") as f:
|
||||
f.write(filepath.encode("utf-8"))
|
||||
|
||||
vcfg = [
|
||||
".::r,u1:r.,u2",
|
||||
"a:a:r,u1:r,u2",
|
||||
".b:.b:r.,u1:r,u2"
|
||||
]
|
||||
self.args = Cfg(v=vcfg, a=["u1:u1", "u2:u2"], e2dsa=True)
|
||||
self.asrv = AuthSrv(self.args, self.log)
|
||||
|
||||
self.assertEqual(self.tardir("", "u1"), "f0 t/f1 a/f3 a/da/f4")
|
||||
self.assertEqual(self.tardir(".t", "u1"), "f2")
|
||||
self.assertEqual(self.tardir(".b", "u1"), ".f6 f6 .db/.f8 .db/f8 db/.f7 db/f7")
|
||||
|
||||
zs = ".f0 f0 .t/.f2 .t/f2 t/.f1 t/f1 .b/f6 .b/db/f7 a/f3 a/da/f4"
|
||||
self.assertEqual(self.tardir("", "u2"), zs)
|
||||
|
||||
self.assertEqual(self.curl("?tar", "x")[1][:17], "\nJ2EOT")
|
||||
|
||||
# search
|
||||
up2k = Up2k(self)
|
||||
u2idx = U2idx(self)
|
||||
allvols = list(self.asrv.vfs.all_vols.values())
|
||||
|
||||
x = u2idx.search("u1", allvols, "", 999)
|
||||
x = " ".join(sorted([x["rp"] for x in x[0]]))
|
||||
# u1 can see dotfiles in volB so they should be included
|
||||
xe = ".b/.db/.f8 .b/.db/f8 .b/.f6 .b/db/.f7 .b/db/f7 .b/f6 a/da/f4 a/f3 f0 t/f1"
|
||||
self.assertEqual(x, xe)
|
||||
|
||||
x = u2idx.search("u2", allvols, "", 999)
|
||||
x = " ".join(sorted([x["rp"] for x in x[0]]))
|
||||
self.assertEqual(x, ".f0 .t/.f2 .t/f2 a/da/f4 a/f3 f0 t/.f1 t/f1")
|
||||
|
||||
self.args = Cfg(v=vcfg, a=["u1:u1", "u2:u2"], dotsrch=False)
|
||||
self.asrv = AuthSrv(self.args, self.log)
|
||||
u2idx = U2idx(self)
|
||||
|
||||
x = u2idx.search("u1", self.asrv.vfs.all_vols.values(), "", 999)
|
||||
x = " ".join(sorted([x["rp"] for x in x[0]]))
|
||||
# u1 can see dotfiles in volB so they should be included
|
||||
xe = "a/da/f4 a/f3 f0 t/f1"
|
||||
self.assertEqual(x, xe)
|
||||
|
||||
def tardir(self, url, uname):
|
||||
h, b = self.curl("/" + url + "?tar", uname, True)
|
||||
tar = tarfile.open(fileobj=io.BytesIO(b), mode="r|").getnames()
|
||||
top = ("top" if not url else url.lstrip(".").split("/")[0]) + "/"
|
||||
assert len(tar) == len([x for x in tar if x.startswith(top)])
|
||||
return " ".join([x[len(top):] for x in tar])
|
||||
|
||||
def curl(self, url, uname, binary=False):
|
||||
conn = tu.VHttpConn(self.args, self.asrv, self.log, hdr(url, uname))
|
||||
HttpCli(conn).run()
|
||||
if binary:
|
||||
h, b = conn.s._reply.split(b"\r\n\r\n", 1)
|
||||
return [h.decode("utf-8"), b]
|
||||
|
||||
return conn.s._reply.decode("utf-8").split("\r\n\r\n", 1)
|
||||
|
||||
def log(self, src, msg, c=0):
|
||||
print(msg)
|
||||
@@ -7,7 +7,6 @@ import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
from textwrap import dedent
|
||||
|
||||
from copyparty import util
|
||||
from copyparty.authsrv import VFS, AuthSrv
|
||||
@@ -175,11 +174,11 @@ class TestVFS(unittest.TestCase):
|
||||
self.assertEqual(len(vfs.nodes), 1)
|
||||
self.assertEqual(n.vpath, "a")
|
||||
self.assertEqual(n.realpath, os.path.join(td, "a"))
|
||||
self.assertAxs(n.axs.uread, ["*"])
|
||||
self.assertAxs(n.axs.uread, ["*", "k"])
|
||||
self.assertAxs(n.axs.uwrite, [])
|
||||
perm_na = (False, False, False, False, False, False, False)
|
||||
perm_rw = (True, True, False, False, False, False, False)
|
||||
perm_ro = (True, False, False, False, False, False, False)
|
||||
perm_na = (False, False, False, False, False, False, False, False)
|
||||
perm_rw = (True, True, False, False, False, False, False, False)
|
||||
perm_ro = (True, False, False, False, False, False, False, False)
|
||||
self.assertEqual(vfs.can_access("/", "*"), perm_na)
|
||||
self.assertEqual(vfs.can_access("/", "k"), perm_rw)
|
||||
self.assertEqual(vfs.can_access("/a", "*"), perm_ro)
|
||||
@@ -232,7 +231,7 @@ class TestVFS(unittest.TestCase):
|
||||
cfg_path = os.path.join(self.td, "test.cfg")
|
||||
with open(cfg_path, "wb") as f:
|
||||
f.write(
|
||||
dedent(
|
||||
util.dedent(
|
||||
"""
|
||||
u a:123
|
||||
u asd:fgh:jkl
|
||||
|
||||
@@ -44,6 +44,7 @@ if MACOS:
|
||||
from copyparty.__init__ import E
|
||||
from copyparty.__main__ import init_E
|
||||
from copyparty.util import FHC, Garda, Unrecv
|
||||
from copyparty.u2idx import U2idx
|
||||
|
||||
init_E(E)
|
||||
|
||||
@@ -106,51 +107,59 @@ def get_ramdisk():
|
||||
|
||||
|
||||
class Cfg(Namespace):
|
||||
def __init__(self, a=None, v=None, c=None):
|
||||
def __init__(self, a=None, v=None, c=None, **ka0):
|
||||
ka = {}
|
||||
|
||||
ex = "daw dav_auth dav_inf dav_mac dav_rt dotsrch e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp ed emp exp force_js getmod grid hardlink ih ihead magic never_symlink nid nih no_acode no_athumb no_dav no_dedup no_del no_dupe no_logues no_mv no_readme no_robots no_sb_md no_sb_lg no_scandir no_tarcmp no_thumb no_vthumb no_zip nrand nw rand smb th_no_crop vague_403 vc ver xdev xlink xvol"
|
||||
ex = "daw dav_auth dav_inf dav_mac dav_rt e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp ed emp exp force_js getmod grid hardlink ih ihead magic never_symlink nid nih no_acode no_athumb no_dav no_dedup no_del no_dupe no_lifetime no_logues no_mv no_readme no_robots no_sb_md no_sb_lg no_scandir no_tarcmp no_thumb no_vthumb no_zip nrand nw rand smb srch_dbg stats th_no_crop vague_403 vc ver xdev xlink xvol"
|
||||
ka.update(**{k: False for k in ex.split()})
|
||||
|
||||
ex = "dotpart no_rescan no_sendfile no_voldump plain_ip"
|
||||
ex = "dotpart dotsrch no_dhash no_fastboot no_rescan no_sendfile no_voldump re_dhash plain_ip"
|
||||
ka.update(**{k: True for k in ex.split()})
|
||||
|
||||
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()})
|
||||
|
||||
ex = "s_thead s_tbody th_convt"
|
||||
ex = "hash_mt srch_time"
|
||||
ka.update(**{k: 1 for k in ex.split()})
|
||||
|
||||
ex = "reg_cap s_thead s_tbody th_convt"
|
||||
ka.update(**{k: 9 for k in ex.split()})
|
||||
|
||||
ex = "df loris re_maxage rproxy rsp_jtr rsp_slp s_wr_slp theme themes turbo"
|
||||
ex = "db_act df loris re_maxage rproxy rsp_jtr rsp_slp s_wr_slp snap_wri theme themes turbo"
|
||||
ka.update(**{k: 0 for k in ex.split()})
|
||||
|
||||
ex = "ah_alg bname doctitle favico hdr_au_usr html_head lg_sbf log_fk md_sbf name textfiles unlist vname R RS SR"
|
||||
ex = "ah_alg bname doctitle exit 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()})
|
||||
|
||||
ex = "on403 on404 xad xar xau xban xbd xbr xbu xiu xm"
|
||||
ka.update(**{k: [] for k in ex.split()})
|
||||
|
||||
ex = "exp_lg exp_md"
|
||||
ex = "exp_lg exp_md th_coversd"
|
||||
ka.update(**{k: {} for k in ex.split()})
|
||||
|
||||
ka.update(ka0)
|
||||
|
||||
super(Cfg, self).__init__(
|
||||
a=a or [],
|
||||
v=v or [],
|
||||
c=c,
|
||||
E=E,
|
||||
dbd="wal",
|
||||
s_wr_sz=512 * 1024,
|
||||
th_size="320x256",
|
||||
fk_salt="a" * 16,
|
||||
unpost=600,
|
||||
u2sort="s",
|
||||
u2ts="c",
|
||||
sort="href",
|
||||
mtp=[],
|
||||
lang="eng",
|
||||
log_badpwd=1,
|
||||
logout=573,
|
||||
mte={"a": True},
|
||||
mth={},
|
||||
lang="eng",
|
||||
logout=573,
|
||||
mtp=[],
|
||||
s_wr_sz=512 * 1024,
|
||||
sort="href",
|
||||
srch_hits=99999,
|
||||
th_size="320x256",
|
||||
u2sort="s",
|
||||
u2ts="c",
|
||||
unpost=600,
|
||||
warksalt="hunter2",
|
||||
**ka
|
||||
)
|
||||
|
||||
@@ -186,11 +195,16 @@ class VSock(object):
|
||||
|
||||
|
||||
class VHttpSrv(object):
|
||||
def __init__(self):
|
||||
def __init__(self, args, asrv, log):
|
||||
self.args = args
|
||||
self.asrv = asrv
|
||||
self.log = log
|
||||
|
||||
self.broker = NullBroker()
|
||||
self.prism = None
|
||||
self.bans = {}
|
||||
self.nreq = 0
|
||||
self.nsus = 0
|
||||
|
||||
aliases = ["splash", "browser", "browser2", "msg", "md", "mde"]
|
||||
self.j2 = {x: J2_FILES for x in aliases}
|
||||
@@ -200,31 +214,38 @@ class VHttpSrv(object):
|
||||
self.g403 = Garda("")
|
||||
self.gurl = Garda("")
|
||||
|
||||
self.u2idx = None
|
||||
self.ptn_cc = re.compile(r"[\x00-\x1f]")
|
||||
|
||||
def cachebuster(self):
|
||||
return "a"
|
||||
|
||||
def get_u2idx(self):
|
||||
self.u2idx = self.u2idx or U2idx(self)
|
||||
return self.u2idx
|
||||
|
||||
|
||||
class VHttpConn(object):
|
||||
def __init__(self, args, asrv, log, buf):
|
||||
self.t0 = time.time()
|
||||
self.s = VSock(buf)
|
||||
self.sr = Unrecv(self.s, None) # type: ignore
|
||||
self.aclose = {}
|
||||
self.addr = ("127.0.0.1", "42069")
|
||||
self.args = args
|
||||
self.asrv = asrv
|
||||
self.nid = None
|
||||
self.bans = {}
|
||||
self.freshen_pwd = 0.0
|
||||
self.hsrv = VHttpSrv(args, asrv, log)
|
||||
self.ico = None
|
||||
self.lf_url = None
|
||||
self.log_func = log
|
||||
self.log_src = "a"
|
||||
self.lf_url = None
|
||||
self.hsrv = VHttpSrv()
|
||||
self.bans = {}
|
||||
self.aclose = {}
|
||||
self.u2fh = FHC()
|
||||
self.mutex = threading.Lock()
|
||||
self.nreq = -1
|
||||
self.nbyte = 0
|
||||
self.ico = None
|
||||
self.nid = None
|
||||
self.nreq = -1
|
||||
self.thumbcli = None
|
||||
self.freshen_pwd = 0.0
|
||||
self.t0 = time.time()
|
||||
self.u2fh = FHC()
|
||||
|
||||
self.get_u2idx = self.hsrv.get_u2idx
|
||||
Reference in New Issue
Block a user