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

Last change on this file was 1cfe843d, checked in by Alexandre Detiste <alexandre.detiste@…>, at 2024-02-22T23:40:25Z

more python2 removal

  • Property mode set to 100644
File size: 11.0 KB
Line 
1"""
2Ported to Python 3.
3"""
4
5import os
6from urllib.parse import quote as urlquote
7
8from twisted.python.filepath import FilePath
9from twisted.web.template import tags as T, Element, renderElement, XMLFile, renderer
10
11from allmydata.util import base32
12from allmydata.interfaces import IDirectoryNode, IFileNode, MDMF_VERSION
13from allmydata.web.common import MultiFormatResource
14from allmydata.mutable.common import UnrecoverableFileError # TODO: move
15
16
17class MoreInfo(MultiFormatResource):
18    """
19    A ``Resource`` for describing more information about a node.
20
21    :param node Node: The node to describe.
22    """
23
24    def __init__(self, node):
25        super(MoreInfo, self).__init__()
26        self.node = node
27
28    def render_HTML(self, req):
29        """
30        Render an HTML template describing this node.
31        """
32        return renderElement(req, MoreInfoElement(self.node))
33
34    render_INFO = render_HTML
35
36
37class MoreInfoElement(Element):
38    """
39    An ``Element`` HTML template which can be flattened to describe this node.
40
41    :param Node node: The node to describe.
42    """
43
44    loader = XMLFile(FilePath(__file__).sibling("info.xhtml"))
45
46    def __init__(self, node):
47        super(MoreInfoElement, self).__init__()
48        self.original = node
49
50    def abbrev(self, storage_index_or_none):
51        if storage_index_or_none:
52            return str(base32.b2a(storage_index_or_none)[:6], "ascii")
53        return "LIT file"
54
55    def get_type(self):
56        node = self.original
57        if IDirectoryNode.providedBy(node):
58            if not node.is_mutable():
59                return "immutable directory"
60            return "directory"
61        if IFileNode.providedBy(node):
62            si = node.get_storage_index()
63            if si:
64                if node.is_mutable():
65                    ret = "mutable file"
66                    if node.get_version() == MDMF_VERSION:
67                        ret += " (mdmf)"
68                    else:
69                        ret += " (sdmf)"
70                    return ret
71                return "immutable file"
72            return "immutable LIT file"
73        return "unknown"
74
75    @renderer
76    def title(self, req, tag):
77        node = self.original
78        si = node.get_storage_index()
79        t = "More Info for %s" % self.get_type()
80        if si:
81            t += " (SI=%s)" % self.abbrev(si)
82        return tag(t)
83
84    @renderer
85    def header(self, req, tag):
86        return self.title(req, tag)
87
88    @renderer
89    def type(self, req, tag):
90        return tag(self.get_type())
91
92    @renderer
93    def si(self, req, tag):
94        si = self.original.get_storage_index()
95        if not si:
96            return "None"
97        return tag(base32.b2a(si))
98
99    @renderer
100    def size(self, req, tag):
101        node = self.original
102        d = node.get_current_size()
103        def _no_size(size):
104            if size is None:
105                return "?"
106            return size
107        d.addCallback(_no_size)
108        def _handle_unrecoverable(f):
109            f.trap(UnrecoverableFileError)
110            return "?"
111        d.addErrback(_handle_unrecoverable)
112        d.addCallback(lambda size: tag(str(size)))
113        return d
114
115    @renderer
116    def directory_writecap(self, req, tag):
117        node = self.original
118        if not IDirectoryNode.providedBy(node):
119            return ""
120        if node.is_readonly():
121            return ""
122        return tag(node.get_uri())
123
124    @renderer
125    def directory_readcap(self, req, tag):
126        node = self.original
127        if not IDirectoryNode.providedBy(node):
128            return ""
129        return tag(node.get_readonly_uri())
130
131    @renderer
132    def directory_verifycap(self, req, tag):
133        node = self.original
134        if not IDirectoryNode.providedBy(node):
135            return ""
136        verifier = node.get_verify_cap()
137        if verifier:
138            return tag(node.get_verify_cap().to_string())
139        return ""
140
141    @renderer
142    def file_writecap(self, req, tag):
143        node = self.original
144        if IDirectoryNode.providedBy(node):
145            node = node._node
146        write_uri = node.get_write_uri()
147        if not write_uri:
148            return ""
149        return tag(write_uri)
150
151    @renderer
152    def file_readcap(self, req, tag):
153        node = self.original
154        if IDirectoryNode.providedBy(node):
155            node = node._node
156        read_uri = node.get_readonly_uri()
157        if not read_uri:
158            return ""
159        return tag(read_uri)
160
161    @renderer
162    def file_verifycap(self, req, tag):
163        node = self.original
164        if IDirectoryNode.providedBy(node):
165            node = node._node
166        verifier = node.get_verify_cap()
167        if verifier:
168            return tag(node.get_verify_cap().to_string())
169        return ""
170
171    def get_root(self, req):
172        # the addSlash=True gives us one extra (empty) segment
173        depth = len(req.prepath) + len(req.postpath) - 1
174        link = "/".join([".."] * depth)
175        return link
176
177    @renderer
178    def raw_link(self, req, tag):
179        node = self.original
180        if IDirectoryNode.providedBy(node):
181            node = node._node
182        elif IFileNode.providedBy(node):
183            pass
184        else:
185            return ""
186        root = self.get_root(req)
187        quoted_uri = urlquote(node.get_uri())
188        text_plain_url = "%s/file/%s/@@named=/raw.txt" % (root, quoted_uri)
189        return T.li("Raw data as ", T.a("text/plain", href=text_plain_url))
190
191    @renderer
192    def is_checkable(self, req, tag):
193        node = self.original
194        si = node.get_storage_index()
195        if si:
196            return tag
197        # don't show checker button for LIT files
198        return ""
199
200    @renderer
201    def check_form(self, req, tag):
202        node = self.original
203        quoted_uri = urlquote(node.get_uri())
204        target = self.get_root(req) + "/uri/" + quoted_uri
205        if IDirectoryNode.providedBy(node):
206            target += "/"
207        check = T.form(action=target, method="post",
208                       enctype="multipart/form-data")(
209            T.fieldset(
210            T.input(type="hidden", name="t", value="check"),
211            T.input(type="hidden", name="return_to", value="."),
212            T.legend("Check on this object", class_="freeform-form-label"),
213            T.div(
214            "Verify every bit? (EXPENSIVE):",
215            T.input(type="checkbox", name="verify"),
216            ),
217            T.div("Repair any problems?: ",
218                  T.input(type="checkbox", name="repair")),
219            T.div("Add/renew lease on all shares?: ",
220                  T.input(type="checkbox", name="add-lease")),
221            T.div("Emit results in JSON format?: ",
222                  T.input(type="checkbox", name="output", value="JSON")),
223
224            T.input(type="submit", value="Check"),
225
226            ))
227        return tag(check)
228
229    @renderer
230    def is_mutable_file(self, req, tag):
231        node = self.original
232        if IDirectoryNode.providedBy(node):
233            return ""
234        if (IFileNode.providedBy(node)
235            and node.is_mutable() and not node.is_readonly()):
236            return tag
237        return ""
238
239    @renderer
240    def overwrite_form(self, req, tag):
241        node = self.original
242        root = self.get_root(req)
243        action = "%s/uri/%s" % (root, urlquote(node.get_uri()))
244        done_url = "%s/uri/%s?t=info" % (root, urlquote(node.get_uri()))
245        overwrite = T.form(action=action, method="post",
246                           enctype="multipart/form-data")(
247            T.fieldset(
248            T.input(type="hidden", name="t", value="upload"),
249            T.input(type='hidden', name='when_done', value=done_url),
250            T.legend("Overwrite", class_="freeform-form-label"),
251            "Upload new contents: ",
252            T.input(type="file", name="file"),
253            " ",
254            T.input(type="submit", value="Replace Contents")
255            ))
256        return tag(overwrite)
257
258    @renderer
259    def is_directory(self, req, tag):
260        node = self.original
261        if IDirectoryNode.providedBy(node):
262            return tag
263        return ""
264
265    @renderer
266    def deep_check_form(self, req, tag):
267        ophandle = base32.b2a(os.urandom(16))
268        deep_check = T.form(action=req.path, method="post",
269                            enctype="multipart/form-data")(
270            T.fieldset(
271            T.input(type="hidden", name="t", value="start-deep-check"),
272            T.input(type="hidden", name="return_to", value="."),
273            T.legend("Run a deep-check operation (EXPENSIVE)", class_="freeform-form-label"),
274            T.div(
275            "Verify every bit? (EVEN MORE EXPENSIVE):",
276            T.input(type="checkbox", name="verify"),
277            ),
278            T.div("Repair any problems?: ",
279                  T.input(type="checkbox", name="repair")),
280            T.div("Add/renew lease on all shares?: ",
281                  T.input(type="checkbox", name="add-lease")),
282            T.div("Emit results in JSON format?: ",
283                  T.input(type="checkbox", name="output", value="JSON")),
284
285            T.input(type="hidden", name="ophandle", value=ophandle),
286            T.input(type="submit", value="Deep-Check"),
287
288            ))
289        return tag(deep_check)
290
291    @renderer
292    def deep_size_form(self, req, tag):
293        ophandle = base32.b2a(os.urandom(16))
294        deep_size = T.form(action=req.path, method="post",
295                            enctype="multipart/form-data")(
296            T.fieldset(
297            T.input(type="hidden", name="t", value="start-deep-size"),
298            T.legend("Run a deep-size operation (EXPENSIVE)", class_="freeform-form-label"),
299            T.input(type="hidden", name="ophandle", value=ophandle),
300            T.input(type="submit", value="Deep-Size"),
301            ))
302        return tag(deep_size)
303
304    @renderer
305    def deep_stats_form(self, req, tag):
306        ophandle = base32.b2a(os.urandom(16))
307        deep_stats = T.form(action=req.path, method="post",
308                            enctype="multipart/form-data")(
309            T.fieldset(
310            T.input(type="hidden", name="t", value="start-deep-stats"),
311            T.legend("Run a deep-stats operation (EXPENSIVE)", class_="freeform-form-label"),
312            T.input(type="hidden", name="ophandle", value=ophandle),
313            T.input(type="submit", value="Deep-Stats"),
314            ))
315        return tag(deep_stats)
316
317    @renderer
318    def manifest_form(self, req, tag):
319        ophandle = base32.b2a(os.urandom(16))
320        manifest = T.form(action=req.path, method="post",
321                            enctype="multipart/form-data")(
322            T.fieldset(
323            T.input(type="hidden", name="t", value="start-manifest"),
324            T.legend("Run a manifest operation (EXPENSIVE)", class_="freeform-form-label"),
325            T.div("Output Format: ",
326                  T.select(name="output")
327                  ( T.option("HTML", value="html", selected="true"),
328                    T.option("text", value="text"),
329                    T.option("JSON", value="json"),
330                    ),
331                  ),
332            T.input(type="hidden", name="ophandle", value=ophandle),
333            T.input(type="submit", value="Manifest"),
334            ))
335        return tag(manifest)
336
337
338# TODO: edge metadata
Note: See TracBrowser for help on using the repository browser.