From 23c2c8d6603a3601669334b950d177a7949ac823 Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@allmydata.com>
Date: Tue, 5 Feb 2008 22:18:02 -0700
Subject: [PATCH] webish: add PUT /uri?mutable=true

---
 docs/webapi.txt                |  8 +++++++-
 src/allmydata/test/test_web.py | 28 ++++++++++++++++++++++++++++
 src/allmydata/webish.py        | 17 +++++++++++++----
 3 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/docs/webapi.txt b/docs/webapi.txt
index afe35cce..3cc00592 100644
--- a/docs/webapi.txt
+++ b/docs/webapi.txt
@@ -178,7 +178,7 @@ f. uploading a file
 
    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
-   write cap.
+   read cap.
 
   POST http://localhost:8123/uri?t=upload&mutable=true
 
@@ -186,6 +186,12 @@ f. uploading a file
    directory, but creates a mutable file (SSK) instead of an immutable one.
    The response contains the new URI that was created.
 
+  PUT http://localhost:8123/uri?mutable=true
+
+   This second form also accepts data from the HTTP request body, but creates
+   a mutable file (SSK) instead of an immutable one (CHK). The response
+   contains the new URI that was created.
+
 
 g. creating a new directory
 
diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py
index 520dcc38..af4cb7b3 100644
--- a/src/allmydata/test/test_web.py
+++ b/src/allmydata/test/test_web.py
@@ -1013,6 +1013,7 @@ class Web(WebMixin, unittest.TestCase):
             uri = uri.strip()
             u = IURI(uri)
             self.failUnless(IMutableFileURI.providedBy(u))
+            self.failUnless(u.storage_index in FakeMutableFileNode.all_contents)
             n = self.s.create_node_from_uri(uri)
             return n.download_to_data()
         d.addCallback(_check)
@@ -1541,6 +1542,33 @@ class Web(WebMixin, unittest.TestCase):
                   "/uri only accepts PUT and PUT?t=mkdir")
         return d
 
+    def test_PUT_NEWFILE_URI_mutable(self):
+        file_contents = "New file contents here\n"
+        d = self.PUT("/uri?mutable=true", file_contents)
+        def _check(uri):
+            uri = uri.strip()
+            u = IURI(uri)
+            self.failUnless(IMutableFileURI.providedBy(u))
+            self.failUnless(u.storage_index in FakeMutableFileNode.all_contents)
+            n = self.s.create_node_from_uri(uri)
+            return n.download_to_data()
+        d.addCallback(_check)
+        def _check2(data):
+            self.failUnlessEqual(data, file_contents)
+        d.addCallback(_check2)
+        return d
+
+        def _check(uri):
+            self.failUnless(uri in FakeCHKFileNode.all_contents)
+            self.failUnlessEqual(FakeCHKFileNode.all_contents[uri],
+                                 file_contents)
+            return self.GET("/uri/%s" % uri)
+        d.addCallback(_check)
+        def _check2(res):
+            self.failUnlessEqual(res, file_contents)
+        d.addCallback(_check2)
+        return d
+
     def test_PUT_mkdir(self):
         d = self.PUT("/uri?t=mkdir", "")
         def _check(uri):
diff --git a/src/allmydata/webish.py b/src/allmydata/webish.py
index 65132317..8795b05e 100644
--- a/src/allmydata/webish.py
+++ b/src/allmydata/webish.py
@@ -1203,10 +1203,19 @@ class URIPUTHandler(rend.Page):
         if t == "":
             # "PUT /uri", to create an unlinked file. This is like PUT but
             # without the associated set_uri.
-            uploadable = FileHandle(req.content)
-            d = IClient(ctx).upload(uploadable)
-            d.addCallback(lambda results: results.uri)
-            # that fires with the URI of the new file
+            mutable = bool(get_arg(req, "mutable", "").strip())
+            if mutable:
+                # SDMF: files are small, and we can only upload data
+                contents = req.content
+                contents.seek(0)
+                data = contents.read()
+                d = IClient(ctx).create_mutable_file(data)
+                d.addCallback(lambda n: n.get_uri())
+            else:
+                uploadable = FileHandle(req.content)
+                d = IClient(ctx).upload(uploadable)
+                d.addCallback(lambda results: results.uri)
+                # that fires with the URI of the new file
             return d
 
         if t == "mkdir":
-- 
2.45.2