paul@52 | 1 | # -*- coding: iso-8859-1 -*- |
paul@52 | 2 | """ |
paul@52 | 3 | MoinMoin - pgp_keys (MoinShare) |
paul@52 | 4 | |
paul@63 | 5 | @copyright: 2012, 2013, 2014 by Paul Boddie <paul@boddie.org.uk> |
paul@52 | 6 | @license: GNU GPL (v2 or later), see COPYING.txt for details. |
paul@52 | 7 | """ |
paul@52 | 8 | |
paul@52 | 9 | from MoinMessage import GPG, MoinMessageError |
paul@52 | 10 | from MoinMessageSupport import get_homedir |
paul@52 | 11 | from MoinSupport import parseAttributes, escattr |
paul@52 | 12 | |
paul@52 | 13 | Dependencies = ["pages"] |
paul@52 | 14 | |
paul@52 | 15 | # Parser support. |
paul@52 | 16 | |
paul@52 | 17 | class Parser: |
paul@52 | 18 | |
paul@52 | 19 | "Display data in application/pgp-keys format." |
paul@52 | 20 | |
paul@52 | 21 | Dependencies = Dependencies |
paul@52 | 22 | extensions = [] |
paul@52 | 23 | |
paul@52 | 24 | # Input content types understood by this parser. |
paul@52 | 25 | |
paul@52 | 26 | input_mimetypes = ["application/pgp-keys"] |
paul@52 | 27 | |
paul@52 | 28 | # Output content types preferred by this parser. |
paul@52 | 29 | |
paul@52 | 30 | output_mimetypes = ["text/html"] |
paul@52 | 31 | |
paul@52 | 32 | def __init__(self, raw, request, **kw): |
paul@52 | 33 | |
paul@52 | 34 | """ |
paul@52 | 35 | Initialise the parser with the given 'raw' data, 'request' and any |
paul@52 | 36 | keyword arguments that may have been supplied. |
paul@52 | 37 | """ |
paul@52 | 38 | |
paul@52 | 39 | self.raw = raw |
paul@52 | 40 | self.request = request |
paul@52 | 41 | self.attrs = parseAttributes(kw.get("format_args", ""), False) |
paul@52 | 42 | |
paul@52 | 43 | def format(self, fmt, write=None): |
paul@52 | 44 | |
paul@52 | 45 | """ |
paul@63 | 46 | Format a key using the given formatter 'fmt'. If the 'write' parameter |
paul@52 | 47 | is specified, use it to write output; otherwise, write output using the |
paul@52 | 48 | request. |
paul@52 | 49 | """ |
paul@52 | 50 | |
paul@52 | 51 | (write or self.request.write)(fmt.text(self.raw)) |
paul@52 | 52 | |
paul@52 | 53 | # Extra API methods. |
paul@52 | 54 | |
paul@52 | 55 | def formatForOutputType(self, mimetype, write=None): |
paul@52 | 56 | |
paul@52 | 57 | """ |
paul@63 | 58 | Format a key for the given 'mimetype'. If the 'write' parameter is |
paul@52 | 59 | specified, use it to write output; otherwise, write output using the |
paul@52 | 60 | request. |
paul@52 | 61 | """ |
paul@52 | 62 | |
paul@52 | 63 | request = self.request |
paul@52 | 64 | write = write or request.write |
paul@52 | 65 | fmt = request.html_formatter |
paul@52 | 66 | _ = request.getText |
paul@52 | 67 | |
paul@52 | 68 | if not mimetype == "text/html": |
paul@52 | 69 | return |
paul@52 | 70 | |
paul@52 | 71 | homedir = get_homedir(request) |
paul@52 | 72 | if not homedir: |
paul@52 | 73 | return |
paul@52 | 74 | |
paul@52 | 75 | gpg = GPG(homedir) |
paul@52 | 76 | |
paul@52 | 77 | write(fmt.text(_("This message contains one or more keys."))) |
paul@52 | 78 | |
paul@52 | 79 | write(fmt.rawHTML('<table class="moinshare-pgp-keys" summary="%s">' % escattr(_("A table of keys")))) |
paul@52 | 80 | write(fmt.rawHTML("<thead>")) |
paul@52 | 81 | write(fmt.table_row(on=1)) |
paul@52 | 82 | write(fmt.rawHTML("<th>")); write(fmt.text(_("Known"))); write(fmt.rawHTML("</th>")) |
paul@52 | 83 | write(fmt.rawHTML("<th>")); write(fmt.text(_("Identity"))); write(fmt.rawHTML("</th>")) |
paul@53 | 84 | write(fmt.rawHTML("<th>")); write(fmt.text(_("Confirmed by"))); write(fmt.rawHTML("</th>")) |
paul@52 | 85 | write(fmt.table_row(on=0)) |
paul@52 | 86 | write(fmt.rawHTML("</thead>")) |
paul@52 | 87 | |
paul@52 | 88 | write(fmt.rawHTML("<tbody>")) |
paul@52 | 89 | |
paul@53 | 90 | # For each key in the message, show whether it is already known to GPG, |
paul@53 | 91 | # the user of the key, and whether other known people have signed it. |
paul@53 | 92 | |
paul@52 | 93 | for key in gpg.getKeysFromString(self.raw): |
paul@52 | 94 | write(fmt.table_row(on=1)) |
paul@53 | 95 | |
paul@53 | 96 | # Known... |
paul@53 | 97 | |
paul@52 | 98 | write(fmt.table_cell(on=1)) |
paul@52 | 99 | try: |
paul@52 | 100 | gpg.listKeys(key["keyid"]) |
paul@52 | 101 | write(fmt.icon("(./)")) |
paul@52 | 102 | write(fmt.text(_("Known"))) |
paul@52 | 103 | except MoinMessageError: |
paul@52 | 104 | pass |
paul@52 | 105 | write(fmt.table_cell(on=0)) |
paul@53 | 106 | |
paul@53 | 107 | # Identity... |
paul@53 | 108 | |
paul@52 | 109 | write(fmt.table_cell(on=1)) |
paul@53 | 110 | write(fmt.text(key["userid"])); write(fmt.linebreak(0)) |
paul@53 | 111 | write(fmt.small(on=1)); write(fmt.text(key["fingerprint"])); write(fmt.small(on=0)) |
paul@52 | 112 | write(fmt.table_cell(on=0)) |
paul@53 | 113 | |
paul@53 | 114 | # Confirmed by... |
paul@53 | 115 | |
paul@52 | 116 | write(fmt.table_cell(on=1)) |
paul@53 | 117 | |
paul@53 | 118 | first = True |
paul@53 | 119 | |
paul@53 | 120 | for signature in key["signatures"]: |
paul@53 | 121 | |
paul@53 | 122 | # Skip unknown signers and self-signatures. |
paul@53 | 123 | |
paul@53 | 124 | signer = signature["userid"] |
paul@53 | 125 | if not signer: |
paul@53 | 126 | continue |
paul@53 | 127 | try: |
paul@53 | 128 | gpg.listKeys(signature["keyid"]) |
paul@53 | 129 | except MoinMessageError: |
paul@53 | 130 | continue |
paul@53 | 131 | |
paul@53 | 132 | if not first: |
paul@53 | 133 | write(fmt.linebreak(0)) |
paul@53 | 134 | write(fmt.text(signer)) |
paul@53 | 135 | first = False |
paul@53 | 136 | |
paul@52 | 137 | write(fmt.table_cell(on=0)) |
paul@52 | 138 | write(fmt.table_row(on=0)) |
paul@52 | 139 | |
paul@52 | 140 | write(fmt.rawHTML("</tbody></table>")) |
paul@52 | 141 | |
paul@52 | 142 | # Class methods. |
paul@52 | 143 | |
paul@52 | 144 | def getOutputTypes(self): |
paul@52 | 145 | return self.output_mimetypes |
paul@52 | 146 | |
paul@52 | 147 | getOutputTypes = classmethod(getOutputTypes) |
paul@52 | 148 | |
paul@52 | 149 | # vim: tabstop=4 expandtab shiftwidth=4 |