From 1e4504463c28d57036e84e130c75eb8360ab9ce2 Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@allmydata.com>
Date: Tue, 5 Feb 2008 23:01:37 -0700
Subject: [PATCH] webish: make POST /uri?t=upload deposit you on an 'Upload
 Results' page

---
 docs/webapi.txt                         |  5 ++--
 src/allmydata/test/test_web.py          | 11 +++++++
 src/allmydata/web/unlinked-upload.xhtml | 22 ++++++++++++++
 src/allmydata/webish.py                 | 39 +++++++++++++++++++------
 4 files changed, 66 insertions(+), 11 deletions(-)
 create mode 100644 src/allmydata/web/unlinked-upload.xhtml

diff --git a/docs/webapi.txt b/docs/webapi.txt
index 3cc00592..6b97019b 100644
--- a/docs/webapi.txt
+++ b/docs/webapi.txt
@@ -177,8 +177,9 @@ f. uploading a file
   POST http://localhost:8123/uri?t=upload
 
    This action also uploads a file without attaching it to a virtual drive
-   directory, but can be used from an HTML form. The response is the file
-   read cap.
+   directory, but can be used from an HTML form. The response is an HTML page
+   that describes the results of the upload, including the resulting URI (but
+   also including information about which peers were used, etc).
 
   POST http://localhost:8123/uri?t=upload&mutable=true
 
diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py
index 5acb9ec9..c6ba8d48 100644
--- a/src/allmydata/test/test_web.py
+++ b/src/allmydata/test/test_web.py
@@ -993,6 +993,17 @@ class Web(WebMixin, unittest.TestCase):
     def test_POST_upload_no_link(self):
         d = self.POST("/uri", t="upload",
                       file=("new.txt", self.NEWFILE_CONTENTS))
+        def _check_upload_results(page):
+            # this should be a page which describes the results of the upload
+            # that just finished.
+            self.failUnless("Upload Results:" in page)
+            self.failUnless("URI:" in page)
+            uri_re = re.compile("URI: <tt><span>(.*)</span>")
+            mo = uri_re.search(page)
+            self.failUnless(mo, page)
+            new_uri = mo.group(1)
+            return new_uri
+        d.addCallback(_check_upload_results)
         d.addCallback(self.failUnlessCHKURIHasContents, self.NEWFILE_CONTENTS)
         return d
 
diff --git a/src/allmydata/web/unlinked-upload.xhtml b/src/allmydata/web/unlinked-upload.xhtml
new file mode 100644
index 00000000..0de727b3
--- /dev/null
+++ b/src/allmydata/web/unlinked-upload.xhtml
@@ -0,0 +1,22 @@
+<html xmlns:n="http://nevow.com/ns/nevow/0.1">
+  <head>
+    <title>AllMyData - Tahoe - File Uploaded</title>
+    <!-- <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>Uploading File... <span n:render="string" n:data="done" /></h1>
+
+<h2>Upload Results:</h2>
+<ul>
+  <li>URI: <tt><span n:render="string" n:data="uri" /></tt></li>
+  <li>Download link: <span n:render="download_link" /></li>
+</ul>
+
+<div>Return to the <a href="/">Welcome Page</a></div>
+
+  </body>
+</html>
diff --git a/src/allmydata/webish.py b/src/allmydata/webish.py
index 611beb2c..e5e824ef 100644
--- a/src/allmydata/webish.py
+++ b/src/allmydata/webish.py
@@ -7,7 +7,7 @@ from twisted.internet import defer, address
 from twisted.internet.interfaces import IConsumer
 from nevow import inevow, rend, loaders, appserver, url, tags as T
 from nevow.static import File as nevow_File # TODO: merge with static.File?
-from allmydata.util import fileutil, idlib
+from allmydata.util import fileutil, idlib, observer
 import simplejson
 from allmydata.interfaces import IDownloadTarget, IDirectoryNode, IFileNode, \
      IMutableFileNode
@@ -1242,16 +1242,37 @@ class UnlinkedPUTCreateDirectory(rend.Page):
 
 
 class UnlinkedPOSTCHKUploader(rend.Page):
-    def renderHTTP(self, ctx):
-        req = inevow.IRequest(ctx)
-        assert req.method == "POST"
+    """'POST /uri', to create an unlinked file."""
+    docFactory = getxmlfile("unlinked-upload.xhtml")
 
-        # "POST /uri", to create an unlinked file.
+    def __init__(self, client, req):
+        rend.Page.__init__(self)
+        # we start the upload now, and distribute notification of its
+        # completion to render_ methods with an ObserverList
+        assert req.method == "POST"
+        self._done = observer.OneShotObserverList()
         fileobj = req.fields["file"].file
         uploadable = FileHandle(fileobj)
-        d = IClient(ctx).upload(uploadable)
-        d.addCallback(lambda results: results.uri)
-        # that fires with the URI of the new file
+        d = client.upload(uploadable)
+        d.addBoth(self._done.fire)
+
+    def upload_results(self):
+        return self._done.when_fired()
+
+    def data_done(self, ctx, data):
+        d = self.upload_results()
+        d.addCallback(lambda res: "done!")
+        return d
+
+    def data_uri(self, ctx, data):
+        d = self.upload_results()
+        d.addCallback(lambda res: res.uri)
+        return d
+
+    def render_download_link(self, ctx, data):
+        d = self.upload_results()
+        d.addCallback(lambda res: T.a(href="/uri/" + urllib.quote(res.uri))
+                      ["/uri/" + res.uri])
         return d
 
 class UnlinkedPOSTSSKUploader(rend.Page):
@@ -1340,7 +1361,7 @@ class Root(rend.Page):
                             if mutable:
                                 return UnlinkedPOSTSSKUploader(), ()
                             else:
-                                return UnlinkedPOSTCHKUploader(), ()
+                                return UnlinkedPOSTCHKUploader(client, req), ()
                         if t == "mkdir":
                             return UnlinkedPOSTCreateDirectory(), ()
                         errmsg = "/uri accepts only PUT, PUT?t=mkdir, POST?t=upload, and POST?t=mkdir"
-- 
2.45.2