From 62e8528cc630bea2f0c64e9a9e9309f84fe65a0d Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Sat, 7 Jul 2007 22:06:52 -0700 Subject: [PATCH] web: /uri/ must escape slashes, we use bangs for this --- docs/webapi.txt | 10 ++++++++++ src/allmydata/test/test_web.py | 12 +++++++++--- src/allmydata/uri.py | 2 +- src/allmydata/webish.py | 15 ++++++++++----- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/docs/webapi.txt b/docs/webapi.txt index dc445a17..b5f6355f 100644 --- a/docs/webapi.txt +++ b/docs/webapi.txt @@ -259,6 +259,12 @@ for files and directories which do not yet exist. would upload a file (with contents taken from the local filesystem) to a new file in a subdirectory of the referenced dirnode. + Note that since tahoe URIs may contain slashes (in particular, dirnode URIs + contain a FURL, which resembles a regular HTTP URL and starts with pb://), + when URIs are used in this form, they must be specially quoted. All slashes + in the URI must be replaced by '!' characters. + + PUT NEWFILEURL?t=uri This attaches a child (either a file or a directory) to the vdrive at the @@ -277,6 +283,10 @@ for files and directories which do not yet exist. URI: unlike the GET /uri/$URI form, you cannot traverse to child nodes by appending additional path segments to the URL. + The $URI provided as a query argument is allowed to contain slashes. The + redirection provided will escape the slashes with exclamation points, as + described above. + == XMLRPC == http://localhost:8011/xmlrpc diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py index f20e5e31..372094b0 100644 --- a/src/allmydata/test/test_web.py +++ b/src/allmydata/test/test_web.py @@ -69,7 +69,7 @@ class MyDirectoryNode(dirnode.MutableDirectoryNode): self._my_files = files self._my_client = client if uri is None: - uri = str(uri_counter.next()) + uri = "URI:DIR:stuff/%s" % str(uri_counter.next()) self._uri = str(uri) self._my_nodes[self._uri] = self self.children = {} @@ -750,7 +750,7 @@ class Web(unittest.TestCase): return res def test_GET_URI_URL(self): # YES - base = "/uri/%s" % self._bar_txt_uri + base = "/uri/%s" % self._bar_txt_uri.replace("/","!") d = self.GET(base) d.addCallback(self.failUnlessIsBarDotTxt) d.addCallback(lambda res: self.GET(base+"?filename=bar.txt")) @@ -760,11 +760,17 @@ class Web(unittest.TestCase): return d def test_GET_URI_URL_dir(self): # YES - base = "/uri/%s?t=json" % self._foo_uri + base = "/uri/%s?t=json" % self._foo_uri.replace("/","!") d = self.GET(base) d.addCallback(self.failUnlessIsFooJSON) return d + def test_GET_URI_URL_missing(self): + base = "/uri/missing?t=json" + d = self.GET(base) + d.addBoth(self.should404, "test_GET_URI_URL_missing") + return d + def test_PUT_NEWFILEURL_uri(self): # YES new_uri = self.makefile(8) d = self.PUT("/vdrive/global/foo/new.txt?t=uri", new_uri) diff --git a/src/allmydata/uri.py b/src/allmydata/uri.py index 80ff5b3c..f50736d2 100644 --- a/src/allmydata/uri.py +++ b/src/allmydata/uri.py @@ -27,7 +27,7 @@ def pack_uri(storage_index, key, uri_extension_hash, def unpack_uri(uri): - assert uri.startswith("URI:") + assert uri.startswith("URI:"), uri d = {} (header, storage_index_s, key_s, uri_extension_hash_s, diff --git a/src/allmydata/webish.py b/src/allmydata/webish.py index 7be89801..19a62c5f 100644 --- a/src/allmydata/webish.py +++ b/src/allmydata/webish.py @@ -101,11 +101,12 @@ class Directory(rend.Page): delete = "-" ctx.fillSlots("delete", delete) + uri_link = urllib.quote(target.get_uri().replace("/", "!")) childdata = [T.a(href="%s?t=json" % name)["JSON"], ", ", T.a(href="%s?t=xml" % name)["XML"], ", ", T.a(href="%s?t=uri" % name)["URI"], ", ", T.a(href="%s?t=readonly-uri" % name)["readonly-URI"], ", ", - T.a(href="/uri/%s" % target.get_uri())["URI-link"], + T.a(href="/uri/%s" % uri_link)["URI-link"], ] ctx.fillSlots("data", childdata) @@ -846,19 +847,23 @@ class Root(rend.Page): d.addCallback(lambda vd: vd.locateChild(ctx, segments[2:])) return d elif segments[0] == "uri": - if len(segments) == 1: + if len(segments) == 1 or segments[1] == '': if "uri" in req.args: - uri = req.args["uri"][0] + uri = req.args["uri"][0].replace("/", "!") there = url.URL.fromContext(ctx) there = there.clear("uri") there = there.child("uri").child(uri) return there, () if len(segments) < 2: return rend.NotFound - uri = segments[1] + uri = segments[1].replace("!", "/") d = vdrive.get_node(uri) - d.addCallback(lambda node: VDrive(node, "")) + d.addCallback(lambda node: VDrive(node, "from-uri")) d.addCallback(lambda vd: vd.locateChild(ctx, segments[2:])) + def _trap_KeyError(f): + f.trap(KeyError) + return rend.FourOhFour(), () + d.addErrback(_trap_KeyError) return d elif segments[0] == "xmlrpc": pass # TODO -- 2.45.2