browser getting close

This commit is contained in:
ed 2019-06-07 18:42:15 +00:00
parent 7aba7737d5
commit 2414766678
5 changed files with 115 additions and 46 deletions

View file

@ -41,6 +41,9 @@
], ],
"python.formatting.provider": "black", "python.formatting.provider": "black",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"[html]": {
"editor.formatOnSave": false,
}
// //
// things you may wanna edit: // things you may wanna edit:
// //

View file

@ -67,12 +67,17 @@ class VFS(object):
return [self, vpath] return [self, vpath]
def can_access(self, vpath, user):
"""return [readable,writable]"""
vn, _ = self._find(vpath)
return [user in vn.uread, user in vn.uwrite]
def ls(self, vpath, user): def ls(self, vpath, user):
"""return user-readable [virt,real] items at vpath""" """return user-readable [fsdir,real,virt] items at vpath"""
vn, rem = self._find(vpath) vn, rem = self._find(vpath)
if user not in vn.uread: if user not in vn.uread:
return [[], []] return [vn.realpath, [], []]
rp = vn.realpath rp = vn.realpath
if rem: if rem:
@ -96,11 +101,7 @@ class VFS(object):
except ValueError: except ValueError:
pass pass
absreal = [] return [rp, real, virt_vis]
for p in real:
absreal.append("{}/{}".format(rp, p).replace("//", "/"))
return [absreal, virt_vis]
def user_tree(self, uname, readable=False, writable=False): def user_tree(self, uname, readable=False, writable=False):
ret = [] ret = []

View file

@ -3,14 +3,20 @@
from __future__ import print_function from __future__ import print_function
import os import os
import stat
import time import time
from datetime import datetime
import mimetypes import mimetypes
import cgi
from .__init__ import E, PY2 from .__init__ import E, PY2
from .util import * # noqa # pylint: disable=unused-wildcard-import from .util import * # noqa # pylint: disable=unused-wildcard-import
if not PY2: if not PY2:
unicode = str unicode = str
from urllib.parse import unquote_plus
else:
from urllib import unquote_plus
class HttpCli(object): class HttpCli(object):
@ -30,6 +36,8 @@ class HttpCli(object):
self.ok = True self.ok = True
self.bufsz = 1024 * 32 self.bufsz = 1024 * 32
self.absolute_urls = False
self.out_headers = {}
def log(self, msg): def log(self, msg):
self.log_func(self.log_src, msg) self.log_func(self.log_src, msg)
@ -72,9 +80,15 @@ class HttpCli(object):
# split req into vpath + args # split req into vpath + args
args = {} args = {}
if "?" not in self.req: if "?" not in self.req:
if not self.req.endswith("/"):
self.absolute_urls = True
vpath = undot(self.req) vpath = undot(self.req)
else: else:
vpath, arglist = self.req.split("?", 1) vpath, arglist = self.req.split("?", 1)
if not vpath.endswith("/"):
self.absolute_urls = True
vpath = undot(vpath) vpath = undot(vpath)
for k in arglist.split("&"): for k in arglist.split("&"):
if "=" in k: if "=" in k:
@ -108,6 +122,9 @@ class HttpCli(object):
u"Content-Type: " + mime, u"Content-Type: " + mime,
u"Content-Length: " + str(len(body)), u"Content-Length: " + str(len(body)),
] ]
for k, v in self.out_headers.items():
response.append("{}: {}".format(k, v))
response.extend(headers) response.extend(headers)
response_str = u"\r\n".join(response).encode("utf-8") response_str = u"\r\n".join(response).encode("utf-8")
if self.ok: if self.ok:
@ -140,9 +157,10 @@ class HttpCli(object):
else: else:
self.vpath = self.wvol[0] self.vpath = self.wvol[0]
self.absolute_urls = True
# go home if verboten # go home if verboten
readable = self.vpath in self.rvol readable, writable = self.conn.auth.vfs.can_access(self.vpath, self.uname)
writable = self.vpath in self.wvol
if not readable and not writable: if not readable and not writable:
self.log("inaccessible: {}".format(self.vpath)) self.log("inaccessible: {}".format(self.vpath))
self.args = {"h": True} self.args = {"h": True}
@ -154,7 +172,7 @@ class HttpCli(object):
if readable: if readable:
return self.tx_browser() return self.tx_browser()
else: else:
return self.tx_jupper() return self.tx_upper()
def handle_post(self): def handle_post(self):
self.log("") self.log("")
@ -275,8 +293,48 @@ class HttpCli(object):
html = self.conn.tpl_mounts.render(this=self) html = self.conn.tpl_mounts.render(this=self)
self.reply(html.encode("utf-8")) self.reply(html.encode("utf-8"))
def tx_jupper(self): def tx_upper(self):
# return html for basic uploader;
# js rewrites to up2k unless args['b']
self.loud_reply("TODO jupper {}".format(self.vpath)) self.loud_reply("TODO jupper {}".format(self.vpath))
def tx_browser(self): def tx_browser(self):
self.loud_reply("TODO browser {}".format(self.vpath)) vpath = u""
vpnodes = [[u"/", u"/"]]
for node in self.vpath.split("/"):
vpath += u"/" + node
vpnodes.append([cgi.escape(vpath) + "/", cgi.escape(node)])
fsroot, vfs_ls, vfs_virt = self.auth.vfs.ls(self.vpath, self.uname)
vfs_ls.extend(vfs_virt)
dirs = []
files = []
for fn in vfs_ls:
href = fn
if self.absolute_urls:
href = vpath + "/" + fn
fspath = fsroot + "/" + fn
inf = os.stat(fspath)
is_dir = stat.S_ISDIR(inf.st_mode)
if is_dir:
margin = "DIR"
href += "/"
else:
margin = "-"
sz = inf.st_size
dt = datetime.utcfromtimestamp(inf.st_mtime)
dt = dt.strftime("%Y-%m-%d %H:%M:%S")
item = [margin, cgi.escape(href), cgi.escape(fn), sz, dt]
if is_dir:
dirs.append(item)
else:
files.append(item)
dirs.extend(files)
html = self.conn.tpl_browser.render(vpnodes=vpnodes, files=dirs)
self.reply(html.encode("utf-8"))

