source: trunk/src/allmydata/web/unlinked.py

Last change on this file was 6c7ffbe, checked in by Christopher R. Wood <chris@…>, at 2024-05-07T18:37:42Z

Allow mkdir-with-children to accept private-key

  • Property mode set to 100644
File size: 7.1 KB
Line 
1"""
2Ported to Python 3.
3"""
4from __future__ import annotations
5
6from urllib.parse import quote as urlquote
7
8from twisted.web import http
9from twisted.internet import defer
10from twisted.python.filepath import FilePath
11from twisted.web.resource import Resource
12from twisted.web.template import (
13    XMLFile,
14    renderer,
15    renderElement,
16    tags,
17)
18from allmydata.immutable.upload import FileHandle
19from allmydata.mutable.publish import MutableFileHandle
20from allmydata.web.common import (
21    get_keypair,
22    get_arg,
23    boolean_of_arg,
24    convert_children_json,
25    WebError,
26    get_format,
27    get_mutable_type,
28    render_exception,
29    url_for_string,
30)
31from allmydata.web import status
32
33def PUTUnlinkedCHK(req, client):
34    # "PUT /uri", to create an unlinked file.
35    uploadable = FileHandle(req.content, client.convergence)
36    d = client.upload(uploadable)
37    d.addCallback(lambda results: results.get_uri())
38    # that fires with the URI of the new file
39    return d
40
41def PUTUnlinkedSSK(req, client, version):
42    # SDMF: files are small, and we can only upload data
43    req.content.seek(0)
44    data = MutableFileHandle(req.content)
45    keypair = get_keypair(req)
46    d = client.create_mutable_file(data, version=version, unique_keypair=keypair)
47    d.addCallback(lambda n: n.get_uri())
48    return d
49
50def PUTUnlinkedCreateDirectory(req, client):
51    # "PUT /uri?t=mkdir", to create an unlinked directory.
52    file_format = get_format(req, None)
53    if file_format == "CHK":
54        raise WebError("format=CHK not accepted for PUT /uri?t=mkdir",
55                       http.BAD_REQUEST)
56    mt = None
57    if file_format:
58        mt = get_mutable_type(file_format)
59    d = client.create_dirnode(version=mt)
60    d.addCallback(lambda dirnode: dirnode.get_uri())
61    # XXX add redirect_to_result
62    return d
63
64
65def POSTUnlinkedCHK(req, client):
66    fileobj = req.fields["file"].file
67    uploadable = FileHandle(fileobj, client.convergence)
68    d = client.upload(uploadable)
69    when_done = get_arg(req, "when_done", None)
70    if when_done:
71        # if when_done= is provided, return a redirect instead of our
72        # usual upload-results page
73        def _done(upload_results, redir_to):
74            if b"%(uri)s" in redir_to:
75                redir_to = redir_to.replace(b"%(uri)s", urlquote(upload_results.get_uri()).encode("utf-8"))
76            return url_for_string(req, redir_to)
77        d.addCallback(_done, when_done)
78    else:
79        # return the Upload Results page, which includes the URI
80        d.addCallback(UploadResultsPage)
81    return d
82
83
84class UploadResultsPage(Resource, object):
85    """'POST /uri', to create an unlinked file."""
86
87    def __init__(self, upload_results):
88        """
89        :param IUploadResults upload_results: stats provider.
90        """
91        super(UploadResultsPage, self).__init__()
92        self._upload_results = upload_results
93
94    @render_exception
95    def render_POST(self, req):
96        elem = UploadResultsElement(self._upload_results)
97        return renderElement(req, elem)
98
99
100class UploadResultsElement(status.UploadResultsRendererMixin):
101
102    loader = XMLFile(FilePath(__file__).sibling("upload-results.xhtml"))
103
104    def __init__(self, upload_results):
105        super(UploadResultsElement, self).__init__()
106        self._upload_results = upload_results
107
108    def upload_results(self):
109        return defer.succeed(self._upload_results)
110
111    @renderer
112    def done(self, req, tag):
113        d = self.upload_results()
114        d.addCallback(lambda res: "done!")
115        return d
116
117    @renderer
118    def uri(self, req, tag):
119        d = self.upload_results()
120        d.addCallback(lambda res: res.get_uri())
121        return d
122
123    @renderer
124    def download_link(self, req, tag):
125        d = self.upload_results()
126        d.addCallback(lambda res:
127                      tags.a("/uri/" + str(res.get_uri(), "utf-8"),
128                             href="/uri/" + urlquote(str(res.get_uri(), "utf-8"))))
129        return d
130
131
132def POSTUnlinkedSSK(req, client, version):
133    # "POST /uri", to create an unlinked file.
134    # SDMF: files are small, and we can only upload data
135    contents = req.fields["file"].file
136    data = MutableFileHandle(contents)
137    d = client.create_mutable_file(data, version=version)
138    d.addCallback(lambda n: n.get_uri())
139    return d
140
141def POSTUnlinkedCreateDirectory(req, client):
142    # "POST /uri?t=mkdir", to create an unlinked directory.
143    ct = req.getHeader("content-type") or ""
144    if not ct.startswith("multipart/form-data"):
145        # guard against accidental attempts to call t=mkdir as if it were
146        # t=mkdir-with-children, but make sure we tolerate the usual HTML
147        # create-directory form (in which the t=mkdir and redirect_to_result=
148        # and other arguments can be passed encoded as multipath/form-data,
149        # in the request body).
150        req.content.seek(0)
151        kids_json = req.content.read()
152        if kids_json:
153            raise WebError("t=mkdir does not accept children=, "
154                           "try t=mkdir-with-children instead",
155                           http.BAD_REQUEST)
156    file_format = get_format(req, None)
157    if file_format == "CHK":
158        raise WebError("format=CHK not currently accepted for POST /uri?t=mkdir",
159                       http.BAD_REQUEST)
160    mt = None
161    if file_format:
162        mt = get_mutable_type(file_format)
163    d = client.create_dirnode(version=mt, unique_keypair=get_keypair(req))
164    redirect = get_arg(req, "redirect_to_result", "false")
165    if boolean_of_arg(redirect):
166        def _then_redir(res):
167            new_url = "uri/" + urlquote(res.get_uri())
168            req.setResponseCode(http.SEE_OTHER) # 303
169            req.setHeader('location', new_url)
170            return ''
171        d.addCallback(_then_redir)
172    else:
173        d.addCallback(lambda dirnode: dirnode.get_uri())
174    return d
175
176def POSTUnlinkedCreateDirectoryWithChildren(req, client):
177    # "POST /uri?t=mkdir", to create an unlinked directory.
178    req.content.seek(0)
179    kids_json = req.content.read()
180    kids = convert_children_json(client.nodemaker, kids_json)
181    d = client.create_dirnode(initial_children=kids, unique_keypair=get_keypair(req))
182    redirect = get_arg(req, "redirect_to_result", "false")
183    if boolean_of_arg(redirect):
184        def _then_redir(res):
185            new_url = "uri/" + urlquote(res.get_uri())
186            req.setResponseCode(http.SEE_OTHER) # 303
187            req.setHeader('location', new_url)
188            return ''
189        d.addCallback(_then_redir)
190    else:
191        d.addCallback(lambda dirnode: dirnode.get_uri())
192    return d
193
194def POSTUnlinkedCreateImmutableDirectory(req, client):
195    # "POST /uri?t=mkdir", to create an unlinked directory.
196    req.content.seek(0)
197    kids_json = req.content.read()
198    kids = convert_children_json(client.nodemaker, kids_json)
199    d = client.create_immutable_dirnode(kids)
200    redirect = get_arg(req, "redirect_to_result", "false")
201    if boolean_of_arg(redirect):
202        def _then_redir(res):
203            new_url = "uri/" + urlquote(res.get_uri())
204            req.setResponseCode(http.SEE_OTHER) # 303
205            req.setHeader('location', new_url)
206            return ''
207        d.addCallback(_then_redir)
208    else:
209        d.addCallback(lambda dirnode: dirnode.get_uri())
210    return d
Note: See TracBrowser for help on using the repository browser.