From 922b3034be0e814129b323318db9648b8d769d2f Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@lothar.com>
Date: Tue, 7 Apr 2009 19:13:40 -0700
Subject: [PATCH] web: make sure that PUT /uri?mutable=false really means
 immutable, fixes #675

---
 src/allmydata/test/test_web.py | 26 ++++++++++++++++++++++++++
 src/allmydata/web/root.py      |  4 ++--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py
index 9bca7521..ad3fa40b 100644
--- a/src/allmydata/test/test_web.py
+++ b/src/allmydata/test/test_web.py
@@ -717,6 +717,17 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
                                                       self.NEWFILE_CONTENTS))
         return d
 
+    def test_PUT_NEWFILEURL_not_mutable(self):
+        d = self.PUT(self.public_url + "/foo/new.txt?mutable=false",
+                     self.NEWFILE_CONTENTS)
+        # TODO: we lose the response code, so we can't check this
+        #self.failUnlessEqual(responsecode, 201)
+        d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"new.txt")
+        d.addCallback(lambda res:
+                      self.failUnlessChildContentsAre(self._foo_node, u"new.txt",
+                                                      self.NEWFILE_CONTENTS))
+        return d
+
     def test_PUT_NEWFILEURL_range_bad(self):
         headers = {"content-range": "bytes 1-10/%d" % len(self.NEWFILE_CONTENTS)}
         target = self.public_url + "/foo/new.txt"
@@ -2309,6 +2320,21 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d.addCallback(_check2)
         return d
 
+    def test_PUT_NEWFILE_URI_not_mutable(self):
+        file_contents = "New file contents here\n"
+        d = self.PUT("/uri?mutable=false", file_contents)
+        def _check(uri):
+            assert isinstance(uri, str), 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_NEWFILE_URI_only_PUT(self):
         d = self.PUT("/uri?t=bogus", "")
         d.addBoth(self.shouldFail, error.Error,
diff --git a/src/allmydata/web/root.py b/src/allmydata/web/root.py
index 196506e4..4d8d2c2d 100644
--- a/src/allmydata/web/root.py
+++ b/src/allmydata/web/root.py
@@ -16,7 +16,7 @@ from allmydata.interfaces import IFileNode
 from allmydata.web import filenode, directory, unlinked, status, operations
 from allmydata.web import reliability, storage
 from allmydata.web.common import abbreviate_size, getxmlfile, WebError, \
-     get_arg, RenderMixin
+     get_arg, RenderMixin, boolean_of_arg
 
 
 class URIHandler(RenderMixin, rend.Page):
@@ -45,7 +45,7 @@ class URIHandler(RenderMixin, rend.Page):
         # "PUT /uri?t=mkdir" to create an unlinked directory
         t = get_arg(req, "t", "").strip()
         if t == "":
-            mutable = bool(get_arg(req, "mutable", "").strip())
+            mutable = boolean_of_arg(get_arg(req, "mutable", "false").strip())
             if mutable:
                 return unlinked.PUTUnlinkedSSK(req, self.client)
             else:
-- 
2.45.2