From: Brian Warner Date: Thu, 7 Dec 2006 21:48:37 +0000 (-0700) Subject: webish: improve download, now you can just append the vdrive path to the base URL... X-Git-Tag: tahoe_v0.1.0-0-UNSTABLE~440 X-Git-Url: https://git.rkrishnan.org/?a=commitdiff_plain;h=4b11831da7a64fa9011cd2f59f4a73664623838d;p=tahoe-lafs%2Ftahoe-lafs.git 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 --- diff --git a/allmydata/test/test_system.py b/allmydata/test/test_system.py index 85e25a3c..165e42d8 100644 --- a/allmydata/test/test_system.py +++ b/allmydata/test/test_system.py @@ -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" in page) + self.failUnless(">mydata567" 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 diff --git a/allmydata/web/directory.xhtml b/allmydata/web/directory.xhtml index 5b4d9c7a..38a09c9c 100644 --- a/allmydata/web/directory.xhtml +++ b/allmydata/web/directory.xhtml @@ -1,8 +1,9 @@ - + + diff --git a/allmydata/web/welcome.xhtml b/allmydata/web/welcome.xhtml index 8ceb6c6f..7adb96ae 100644 --- a/allmydata/web/welcome.xhtml +++ b/allmydata/web/welcome.xhtml @@ -1,15 +1,16 @@ Welcome To AllMyData (tahoe2) - + +

Welcome To AllMyData! (tahoe2)

-

To view the global shared filestore, Click Here!

+

To view the global shared filestore, Click Here!

Mesh Status

@@ -32,6 +33,7 @@ +
diff --git a/allmydata/webish.py b/allmydata/webish.py index 7dcb332e..8823a241 100644 --- a/allmydata/webish.py +++ b/allmydata/webish.py @@ -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)