mirror of
https://github.com/9001/copyparty.git
synced 2026-01-12 15:52:39 -07:00
sftp: fix nested write-only folders (could not browse)
This commit is contained in:
parent
8c9e1016de
commit
6c41bac6d2
|
|
@ -292,6 +292,20 @@ class SFTP_Srv(paramiko.SFTPServerInterface):
|
||||||
if self.uname == LEELOO_DALLAS:
|
if self.uname == LEELOO_DALLAS:
|
||||||
raise Exception("send her back")
|
raise Exception("send her back")
|
||||||
|
|
||||||
|
self.vols = [
|
||||||
|
vp
|
||||||
|
for vp, vn in self.asrv.vfs.all_vols.items()
|
||||||
|
if self.uname in vn.axs.uread
|
||||||
|
or self.uname in vn.axs.uwrite
|
||||||
|
or self.uname in vn.axs.uget
|
||||||
|
]
|
||||||
|
self.vis = set()
|
||||||
|
for zs in self.vols:
|
||||||
|
self.vis.add(zs)
|
||||||
|
while zs:
|
||||||
|
zs = zs.rsplit("/", 1)[0] if "/" in zs else ""
|
||||||
|
self.vis.add(zs)
|
||||||
|
|
||||||
def log(self, msg: str, c: Union[int, str] = 0) -> None:
|
def log(self, msg: str, c: Union[int, str] = 0) -> None:
|
||||||
self.hub.log("sftp:%s" % (self.ip,), msg, c)
|
self.hub.log("sftp:%s" % (self.ip,), msg, c)
|
||||||
|
|
||||||
|
|
@ -357,6 +371,7 @@ class SFTP_Srv(paramiko.SFTPServerInterface):
|
||||||
def _list_folder(self, path: str) -> list[SATTR] | int:
|
def _list_folder(self, path: str) -> list[SATTR] | int:
|
||||||
if self.v:
|
if self.v:
|
||||||
self.log("ls(%s):" % (path,))
|
self.log("ls(%s):" % (path,))
|
||||||
|
path = path.strip("/")
|
||||||
try:
|
try:
|
||||||
ap, vn, rem = self.v2a(path, r=True)
|
ap, vn, rem = self.v2a(path, r=True)
|
||||||
except Pebkac:
|
except Pebkac:
|
||||||
|
|
@ -366,23 +381,23 @@ class SFTP_Srv(paramiko.SFTPServerInterface):
|
||||||
return [] # display write-only folders as empty
|
return [] # display write-only folders as empty
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if self.asrv.vfs.realpath or path.strip("/"):
|
if path not in self.vis:
|
||||||
self.log("ls(%s): EPERM" % (path,))
|
self.log("ls(%s): EPERM" % (path,))
|
||||||
return SFTP_PERMISSION_DENIED
|
return SFTP_PERMISSION_DENIED
|
||||||
# list of accessible volumes
|
# list of accessible volumes
|
||||||
ret = []
|
ret = []
|
||||||
zi = int(time.time())
|
zi = int(time.time())
|
||||||
vst = os.stat_result((16877, -1, -1, 1, 1000, 1000, 8, zi, zi, zi))
|
vst = os.stat_result((16877, -1, -1, 1, 1000, 1000, 8, zi, zi, zi))
|
||||||
for vn in self.asrv.vfs.all_vols.values():
|
prefix = path + "/"
|
||||||
if "/" in vn.vpath or not vn.vpath:
|
for vn in self.asrv.vfs.all_nodes.values():
|
||||||
continue # only include toplevel-mounted vols
|
if path and not vn.vpath.startswith(prefix):
|
||||||
try:
|
continue # vn is parent
|
||||||
self.hub.asrv.vfs.get(vn.vpath, self.uname, True, False)
|
vname = vn.vpath[len(prefix) :]
|
||||||
|
if "/" in vname or not vname:
|
||||||
|
continue # only include vols at current level
|
||||||
ret.append(SATTR.from_stat(vst, filename=vn.vpath))
|
ret.append(SATTR.from_stat(vst, filename=vn.vpath))
|
||||||
except:
|
|
||||||
pass
|
|
||||||
ret.sort(key=lambda x: x.filename)
|
ret.sort(key=lambda x: x.filename)
|
||||||
self.log("ls(%s): vfs-root; |%d|" % (path, len(ret)))
|
self.log("ls(%s): vfs-vols; |%d|" % (path, len(ret)))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
_, vfs_ls, vfs_virt = vn.ls(
|
_, vfs_ls, vfs_virt = vn.ls(
|
||||||
|
|
@ -419,6 +434,7 @@ class SFTP_Srv(paramiko.SFTPServerInterface):
|
||||||
return SFTP_FAILURE
|
return SFTP_FAILURE
|
||||||
|
|
||||||
def _stat(self, vp: str) -> SATTR | int:
|
def _stat(self, vp: str) -> SATTR | int:
|
||||||
|
vp = vp.strip("/")
|
||||||
try:
|
try:
|
||||||
ap, vn, _ = self.v2a(vp)
|
ap, vn, _ = self.v2a(vp)
|
||||||
if (
|
if (
|
||||||
|
|
@ -431,12 +447,12 @@ class SFTP_Srv(paramiko.SFTPServerInterface):
|
||||||
st = bos.stat(ap)
|
st = bos.stat(ap)
|
||||||
self.log("stat(%s): %s" % (vp, st))
|
self.log("stat(%s): %s" % (vp, st))
|
||||||
except:
|
except:
|
||||||
if vp.strip("/") or self.asrv.vfs.realpath:
|
if vp not in self.vis:
|
||||||
self.log("stat(%s): ENOENT" % (vp,))
|
self.log("stat(%s): ENOENT" % (vp,))
|
||||||
return SFTP_NO_SUCH_FILE
|
return SFTP_NO_SUCH_FILE
|
||||||
zi = int(time.time())
|
zi = int(time.time())
|
||||||
st = os.stat_result((16877, -1, -1, 1, 1000, 1000, 8, zi, zi, zi))
|
st = os.stat_result((16877, -1, -1, 1, 1000, 1000, 8, zi, zi, zi))
|
||||||
self.log("stat(%s): vfs-root")
|
self.log("stat(%s): vfs-vols")
|
||||||
return SATTR.from_stat(st)
|
return SATTR.from_stat(st)
|
||||||
|
|
||||||
def open(self, path: str, flags: int, attr: SATTR) -> paramiko.SFTPHandle | int:
|
def open(self, path: str, flags: int, attr: SATTR) -> paramiko.SFTPHandle | int:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue