]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
webish: improve download, now you can just append the vdrive path to the base URL...
authorBrian Warner <warner@allmydata.com>
Thu, 7 Dec 2006 21:48:37 +0000 (14:48 -0700)
committerBrian Warner <warner@allmydata.com>
Thu, 7 Dec 2006 21:48:37 +0000 (14:48 -0700)
allmydata/test/test_system.py
allmydata/web/directory.xhtml
allmydata/web/welcome.xhtml
allmydata/webish.py

index 85e25a3c970ee6aa3d6198c24a3f89805dc20a81..165e42d8667927ffa4ee87b2d6f80ae50fd8d16f 100644 (file)
@@ -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
 
index 5b4d9c7aa27914fa33fb6235ab6e983c548c2760..38a09c9c74f2405c150df90101de52befa8af249 100644 (file)
@@ -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>
index 8ceb6c6f4f1b69dfc5ed6ead0e58e8163feeb868..7adb96ae37979e6454fdb01f1896e64bf32d1773 100644 (file)
@@ -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>
index 7dcb332eaead6dea304aa630f7ac8aa659fb3513..8823a2415feaad87cdf6c15c44a4e1a7da03502b 100644 (file)
@@ -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)