From e58a01270b6b754f1c76b4640f9813049ce1c783 Mon Sep 17 00:00:00 2001 From: Marcus Wanner Date: Fri, 18 Nov 2011 20:42:10 -0500 Subject: [PATCH] Change the arbitrary URI support from implied to explicit The move webapi function now takes a target_type argument which lets it know whether the target is a subdirectory name or URI. This is an improvement over the old system in which the move handler tried to guess whether the target was a name or a URI. Also fixed a little docs copypaste problem and tweaked some line wrapping. --- docs/frontends/webapi.rst | 21 +++++++++++++-------- src/allmydata/test/test_web.py | 16 +++++++++++++--- src/allmydata/uri.py | 7 ------- src/allmydata/web/directory.py | 21 ++++++++++++++------- src/allmydata/web/move-form.xhtml | 10 ++++++++-- 5 files changed, 48 insertions(+), 27 deletions(-) diff --git a/docs/frontends/webapi.rst b/docs/frontends/webapi.rst index 5f1060b1..11cee722 100644 --- a/docs/frontends/webapi.rst +++ b/docs/frontends/webapi.rst @@ -1281,16 +1281,21 @@ Renaming A Child Moving A Child ---------------- -``POST /uri/$DIRCAP/[SUBDIRS../]?t=rename&from_name=OLD&to_dir=TARGET[&to_name=NEW]`` +``POST /uri/$DIRCAP/[SUBDIRS../]?t=move&from_name=OLD&to_dir=TARGET`` This instructs the node to move a child of the given directory to a - different directory, both of which must be mutable. The child can also be - renamed in the process. The to_dir parameter can be either the name of a - subdirectory of the dircap from which the child is being moved (multiple - levels of descent are supported) or the writecap of an unrelated directory. - - This operation will replace any existing child of the new name, making it - behave like the UNIX "``mv -f``" command. The original child is not + different directory, both of which must be mutable. The child can also + be renamed in the process. The to_dir parameter should contain the name + of a subdirectory of the dircap from which the child is being moved + (multiple levels of descent are supported), unless the file is to be + moved to an unrelated directory. In the latter case, this can be + specified by passing a target_type=uri argument and the target URI in + to_dir=. If the target is the name of a subdirectory, this can be + signified by passing target_type=name. A new name for the child can + also be specified using the to_name= parameter. + + This operation will replace any existing child of the new name, making + it behave like the UNIX "``mv -f``" command. The original child is not unlinked until it is linked into the target directory. Other Utilities diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py index a03d56c0..baf00178 100644 --- a/src/allmydata/test/test_web.py +++ b/src/allmydata/test/test_web.py @@ -3247,7 +3247,6 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi return d def test_POST_move_file(self): - """""" d = self.POST(self.public_url + "/foo", t="move", from_name="bar.txt", to_dir="sub") d.addCallback(lambda res: @@ -3331,6 +3330,16 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi d.addCallback(self.failUnlessIsBazDotTxt) return d + def test_POST_move_file_bad_target_type(self): + d = self.POST(self.public_url + "/foo", t="move", target_type="*D", + from_name="bar.txt", to_dir="sub") + d.addBoth(self.shouldFail, error.Error, + "test_POST_rename_file_slash_fail", + "400 Bad Request", + "invalid target_type parameter", + ) + return d + def test_POST_move_file_multi_level(self): d = self.POST(self.public_url + "/foo/sub/level2?t=mkdir", "") d.addCallback(lambda res: self.POST(self.public_url + "/foo", t="move", @@ -3344,7 +3353,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi return d def test_POST_move_file_to_uri(self): - d = self.POST(self.public_url + "/foo", t="move", + d = self.POST(self.public_url + "/foo", t="move", target_type="uri", from_name="bar.txt", to_dir=self._sub_uri) d.addCallback(lambda res: self.failIfNodeHasChild(self._foo_node, u"bar.txt")) @@ -3379,7 +3388,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi return d def test_POST_move_file_to_bad_uri(self): - d = self.POST(self.public_url + "/foo", t="move", from_name="bar.txt", + d = self.POST(self.public_url + "/foo", t="move", + from_name="bar.txt", target_type="uri", to_dir="URI:DIR2:mn5jlyjnrjeuydyswlzyui72i:rmneifcj6k6sycjljjhj3f6majsq2zqffydnnul5hfa4j577arma") d.addBoth(self.shouldFail, error.Error, "POST_move_file_to_bad_uri", diff --git a/src/allmydata/uri.py b/src/allmydata/uri.py index dfa6cfa9..ee9c86aa 100644 --- a/src/allmydata/uri.py +++ b/src/allmydata/uri.py @@ -934,13 +934,6 @@ def is_literal_file_uri(s): s.startswith(ALLEGED_READONLY_PREFIX + 'URI:LIT:') or s.startswith(ALLEGED_IMMUTABLE_PREFIX + 'URI:LIT:')) -def is_writeable_directory_uri(s): - if not isinstance(s, str): - return False - return (s.startswith('URI:DIR2:') or - s.startswith(ALLEGED_READONLY_PREFIX + 'URI:DIR2:') or - s.startswith(ALLEGED_IMMUTABLE_PREFIX + 'URI:DIR2:')) - def has_uri_prefix(s): if not isinstance(s, str): return False diff --git a/src/allmydata/web/directory.py b/src/allmydata/web/directory.py index d4f88de2..c7f9af2d 100644 --- a/src/allmydata/web/directory.py +++ b/src/allmydata/web/directory.py @@ -13,7 +13,7 @@ from nevow.inevow import IRequest from foolscap.api import fireEventually from allmydata.util import base32, time_format -from allmydata.uri import from_string_dirnode, is_writeable_directory_uri +from allmydata.uri import from_string_dirnode from allmydata.interfaces import IDirectoryNode, IFileNode, IFilesystemNode, \ IImmutableFileNode, IMutableFileNode, ExistingChildError, \ NoSuchChildError, EmptyPathnameComponentError, SDMF_VERSION, MDMF_VERSION @@ -444,23 +444,30 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin): if not from_name or not to_dir: raise WebError("move requires from_name and to_dir") replace = boolean_of_arg(get_arg(req, "replace", "true")) + target_type = get_arg(req, "target_type", "name") + if not target_type in ["name", "uri"]: + raise WebError("invalid target_type parameter", + http.BAD_REQUEST) # allow from_name to contain slashes, so they can fix names that # were accidentally created with them. But disallow them in to_name # (if it's specified), to discourage the practice. if to_name and "/" in to_name: - raise WebError("to_name= may not contain a slash", http.BAD_REQUEST) + raise WebError("to_name= may not contain a slash", + http.BAD_REQUEST) - d = self.node.has_child(to_dir.split('/')[0]) - def get_target_node(isname): - if isname or not is_writeable_directory_uri(str(to_dir)): + d = defer.Deferred() + def get_target_node(target_type): + if target_type == "name": return self.node.get_child_at_path(to_dir) - else: + elif target_type == "uri": return self.client.create_node_from_uri(str(to_dir)) d.addCallback(get_target_node) + d.callback(target_type) def is_target_node_usable(target_node): if not IDirectoryNode.providedBy(target_node): - raise WebError("to_dir is not a usable directory", http.GONE) + raise WebError("to_dir is not a usable directory", + http.GONE) return target_node d.addCallback(is_target_node_usable) d.addCallback(lambda new_parent: self.node.move_child_to( diff --git a/src/allmydata/web/move-form.xhtml b/src/allmydata/web/move-form.xhtml index 51baae7d..1df427cc 100644 --- a/src/allmydata/web/move-form.xhtml +++ b/src/allmydata/web/move-form.xhtml @@ -17,12 +17,18 @@ Move child: - +
to
+ + + +

New name? - +
-- 2.45.2