View file

@ -12,8 +12,8 @@
<body> <body>
<h1 id="path"> <h1 id="path">
{% for n in vpnodes[:-1] %} {% for n in vpnodes[:-1] %}
<a href="{{ n[0] }}">/{{ n[1] }}</a> <a href="{{ n[0] }}">{{ n[1] }}</a>
{% endfor %} {%- endfor %}
<span>{{ vpnodes[-1][1] }}</li> <span>{{ vpnodes[-1][1] }}</li>
</h1> </h1>
<table id="files"> <table id="files">
@ -26,14 +26,11 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for f in files %} {% for f in files %}
<tr> <tr><td>{{ f[0] }}</td><td><a href="{{ f[1] }}">{{ f[2] }}</a></td><td>{{ f[3] }}</td><td>{{ f[4] }}</td></tr>
<td>{{ f[0] }}</td> {%- endfor %}
<td><a href="{{ f[1] }}">{{ f[2] }}</a></td>
<td>{{ f[3] }}</td>
<td>{{ f[4] }}</td>
</tr>
{% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>

View file

@ -11,6 +11,7 @@ import subprocess as sp # nosec
from textwrap import dedent from textwrap import dedent
from argparse import Namespace from argparse import Namespace
from copyparty.authsrv import AuthSrv from copyparty.authsrv import AuthSrv
from copyparty import util
class TestVFS(unittest.TestCase): class TestVFS(unittest.TestCase):
@ -24,10 +25,10 @@ class TestVFS(unittest.TestCase):
return foo return foo
def undot(self, vfs, query, response): def undot(self, vfs, query, response):
self.assertEqual(vfs.undot(query), response) self.assertEqual(util.undot(query), response)
query = self.unfoo(query) query = self.unfoo(query)
response = self.unfoo(response) response = self.unfoo(response)
self.assertEqual(vfs.undot(query), response) self.assertEqual(util.undot(query), response)
def absify(self, root, names): def absify(self, root, names):
return ["{}/{}".format(root, x).replace("//", "/") for x in names] return ["{}/{}".format(root, x).replace("//", "/") for x in names]
@ -130,34 +131,39 @@ class TestVFS(unittest.TestCase):
self.assertEqual(n.uread, ["k"]) self.assertEqual(n.uread, ["k"])
self.assertEqual(n.uwrite, ["*", "k"]) self.assertEqual(n.uwrite, ["*", "k"])
real, virt = vfs.ls("/", "*") fsdir, real, virt = vfs.ls("/", "*")
self.assertEqual(real, self.absify(td, ["b", "c"])) self.assertEqual(fsdir, td)
self.assertEqual(real, ["b", "c"])
self.assertEqual(virt, ["a"]) self.assertEqual(virt, ["a"])
real, virt = vfs.ls("a", "*") fsdir, real, virt = vfs.ls("a", "*")
self.assertEqual(real, self.absify(td, ["a/aa", "a/ab"])) self.assertEqual(fsdir, td + "/a")
self.assertEqual(real, ["aa", "ab"])
self.assertEqual(virt, ["ac"]) self.assertEqual(virt, ["ac"])
real, virt = vfs.ls("a/ab", "*") fsdir, real, virt = vfs.ls("a/ab", "*")
self.assertEqual(real, self.absify(td, ["a/ab/aba", "a/ab/abb", "a/ab/abc"])) self.assertEqual(fsdir, td + "/a/ab")
self.assertEqual(real, ["aba", "abb", "abc"])
self.assertEqual(virt, []) self.assertEqual(virt, [])
real, virt = vfs.ls("a/ac", "*") fsdir, real, virt = vfs.ls("a/ac", "*")
self.assertEqual(real, self.absify(td, ["a/ac/aca", "a/ac/acc"])) self.assertEqual(fsdir, td + "/a/ac")
self.assertEqual(real, ["aca", "acc"])
self.assertEqual(virt, []) self.assertEqual(virt, [])
real, virt = vfs.ls("a/ac", "k") fsdir, real, virt = vfs.ls("a/ac", "k")
self.assertEqual(real, self.absify(td, ["a/ac/aca", "a/ac/acc"])) self.assertEqual(fsdir, td + "/a/ac")
self.assertEqual(real, ["aca", "acc"])
self.assertEqual(virt, ["acb"]) self.assertEqual(virt, ["acb"])
real, virt = vfs.ls("a/ac/acb", "*") fsdir, real, virt = vfs.ls("a/ac/acb", "*")
self.assertEqual(fsdir, td + "/a/ac/acb")
self.assertEqual(real, []) self.assertEqual(real, [])
self.assertEqual(virt, []) self.assertEqual(virt, [])
real, virt = vfs.ls("a/ac/acb", "k") fsdir, real, virt = vfs.ls("a/ac/acb", "k")
self.assertEqual( self.assertEqual(fsdir, td + "/a/ac/acb")
real, self.absify(td, ["a/ac/acb/acba", "a/ac/acb/acbb", "a/ac/acb/acbc"]) self.assertEqual(real, ["acba", "acbb", "acbc"])
)
self.assertEqual(virt, []) self.assertEqual(virt, [])
# breadth-first construction # breadth-first construction
@ -187,17 +193,21 @@ class TestVFS(unittest.TestCase):
# shadowing # shadowing
vfs = AuthSrv(Namespace(c=None, a=[], v=[".::r", "b:a/ac:r"]), None).vfs vfs = AuthSrv(Namespace(c=None, a=[], v=[".::r", "b:a/ac:r"]), None).vfs
r1, v1 = vfs.ls("", "*") fsp, r1, v1 = vfs.ls("", "*")
self.assertEqual(r1, self.absify(td, ["b", "c"])) self.assertEqual(fsp, td)
self.assertEqual(r1, ["b", "c"])
self.assertEqual(v1, ["a"]) self.assertEqual(v1, ["a"])
r1, v1 = vfs.ls("a", "*") fsp, r1, v1 = vfs.ls("a", "*")
self.assertEqual(r1, self.absify(td, ["a/aa", "a/ab"])) self.assertEqual(fsp, td + "/a")
self.assertEqual(r1, ["aa", "ab"])
self.assertEqual(v1, ["ac"]) self.assertEqual(v1, ["ac"])
r1, v1 = vfs.ls("a/ac", "*") fsp1, r1, v1 = vfs.ls("a/ac", "*")
r2, v2 = vfs.ls("b", "*") fsp2, r2, v2 = vfs.ls("b", "*")
self.assertEqual(r1, self.absify(td, ["b/ba", "b/bb", "b/bc"])) self.assertEqual(fsp1, td + "/b")
self.assertEqual(fsp2, td + "/b")
self.assertEqual(r1, ["ba", "bb", "bc"])
self.assertEqual(r1, r2) self.assertEqual(r1, r2)
self.assertEqual(v1, v2) self.assertEqual(v1, v2)