import os, urllib from twisted.python.filepath import FilePath from twisted.web.template import tags as T, Element, renderElement, XMLFile, renderer from allmydata.util import base32 from allmydata.interfaces import IDirectoryNode, IFileNode, MDMF_VERSION from allmydata.web.common import MultiFormatResource from allmydata.mutable.common import UnrecoverableFileError # TODO: move class MoreInfo(MultiFormatResource): """ A ``Resource`` for describing more information about a node. :param node Node: The node to describe. """ def __init__(self, node): super(MoreInfo, self).__init__() self.node = node def render_HTML(self, req): """ Render an HTML template describing this node. """ return renderElement(req, MoreInfoElement(self.node)) render_INFO = render_HTML class MoreInfoElement(Element): """ An ``Element`` HTML template which can be flattened to describe this node. :param Node node: The node to describe. """ loader = XMLFile(FilePath(__file__).sibling("info.xhtml")) def __init__(self, node): super(MoreInfoElement, self).__init__() self.original = node def abbrev(self, storage_index_or_none): if storage_index_or_none: return base32.b2a(storage_index_or_none)[:6] return "LIT file" def get_type(self): node = self.original if IDirectoryNode.providedBy(node): if not node.is_mutable(): return "immutable directory" return "directory" if IFileNode.providedBy(node): si = node.get_storage_index() if si: if node.is_mutable(): ret = "mutable file" if node.get_version() == MDMF_VERSION: ret += " (mdmf)" else: ret += " (sdmf)" return ret return "immutable file" return "immutable LIT file" return "unknown" @renderer def title(self, req, tag): node = self.original si = node.get_storage_index() t = "More Info for %s" % self.get_type() if si: t += " (SI=%s)" % self.abbrev(si) return tag(t) @renderer def header(self, req, tag): return self.title(req, tag) @renderer def type(self, req, tag): return tag(self.get_type()) @renderer def si(self, req, tag): si = self.original.get_storage_index() if not si: return "None" return tag(base32.b2a(si)) @renderer def size(self, req, tag): node = self.original d = node.get_current_size() def _no_size(size): if size is None: return "?" return size d.addCallback(_no_size) def _handle_unrecoverable(f): f.trap(UnrecoverableFileError) return "?" d.addErrback(_handle_unrecoverable) d.addCallback(lambda size: tag(str(size))) return d @renderer def directory_writecap(self, req, tag): node = self.original if not IDirectoryNode.providedBy(node): return "" if node.is_readonly(): return "" return tag(node.get_uri()) @renderer def directory_readcap(self, req, tag): node = self.original if not IDirectoryNode.providedBy(node): return "" return tag(node.get_readonly_uri()) @renderer def directory_verifycap(self, req, tag): node = self.original if not IDirectoryNode.providedBy(node): return "" verifier = node.get_verify_cap() if verifier: return tag(node.get_verify_cap().to_string()) return "" @renderer def file_writecap(self, req, tag): node = self.original if IDirectoryNode.providedBy(node): node = node._node write_uri = node.get_write_uri() if not write_uri: return "" return tag(write_uri) @renderer def file_readcap(self, req, tag): node = self.original if IDirectoryNode.providedBy(node): node = node._node read_uri = node.get_readonly_uri() if not read_uri: return "" return tag(read_uri) @renderer def file_verifycap(self, req, tag): node = self.original if IDirectoryNode.providedBy(node): node = node._node verifier = node.get_verify_cap() if verifier: return tag(node.get_verify_cap().to_string()) return "" def get_root(self, req): # the addSlash=True gives us one extra (empty) segment depth = len(req.prepath) + len(req.postpath) - 1 link = "/".join([".."] * depth) return link @renderer def raw_link(self, req, tag): node = self.original if IDirectoryNode.providedBy(node): node = node._node elif IFileNode.providedBy(node): pass else: return "" root = self.get_root(req) quoted_uri = urllib.quote(node.get_uri()) text_plain_url = "%s/file/%s/@@named=/raw.txt" % (root, quoted_uri) return T.li("Raw data as ", T.a("text/plain", href=text_plain_url)) @renderer def is_checkable(self, req, tag): node = self.original si = node.get_storage_index() if si: return tag # don't show checker button for LIT files return "" @renderer def check_form(self, req, tag): node = self.original quoted_uri = urllib.quote(node.get_uri()) target = self.get_root(req) + "/uri/" + quoted_uri if IDirectoryNode.providedBy(node): target += "/" check = T.form(action=target, method="post", enctype="multipart/form-data")( T.fieldset( T.input(type="hidden", name="t", value="check"), T.input(type="hidden", name="return_to", value="."), T.legend("Check on this object", class_="freeform-form-label"), T.div( "Verify every bit? (EXPENSIVE):", T.input(type="checkbox", name="verify"), ), T.div("Repair any problems?: ", T.input(type="checkbox", name="repair")), T.div("Add/renew lease on all shares?: ", T.input(type="checkbox", name="add-lease")), T.div("Emit results in JSON format?: ", T.input(type="checkbox", name="output", value="JSON")), T.input(type="submit", value="Check"), )) return tag(check) @renderer def is_mutable_file(self, req, tag): node = self.original if IDirectoryNode.providedBy(node): return "" if (IFileNode.providedBy(node) and node.is_mutable() and not node.is_readonly()): return tag return "" @renderer def overwrite_form(self, req, tag): node = self.original root = self.get_root(req) action = "%s/uri/%s" % (root, urllib.quote(node.get_uri())) done_url = "%s/uri/%s?t=info" % (root, urllib.quote(node.get_uri())) overwrite = T.form(action=action, method="post", enctype="multipart/form-data")( T.fieldset( T.input(type="hidden", name="t", value="upload"), T.input(type='hidden', name='when_done', value=done_url), T.legend("Overwrite", class_="freeform-form-label"), "Upload new contents: ", T.input(type="file", name="file"), " ", T.input(type="submit", value="Replace Contents") )) return tag(overwrite) @renderer def is_directory(self, req, tag): node = self.original if IDirectoryNode.providedBy(node): return tag return "" @renderer def deep_check_form(self, req, tag): ophandle = base32.b2a(os.urandom(16)) deep_check = T.form(action=req.path, method="post", enctype="multipart/form-data")( T.fieldset( T.input(type="hidden", name="t", value="start-deep-check"), T.input(type="hidden", name="return_to", value="."), T.legend("Run a deep-check operation (EXPENSIVE)", class_="freeform-form-label"), T.div( "Verify every bit? (EVEN MORE EXPENSIVE):", T.input(type="checkbox", name="verify"), ), T.div("Repair any problems?: ", T.input(type="checkbox", name="repair")), T.div("Add/renew lease on all shares?: ", T.input(type="checkbox", name="add-lease")), T.div("Emit results in JSON format?: ", T.input(type="checkbox", name="output", value="JSON")), T.input(type="hidden", name="ophandle", value=ophandle), T.input(type="submit", value="Deep-Check"), )) return tag(deep_check) @renderer def deep_size_form(self, req, tag): ophandle = base32.b2a(os.urandom(16)) deep_size = T.form(action=req.path, method="post", enctype="multipart/form-data")( T.fieldset( T.input(type="hidden", name="t", value="start-deep-size"), T.legend("Run a deep-size operation (EXPENSIVE)", class_="freeform-form-label"), T.input(type="hidden", name="ophandle", value=ophandle), T.input(type="submit", value="Deep-Size"), )) return tag(deep_size) @renderer def deep_stats_form(self, req, tag): ophandle = base32.b2a(os.urandom(16)) deep_stats = T.form(action=req.path, method="post", enctype="multipart/form-data")( T.fieldset( T.input(type="hidden", name="t", value="start-deep-stats"), T.legend("Run a deep-stats operation (EXPENSIVE)", class_="freeform-form-label"), T.input(type="hidden", name="ophandle", value=ophandle), T.input(type="submit", value="Deep-Stats"), )) return tag(deep_stats) @renderer def manifest_form(self, req, tag): ophandle = base32.b2a(os.urandom(16)) manifest = T.form(action=req.path, method="post", enctype="multipart/form-data")( T.fieldset( T.input(type="hidden", name="t", value="start-manifest"), T.legend("Run a manifest operation (EXPENSIVE)", class_="freeform-form-label"), T.div("Output Format: ", T.select(name="output") ( T.option("HTML", value="html", selected="true"), T.option("text", value="text"), T.option("JSON", value="json"), ), ), T.input(type="hidden", name="ophandle", value=ophandle), T.input(type="submit", value="Manifest"), )) return tag(manifest) # TODO: edge metadata