mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-01-30 08:04:08 +00:00
webish: improve download, now you can just append the vdrive path to the base URL to get at the contents of the file. Also added a download-by-URI box
This commit is contained in:
parent
13d6566c13
commit
4b11831da7
@ -103,13 +103,13 @@ class SystemTest(unittest.TestCase):
|
||||
v0 = self.clients[0].getServiceNamed("vdrive")
|
||||
d1 = v0.make_directory("/", "subdir1")
|
||||
d1.addCallback(lambda subdir1:
|
||||
v0.put_file_by_data(subdir1, "data", DATA))
|
||||
v0.put_file_by_data(subdir1, "mydata567", DATA))
|
||||
return d1
|
||||
d.addCallback(_do_publish)
|
||||
def _publish_done(res):
|
||||
log.msg("publish finished")
|
||||
v1 = self.clients[1].getServiceNamed("vdrive")
|
||||
d1 = v1.get_file_to_data("/subdir1/data")
|
||||
d1 = v1.get_file_to_data("/subdir1/mydata567")
|
||||
return d1
|
||||
d.addCallback(_publish_done)
|
||||
def _get_done(data):
|
||||
@ -133,12 +133,11 @@ class SystemTest(unittest.TestCase):
|
||||
d.addCallback(lambda res: getPage(base + "vdrive/subdir1"))
|
||||
def _got_subdir1(page):
|
||||
# there ought to be an href for our file
|
||||
self.failUnless(">data</a>" in page)
|
||||
self.failUnless(">mydata567</a>" in page)
|
||||
d.addCallback(_got_subdir1)
|
||||
if False: # not implemented yet
|
||||
d.addCallback(lambda res: getPage(base + "vdrive/subdir/data"))
|
||||
def _got_data(page):
|
||||
self.failUnlessEqual(page, self.data)
|
||||
d.addCallback(_got_data)
|
||||
d.addCallback(lambda res: getPage(base + "vdrive/subdir1/mydata567"))
|
||||
def _got_data(page):
|
||||
self.failUnlessEqual(page, self.data)
|
||||
d.addCallback(_got_data)
|
||||
return d
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
<html xmlns:n="http://nevow.com/ns/nevow/0.1">
|
||||
<head>
|
||||
<title n:render="title"></title>
|
||||
<link href="http://www.allmydata.com/common/css/styles.css"
|
||||
rel="stylesheet" type="text/css"/>
|
||||
<!-- <link href="http://www.allmydata.com/common/css/styles.css"
|
||||
rel="stylesheet" type="text/css"/> -->
|
||||
<link href="/webform_css" rel="stylesheet" type="text/css"/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
|
@ -1,15 +1,16 @@
|
||||
<html xmlns:n="http://nevow.com/ns/nevow/0.1">
|
||||
<head>
|
||||
<title>Welcome To AllMyData (tahoe2)</title>
|
||||
<link href="http://www.allmydata.com/common/css/styles.css"
|
||||
rel="stylesheet" type="text/css"/>
|
||||
<!-- <link href="http://www.allmydata.com/common/css/styles.css"
|
||||
rel="stylesheet" type="text/css"/> -->
|
||||
<link href="/webform_css" rel="stylesheet" type="text/css"/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Welcome To AllMyData! (tahoe2)</h1>
|
||||
|
||||
<p>To view the global shared filestore, <a href="vdrive">Click Here!</a></p>
|
||||
<p>To view the global shared filestore, <a href="../vdrive">Click Here!</a></p>
|
||||
|
||||
<h2>Mesh Status</h2>
|
||||
|
||||
@ -32,6 +33,7 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div n:render="forms"/>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
from twisted.application import service, strports
|
||||
from twisted.web import static, resource, server
|
||||
from twisted.web import static, resource, server, html
|
||||
from twisted.python import util, log
|
||||
from nevow import inevow, rend, loaders, appserver, url, tags as T
|
||||
from allmydata.util import idlib
|
||||
@ -16,38 +16,12 @@ def getxmlfile(name):
|
||||
class IClient(Interface):
|
||||
pass
|
||||
|
||||
class WebishServer(service.MultiService):
|
||||
name = "webish"
|
||||
|
||||
def __init__(self, webport):
|
||||
service.MultiService.__init__(self)
|
||||
self.root = root = static.Data("root", "text/plain")
|
||||
w = Welcome()
|
||||
root.putChild("", w)
|
||||
root.putChild("vdrive",
|
||||
static.Data("sorry, still initializing", "text/plain"))
|
||||
self.site = site = appserver.NevowSite(root)
|
||||
s = strports.service(webport, site)
|
||||
s.setServiceParent(self)
|
||||
self.listener = s # stash it so the tests can query for the portnum
|
||||
|
||||
def startService(self):
|
||||
service.MultiService.startService(self)
|
||||
# to make various services available to render_* methods, we stash a
|
||||
# reference to the client on the NevowSite. This will be available by
|
||||
# adapting the 'context' argument to a special marker interface named
|
||||
# IClient.
|
||||
self.site.remember(self.parent, IClient)
|
||||
# I thought you could do the same with an existing interface, but
|
||||
# apparently 'ISite' does not exist
|
||||
#self.site._client = self.parent
|
||||
|
||||
def set_root_dirnode(self, dirnode):
|
||||
self.root.putChild("vdrive", Directory(dirnode, "/"))
|
||||
# I tried doing it this way and for some reason it didn't seem to work
|
||||
#print "REMEMBERING", self.site, dl, IDownloader
|
||||
#self.site.remember(dl, IDownloader)
|
||||
|
||||
def get_downloader_service(ctx):
|
||||
return IClient(ctx).getServiceNamed("downloader")
|
||||
def get_uploader_service(ctx):
|
||||
return IClient(ctx).getServiceNamed("uploader")
|
||||
def get_vdrive_service(ctx):
|
||||
return IClient(ctx).getServiceNamed("vdrive")
|
||||
|
||||
class Welcome(rend.Page):
|
||||
addSlash = True
|
||||
@ -76,6 +50,31 @@ class Welcome(rend.Page):
|
||||
ctx.fillSlots("connected", connected)
|
||||
return ctx.tag
|
||||
|
||||
# this is a form where users can download files by URI
|
||||
|
||||
def bind_download(self, ctx):
|
||||
uriarg = annotate.Argument("uri",
|
||||
annotate.String("URI of file to download: "))
|
||||
namearg = annotate.Argument("filename",
|
||||
annotate.String("Filename to download as: "))
|
||||
ctxarg = annotate.Argument("ctx", annotate.Context())
|
||||
meth = annotate.Method(arguments=[uriarg, namearg, ctxarg],
|
||||
label="Download File by URI")
|
||||
# buttons always use value=data.label
|
||||
# MethodBindingRenderer uses value=(data.action or data.label)
|
||||
return annotate.MethodBinding("download", meth, action="Download")
|
||||
|
||||
def download(self, uri, filename, ctx):
|
||||
log.msg("webish downloading URI")
|
||||
target = url.here.sibling("download_uri").add("uri", uri)
|
||||
if filename:
|
||||
target = target.add("filename", filename)
|
||||
return target
|
||||
|
||||
def render_forms(self, ctx, data):
|
||||
return webform.renderForms()
|
||||
|
||||
|
||||
class Directory(rend.Page):
|
||||
addSlash = True
|
||||
docFactory = getxmlfile("directory.xhtml")
|
||||
@ -84,24 +83,20 @@ class Directory(rend.Page):
|
||||
self._dirnode = dirnode
|
||||
self._dirname = dirname
|
||||
|
||||
def get_service(self, ctx, name):
|
||||
return IClient(ctx).getServiceNamed(name)
|
||||
|
||||
def childFactory(self, ctx, name):
|
||||
if name.startswith("freeform"): # ick
|
||||
return None
|
||||
if name == "_download":
|
||||
args = inevow.IRequest(ctx).args
|
||||
filename = args["filename"][0]
|
||||
verifierid = args["verifierid"][0]
|
||||
return Downloader(self.get_service(ctx, "downloader"),
|
||||
self._dirname, filename, idlib.a2b(verifierid))
|
||||
if self._dirname == "/":
|
||||
dirname = "/" + name
|
||||
else:
|
||||
dirname = self._dirname + "/" + name
|
||||
d = self._dirnode.callRemote("get", name)
|
||||
d.addCallback(lambda newnode: Directory(newnode, dirname))
|
||||
def _got_child(res):
|
||||
if isinstance(res, str):
|
||||
dl = get_downloader_service(ctx)
|
||||
return Downloader(dl, name, res)
|
||||
return Directory(res, dirname)
|
||||
d.addCallback(_got_child)
|
||||
return d
|
||||
|
||||
def render_title(self, ctx, data):
|
||||
@ -118,13 +113,15 @@ class Directory(rend.Page):
|
||||
name, target = data
|
||||
if isinstance(target, str):
|
||||
# file
|
||||
args = {'verifierid': idlib.b2a(target),
|
||||
'filename': name,
|
||||
}
|
||||
dlurl = "_download?%s" % urllib.urlencode(args)
|
||||
ctx.fillSlots("filename", T.a(href=dlurl)[name])
|
||||
dlurl = urllib.quote(name)
|
||||
ctx.fillSlots("filename",
|
||||
T.a(href=dlurl)[html.escape(name)])
|
||||
ctx.fillSlots("type", "FILE")
|
||||
ctx.fillSlots("fileid", idlib.b2a(target))
|
||||
uri = idlib.b2a(target)
|
||||
dl_uri_url = url.root.child("download_uri").child(uri)
|
||||
# add a filename= query argument to give it a Content-Type
|
||||
dl_uri_url = dl_uri_url.add("filename", name)
|
||||
ctx.fillSlots("fileid", T.a(href=dl_uri_url)[html.escape(uri)])
|
||||
|
||||
# this creates a button which will cause our child__delete method
|
||||
# to be invoked, which deletes the file and then redirects the
|
||||
@ -138,13 +135,14 @@ class Directory(rend.Page):
|
||||
ctx.fillSlots("delete", delete)
|
||||
else:
|
||||
# directory
|
||||
ctx.fillSlots("filename", T.a(href=name)[name])
|
||||
subdir_url = urllib.quote(name)
|
||||
ctx.fillSlots("filename",
|
||||
T.a(href=subdir_url)[html.escape(name)])
|
||||
ctx.fillSlots("type", "DIR")
|
||||
ctx.fillSlots("fileid", "-")
|
||||
ctx.fillSlots("delete", "-")
|
||||
return ctx.tag
|
||||
|
||||
child_webform_css = webform.defaultCSS
|
||||
def render_forms(self, ctx, data):
|
||||
return webform.renderForms()
|
||||
|
||||
@ -167,14 +165,15 @@ class Directory(rend.Page):
|
||||
contentsarg = annotate.Argument("contents", up)
|
||||
|
||||
ctxarg = annotate.Argument("ctx", annotate.Context())
|
||||
meth = annotate.Method(arguments=[contentsarg, ctxarg])
|
||||
return annotate.MethodBinding("upload", meth, action="Upload File")
|
||||
meth = annotate.Method(arguments=[contentsarg, ctxarg],
|
||||
label="Upload File to this directory")
|
||||
return annotate.MethodBinding("upload", meth, action="Upload")
|
||||
|
||||
def upload(self, contents, ctx):
|
||||
# contents is a cgi.FieldStorage instance
|
||||
log.msg("starting webish upload")
|
||||
|
||||
uploader = self.get_service(ctx, "uploader")
|
||||
uploader = get_uploader_service(ctx)
|
||||
d = uploader.upload(upload.Data(contents.value))
|
||||
name = contents.filename
|
||||
d.addCallback(lambda vid:
|
||||
@ -191,8 +190,8 @@ class Directory(rend.Page):
|
||||
"""Make new directory 1"""
|
||||
namearg = annotate.Argument("name",
|
||||
annotate.String("New directory name: "))
|
||||
meth = annotate.Method(arguments=[namearg])
|
||||
return annotate.MethodBinding("mkdir", meth, action="Make Directory")
|
||||
meth = annotate.Method(arguments=[namearg], label="Make New Subdirectory")
|
||||
return annotate.MethodBinding("mkdir", meth, action="Create Directory")
|
||||
|
||||
def mkdir(self, name):
|
||||
"""mkdir2"""
|
||||
@ -207,7 +206,7 @@ class Directory(rend.Page):
|
||||
def child__delete(self, ctx):
|
||||
# perform the delete, then redirect back to the directory page
|
||||
args = inevow.IRequest(ctx).args
|
||||
vdrive = self.get_service(ctx, "vdrive")
|
||||
vdrive = get_vdrive_service(ctx)
|
||||
d = vdrive.remove(self._dirnode, args["name"][0])
|
||||
def _deleted(res):
|
||||
return url.here.up()
|
||||
@ -244,9 +243,8 @@ class TypedFile(static.File):
|
||||
self.defaultType)
|
||||
|
||||
class Downloader(resource.Resource):
|
||||
def __init__(self, downloader, dirname, name, verifierid):
|
||||
def __init__(self, downloader, name, verifierid):
|
||||
self._downloader = downloader
|
||||
self._dirname = dirname
|
||||
self._name = name
|
||||
self._verifierid = verifierid
|
||||
|
||||
@ -268,3 +266,60 @@ class Downloader(resource.Resource):
|
||||
return server.NOT_DONE_YET
|
||||
|
||||
|
||||
|
||||
class Root(rend.Page):
|
||||
def locateChild(self, ctx, segments):
|
||||
if segments[0] == "download_uri":
|
||||
req = inevow.IRequest(ctx)
|
||||
dl = get_downloader_service(ctx)
|
||||
filename = "unknown_filename"
|
||||
if "filename" in req.args:
|
||||
filename = req.args["filename"][0]
|
||||
if len(segments) > 1:
|
||||
# http://host/download_uri/URIGOESHERE
|
||||
uri_a = segments[1]
|
||||
elif "uri" in req.args:
|
||||
# http://host/download_uri?uri=URIGOESHERE
|
||||
uri_a = req.args["uri"][0]
|
||||
else:
|
||||
return rend.NotFound
|
||||
child = Downloader(dl, filename, idlib.a2b(uri_a))
|
||||
return child, ()
|
||||
return rend.Page.locateChild(self, ctx, segments)
|
||||
|
||||
child_webform_css = webform.defaultCSS
|
||||
|
||||
child_welcome = Welcome()
|
||||
|
||||
|
||||
class WebishServer(service.MultiService):
|
||||
name = "webish"
|
||||
|
||||
def __init__(self, webport):
|
||||
service.MultiService.__init__(self)
|
||||
self.root = Root()
|
||||
placeholder = static.Data("sorry, still initializing", "text/plain")
|
||||
self.root.putChild("vdrive", placeholder)
|
||||
self.root.putChild("", url.here.child("welcome"))#Welcome())
|
||||
|
||||
self.site = site = appserver.NevowSite(self.root)
|
||||
s = strports.service(webport, site)
|
||||
s.setServiceParent(self)
|
||||
self.listener = s # stash it so the tests can query for the portnum
|
||||
|
||||
def startService(self):
|
||||
service.MultiService.startService(self)
|
||||
# to make various services available to render_* methods, we stash a
|
||||
# reference to the client on the NevowSite. This will be available by
|
||||
# adapting the 'context' argument to a special marker interface named
|
||||
# IClient.
|
||||
self.site.remember(self.parent, IClient)
|
||||
# I thought you could do the same with an existing interface, but
|
||||
# apparently 'ISite' does not exist
|
||||
#self.site._client = self.parent
|
||||
|
||||
def set_root_dirnode(self, dirnode):
|
||||
self.root.putChild("vdrive", Directory(dirnode, "/"))
|
||||
# I tried doing it this way and for some reason it didn't seem to work
|
||||
#print "REMEMBERING", self.site, dl, IDownloader
|
||||
#self.site.remember(dl, IDownloader)
|
||||
|
Loading…
x
Reference in New Issue
Block a user