cq: Format with black and isort
This commit is contained in:
@@ -16,15 +16,14 @@
|
||||
|
||||
import logging
|
||||
|
||||
from nbxmpp.protocol import JID
|
||||
|
||||
import gpg
|
||||
from gpg.results import ImportResult
|
||||
from nbxmpp.protocol import JID
|
||||
|
||||
from openpgp.backend.util import parse_uid
|
||||
from openpgp.modules.util import DecryptionFailed
|
||||
|
||||
log = logging.getLogger('gajim.p.openpgp.gpgme')
|
||||
log = logging.getLogger("gajim.p.openpgp.gpgme")
|
||||
|
||||
|
||||
class KeyringItem:
|
||||
@@ -73,31 +72,33 @@ class GPGME:
|
||||
def __init__(self, jid, gnuhome):
|
||||
self._jid = jid
|
||||
self._context_args = {
|
||||
'home_dir': str(gnuhome),
|
||||
'offline': True,
|
||||
'armor': False,
|
||||
"home_dir": str(gnuhome),
|
||||
"offline": True,
|
||||
"armor": False,
|
||||
}
|
||||
|
||||
def generate_key(self):
|
||||
with gpg.Context(**self._context_args) as context:
|
||||
result = context.create_key(f'xmpp:{str(self._jid)}',
|
||||
algorithm='default',
|
||||
expires=False,
|
||||
passphrase=None,
|
||||
force=False)
|
||||
result = context.create_key(
|
||||
f"xmpp:{str(self._jid)}",
|
||||
algorithm="default",
|
||||
expires=False,
|
||||
passphrase=None,
|
||||
force=False,
|
||||
)
|
||||
|
||||
log.info('Generated new key: %s', result.fpr)
|
||||
log.info("Generated new key: %s", result.fpr)
|
||||
|
||||
def get_key(self, fingerprint):
|
||||
with gpg.Context(**self._context_args) as context:
|
||||
try:
|
||||
key = context.get_key(fingerprint)
|
||||
except gpg.errors.KeyNotFound as error:
|
||||
log.warning('key not found: %s', error.keystr)
|
||||
log.warning("key not found: %s", error.keystr)
|
||||
return
|
||||
|
||||
except Exception as error:
|
||||
log.warning('get_key() error: %s', error)
|
||||
log.warning("get_key() error: %s", error)
|
||||
return
|
||||
|
||||
return key
|
||||
@@ -121,7 +122,7 @@ class GPGME:
|
||||
for key in context.keylist():
|
||||
keyring_item = KeyringItem(key)
|
||||
if not keyring_item.is_xmpp_key:
|
||||
log.warning('Key not suited for xmpp: %s', key.fpr)
|
||||
log.warning("Key not suited for xmpp: %s", key.fpr)
|
||||
self.delete_key(keyring_item.fingerprint)
|
||||
continue
|
||||
|
||||
@@ -157,12 +158,12 @@ class GPGME:
|
||||
recipients.append(key)
|
||||
|
||||
if not recipients:
|
||||
return None, 'No keys found to encrypt to'
|
||||
return None, "No keys found to encrypt to"
|
||||
|
||||
with gpg.Context(**self._context_args) as context:
|
||||
result = context.encrypt(str(plaintext).encode(),
|
||||
recipients,
|
||||
always_trust=True)
|
||||
result = context.encrypt(
|
||||
str(plaintext).encode(), recipients, always_trust=True
|
||||
)
|
||||
|
||||
ciphertext, result, _sign_result = result
|
||||
return ciphertext, None
|
||||
@@ -172,7 +173,7 @@ class GPGME:
|
||||
try:
|
||||
result = context.decrypt(ciphertext)
|
||||
except Exception as error:
|
||||
raise DecryptionFailed('Decryption failed: %s' % error)
|
||||
raise DecryptionFailed("Decryption failed: %s" % error)
|
||||
|
||||
plaintext, result, verify_result = result
|
||||
plaintext = plaintext.decode()
|
||||
@@ -181,16 +182,16 @@ class GPGME:
|
||||
if not fingerprints or len(fingerprints) > 1:
|
||||
log.error(result)
|
||||
log.error(verify_result)
|
||||
raise DecryptionFailed('Verification failed')
|
||||
raise DecryptionFailed("Verification failed")
|
||||
|
||||
return plaintext, fingerprints[0]
|
||||
|
||||
def import_key(self, data, jid):
|
||||
log.info('Import key from %s', jid)
|
||||
log.info("Import key from %s", jid)
|
||||
with gpg.Context(**self._context_args) as context:
|
||||
result = context.key_import(data)
|
||||
if not isinstance(result, ImportResult) or result.imported != 1:
|
||||
log.error('Key import failed: %s', jid)
|
||||
log.error("Key import failed: %s", jid)
|
||||
log.error(result)
|
||||
return
|
||||
|
||||
@@ -198,7 +199,7 @@ class GPGME:
|
||||
key = self.get_key(fingerprint)
|
||||
item = KeyringItem(key)
|
||||
if not item.is_valid(jid):
|
||||
log.warning('Invalid key found')
|
||||
log.warning("Invalid key found")
|
||||
log.warning(key)
|
||||
self.delete_key(item.fingerprint)
|
||||
return
|
||||
@@ -206,7 +207,7 @@ class GPGME:
|
||||
return item
|
||||
|
||||
def delete_key(self, fingerprint):
|
||||
log.info('Delete Key: %s', fingerprint)
|
||||
log.info("Delete Key: %s", fingerprint)
|
||||
key = self.get_key(fingerprint)
|
||||
with gpg.Context(**self._context_args) as context:
|
||||
context.op_delete(key, True)
|
||||
|
||||
@@ -23,10 +23,9 @@ from nbxmpp.protocol import JID
|
||||
from openpgp.backend.util import parse_uid
|
||||
from openpgp.modules.util import DecryptionFailed
|
||||
|
||||
|
||||
log = logging.getLogger('gajim.p.openpgp.pygnupg')
|
||||
log = logging.getLogger("gajim.p.openpgp.pygnupg")
|
||||
if log.getEffectiveLevel() == logging.DEBUG:
|
||||
log = logging.getLogger('gnupg')
|
||||
log = logging.getLogger("gnupg")
|
||||
log.addHandler(logging.StreamHandler())
|
||||
log.setLevel(logging.DEBUG)
|
||||
|
||||
@@ -50,10 +49,10 @@ class KeyringItem:
|
||||
|
||||
@property
|
||||
def keyid(self) -> str:
|
||||
return self._key['keyid']
|
||||
return self._key["keyid"]
|
||||
|
||||
def _get_uid(self) -> str | None:
|
||||
for uid in self._key['uids']:
|
||||
for uid in self._key["uids"]:
|
||||
try:
|
||||
return parse_uid(uid)
|
||||
except Exception:
|
||||
@@ -61,7 +60,7 @@ class KeyringItem:
|
||||
|
||||
@property
|
||||
def fingerprint(self):
|
||||
return self._key['fingerprint']
|
||||
return self._key["fingerprint"]
|
||||
|
||||
@property
|
||||
def uid(self):
|
||||
@@ -79,28 +78,28 @@ class KeyringItem:
|
||||
|
||||
class PythonGnuPG(gnupg.GPG):
|
||||
def __init__(self, jid: str, gnupghome: Path) -> None:
|
||||
gnupg.GPG.__init__(self, gpgbinary='gpg', gnupghome=str(gnupghome))
|
||||
gnupg.GPG.__init__(self, gpgbinary="gpg", gnupghome=str(gnupghome))
|
||||
|
||||
self._jid = jid
|
||||
self._own_fingerprint = None
|
||||
|
||||
@staticmethod
|
||||
def _get_key_params(jid):
|
||||
'''
|
||||
"""
|
||||
Generate --gen-key input
|
||||
'''
|
||||
"""
|
||||
|
||||
params = {
|
||||
'Key-Type': 'RSA',
|
||||
'Key-Length': 2048,
|
||||
'Name-Real': 'xmpp:%s' % jid,
|
||||
"Key-Type": "RSA",
|
||||
"Key-Length": 2048,
|
||||
"Name-Real": "xmpp:%s" % jid,
|
||||
}
|
||||
|
||||
out = 'Key-Type: %s\n' % params.pop('Key-Type')
|
||||
out = "Key-Type: %s\n" % params.pop("Key-Type")
|
||||
for key, val in list(params.items()):
|
||||
out += '%s: %s\n' % (key, val)
|
||||
out += '%no-protection\n'
|
||||
out += '%commit\n'
|
||||
out += "%s: %s\n" % (key, val)
|
||||
out += "%no-protection\n"
|
||||
out += "%commit\n"
|
||||
return out
|
||||
|
||||
def generate_key(self):
|
||||
@@ -108,18 +107,20 @@ class PythonGnuPG(gnupg.GPG):
|
||||
|
||||
def encrypt(self, payload, keys):
|
||||
recipients = [key.fingerprint for key in keys]
|
||||
log.info('encrypt to:')
|
||||
log.info("encrypt to:")
|
||||
for fingerprint in recipients:
|
||||
log.info(fingerprint)
|
||||
|
||||
result = super().encrypt(str(payload).encode('utf8'),
|
||||
recipients,
|
||||
armor=False,
|
||||
sign=self._own_fingerprint,
|
||||
always_trust=True)
|
||||
result = super().encrypt(
|
||||
str(payload).encode("utf8"),
|
||||
recipients,
|
||||
armor=False,
|
||||
sign=self._own_fingerprint,
|
||||
always_trust=True,
|
||||
)
|
||||
|
||||
if result.ok:
|
||||
error = ''
|
||||
error = ""
|
||||
else:
|
||||
error = result.status
|
||||
|
||||
@@ -130,7 +131,7 @@ class PythonGnuPG(gnupg.GPG):
|
||||
if not result.ok:
|
||||
raise DecryptionFailed(result.status)
|
||||
|
||||
return result.data.decode('utf8'), result.fingerprint
|
||||
return result.data.decode("utf8"), result.fingerprint
|
||||
|
||||
def get_key(self, fingerprint):
|
||||
return super().list_keys(keys=[fingerprint])
|
||||
@@ -141,7 +142,7 @@ class PythonGnuPG(gnupg.GPG):
|
||||
for key in result:
|
||||
item = KeyringItem(key)
|
||||
if not item.is_xmpp_key:
|
||||
log.warning('Invalid key found, deleting key')
|
||||
log.warning("Invalid key found, deleting key")
|
||||
log.warning(key)
|
||||
self.delete_key(item.fingerprint)
|
||||
continue
|
||||
@@ -149,17 +150,17 @@ class PythonGnuPG(gnupg.GPG):
|
||||
return keys
|
||||
|
||||
def import_key(self, data, jid):
|
||||
log.info('Import key from %s', jid)
|
||||
log.info("Import key from %s", jid)
|
||||
result = super().import_keys(data)
|
||||
if not result:
|
||||
log.error('Could not import key')
|
||||
log.error("Could not import key")
|
||||
log.error(result)
|
||||
return
|
||||
|
||||
key = self.get_key(result.results[0]['fingerprint'])
|
||||
key = self.get_key(result.results[0]["fingerprint"])
|
||||
item = KeyringItem(key[0])
|
||||
if not item.is_valid(jid):
|
||||
log.warning('Invalid key found, deleting key')
|
||||
log.warning("Invalid key found, deleting key")
|
||||
log.warning(key)
|
||||
self.delete_key(item.fingerprint)
|
||||
return
|
||||
@@ -172,17 +173,16 @@ class PythonGnuPG(gnupg.GPG):
|
||||
return None, None
|
||||
|
||||
if len(result) > 1:
|
||||
log.error('More than one secret key found')
|
||||
log.error("More than one secret key found")
|
||||
return None, None
|
||||
|
||||
self._own_fingerprint = result[0]['fingerprint']
|
||||
return self._own_fingerprint, int(result[0]['date'])
|
||||
self._own_fingerprint = result[0]["fingerprint"]
|
||||
return self._own_fingerprint, int(result[0]["date"])
|
||||
|
||||
def export_key(self, fingerprint):
|
||||
key = super().export_keys(
|
||||
fingerprint, secret=False, armor=False, minimal=True)
|
||||
key = super().export_keys(fingerprint, secret=False, armor=False, minimal=True)
|
||||
return key
|
||||
|
||||
def delete_key(self, fingerprint):
|
||||
log.info('Delete Key: %s', fingerprint)
|
||||
log.info("Delete Key: %s", fingerprint)
|
||||
super().delete_keys(fingerprint)
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OpenPGP Gajim Plugin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sqlite3
|
||||
import logging
|
||||
import sqlite3
|
||||
from collections import namedtuple
|
||||
|
||||
log = logging.getLogger('gajim.p.openpgp.sql')
|
||||
log = logging.getLogger("gajim.p.openpgp.sql")
|
||||
|
||||
TABLE_LAYOUT = '''
|
||||
TABLE_LAYOUT = """
|
||||
CREATE TABLE contacts (
|
||||
jid TEXT,
|
||||
fingerprint TEXT,
|
||||
@@ -29,13 +29,14 @@ TABLE_LAYOUT = '''
|
||||
timestamp INTEGER,
|
||||
comment TEXT
|
||||
);
|
||||
CREATE UNIQUE INDEX jid_fingerprint ON contacts (jid, fingerprint);'''
|
||||
CREATE UNIQUE INDEX jid_fingerprint ON contacts (jid, fingerprint);"""
|
||||
|
||||
|
||||
class Storage:
|
||||
def __init__(self, folder_path):
|
||||
self._con = sqlite3.connect(str(folder_path / 'contacts.db'),
|
||||
detect_types=sqlite3.PARSE_COLNAMES)
|
||||
self._con = sqlite3.connect(
|
||||
str(folder_path / "contacts.db"), detect_types=sqlite3.PARSE_COLNAMES
|
||||
)
|
||||
|
||||
self._con.row_factory = self._namedtuple_factory
|
||||
self._create_database()
|
||||
@@ -51,11 +52,11 @@ class Storage:
|
||||
return named_row
|
||||
|
||||
def _user_version(self):
|
||||
return self._con.execute('PRAGMA user_version').fetchone()[0]
|
||||
return self._con.execute("PRAGMA user_version").fetchone()[0]
|
||||
|
||||
def _create_database(self):
|
||||
if not self._user_version():
|
||||
log.info('Create contacts.db')
|
||||
log.info("Create contacts.db")
|
||||
self._execute_query(TABLE_LAYOUT)
|
||||
|
||||
def _execute_query(self, query):
|
||||
@@ -64,41 +65,43 @@ class Storage:
|
||||
%s
|
||||
PRAGMA user_version=1;
|
||||
END TRANSACTION;
|
||||
""" % (query)
|
||||
""" % (
|
||||
query
|
||||
)
|
||||
self._con.executescript(transaction)
|
||||
|
||||
def _migrate_database(self):
|
||||
pass
|
||||
|
||||
def load_contacts(self):
|
||||
sql = '''SELECT jid as "jid [jid]",
|
||||
sql = """SELECT jid as "jid [jid]",
|
||||
fingerprint,
|
||||
active,
|
||||
trust,
|
||||
timestamp,
|
||||
comment
|
||||
FROM contacts'''
|
||||
FROM contacts"""
|
||||
|
||||
return self._con.execute(sql).fetchall()
|
||||
|
||||
def save_contact(self, db_values):
|
||||
sql = '''REPLACE INTO
|
||||
sql = """REPLACE INTO
|
||||
contacts(jid, fingerprint, active, trust, timestamp, comment)
|
||||
VALUES(?, ?, ?, ?, ?, ?)'''
|
||||
VALUES(?, ?, ?, ?, ?, ?)"""
|
||||
for values in db_values:
|
||||
log.info('Store key: %s', values)
|
||||
log.info("Store key: %s", values)
|
||||
self._con.execute(sql, values)
|
||||
self._con.commit()
|
||||
|
||||
def set_trust(self, jid, fingerprint, trust):
|
||||
sql = 'UPDATE contacts SET trust = ? WHERE jid = ? AND fingerprint = ?'
|
||||
log.info('Set Trust: %s %s %s', trust, jid, fingerprint)
|
||||
sql = "UPDATE contacts SET trust = ? WHERE jid = ? AND fingerprint = ?"
|
||||
log.info("Set Trust: %s %s %s", trust, jid, fingerprint)
|
||||
self._con.execute(sql, (trust, jid, fingerprint))
|
||||
self._con.commit()
|
||||
|
||||
def delete_key(self, jid, fingerprint):
|
||||
sql = 'DELETE from contacts WHERE jid = ? AND fingerprint = ?'
|
||||
log.info('Delete Key: %s %s', jid, fingerprint)
|
||||
sql = "DELETE from contacts WHERE jid = ? AND fingerprint = ?"
|
||||
log.info("Delete Key: %s %s", jid, fingerprint)
|
||||
self._con.execute(sql, (jid, fingerprint))
|
||||
self._con.commit()
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
def parse_uid(uid: str, compat=False) -> str:
|
||||
if uid.startswith('xmpp:'):
|
||||
if uid.startswith("xmpp:"):
|
||||
return uid[5:]
|
||||
|
||||
# Compat with uids of form "Name <xmpp:my@jid.com>"
|
||||
if compat and '<xmpp:' in uid and uid.endswith('>'):
|
||||
return uid[:-1].split('<xmpp:', maxsplit=1)[1]
|
||||
if compat and "<xmpp:" in uid and uid.endswith(">"):
|
||||
return uid[:-1].split("<xmpp:", maxsplit=1)[1]
|
||||
|
||||
raise ValueError('Uknown UID format: %s' % uid)
|
||||
raise ValueError("Uknown UID format: %s" % uid)
|
||||
|
||||
@@ -20,41 +20,31 @@ import time
|
||||
from gi.repository import Gtk
|
||||
|
||||
from gajim.common import app
|
||||
|
||||
from gajim.gtk.dialogs import ConfirmationDialog
|
||||
from gajim.gtk.dialogs import DialogButton
|
||||
from gajim.plugins.plugins_i18n import _
|
||||
|
||||
from openpgp.modules.util import Trust
|
||||
|
||||
log = logging.getLogger('gajim.p.openpgp.keydialog')
|
||||
log = logging.getLogger("gajim.p.openpgp.keydialog")
|
||||
|
||||
TRUST_DATA = {
|
||||
Trust.NOT_TRUSTED: ('dialog-error-symbolic',
|
||||
_('Not Trusted'),
|
||||
'error-color'),
|
||||
Trust.UNKNOWN: ('security-low-symbolic',
|
||||
_('Not Decided'),
|
||||
'warning-color'),
|
||||
Trust.BLIND: ('security-medium-symbolic',
|
||||
_('Blind Trust'),
|
||||
'encrypted-color'),
|
||||
Trust.VERIFIED: ('security-high-symbolic',
|
||||
_('Verified'),
|
||||
'encrypted-color')
|
||||
Trust.NOT_TRUSTED: ("dialog-error-symbolic", _("Not Trusted"), "error-color"),
|
||||
Trust.UNKNOWN: ("security-low-symbolic", _("Not Decided"), "warning-color"),
|
||||
Trust.BLIND: ("security-medium-symbolic", _("Blind Trust"), "encrypted-color"),
|
||||
Trust.VERIFIED: ("security-high-symbolic", _("Verified"), "encrypted-color"),
|
||||
}
|
||||
|
||||
|
||||
class KeyDialog(Gtk.Dialog):
|
||||
def __init__(self, account, jid, transient):
|
||||
super().__init__(title=_('Public Keys for %s') % jid,
|
||||
destroy_with_parent=True)
|
||||
super().__init__(title=_("Public Keys for %s") % jid, destroy_with_parent=True)
|
||||
|
||||
self.set_transient_for(transient)
|
||||
self.set_resizable(True)
|
||||
self.set_default_size(500, 300)
|
||||
|
||||
self.get_style_context().add_class('openpgp-key-dialog')
|
||||
self.get_style_context().add_class("openpgp-key-dialog")
|
||||
|
||||
self._client = app.get_client(account)
|
||||
|
||||
@@ -62,17 +52,15 @@ class KeyDialog(Gtk.Dialog):
|
||||
self._listbox.set_selection_mode(Gtk.SelectionMode.NONE)
|
||||
|
||||
self._scrolled = Gtk.ScrolledWindow()
|
||||
self._scrolled.set_policy(Gtk.PolicyType.NEVER,
|
||||
Gtk.PolicyType.AUTOMATIC)
|
||||
self._scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
|
||||
self._scrolled.add(self._listbox)
|
||||
|
||||
box = self.get_content_area()
|
||||
box.pack_start(self._scrolled, True, True, 0)
|
||||
|
||||
keys = self._client.get_module('OpenPGP').get_keys(
|
||||
jid, only_trusted=False)
|
||||
keys = self._client.get_module("OpenPGP").get_keys(jid, only_trusted=False)
|
||||
for key in keys:
|
||||
log.info('Load: %s', key.fingerprint)
|
||||
log.info("Load: %s", key.fingerprint)
|
||||
self._listbox.add(KeyRow(key))
|
||||
self.show_all()
|
||||
|
||||
@@ -92,11 +80,10 @@ class KeyRow(Gtk.ListBoxRow):
|
||||
box.add(self._trust_button)
|
||||
|
||||
label_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
fingerprint = Gtk.Label(
|
||||
label=self._format_fingerprint(key.fingerprint))
|
||||
fingerprint.get_style_context().add_class('openpgp-mono')
|
||||
fingerprint = Gtk.Label(label=self._format_fingerprint(key.fingerprint))
|
||||
fingerprint.get_style_context().add_class("openpgp-mono")
|
||||
if not key.active:
|
||||
fingerprint.get_style_context().add_class('openpgp-inactive-color')
|
||||
fingerprint.get_style_context().add_class("openpgp-inactive-color")
|
||||
fingerprint.set_selectable(True)
|
||||
fingerprint.set_halign(Gtk.Align.START)
|
||||
fingerprint.set_valign(Gtk.Align.START)
|
||||
@@ -105,9 +92,9 @@ class KeyRow(Gtk.ListBoxRow):
|
||||
|
||||
date = Gtk.Label(label=self._format_timestamp(key.timestamp))
|
||||
date.set_halign(Gtk.Align.START)
|
||||
date.get_style_context().add_class('openpgp-mono')
|
||||
date.get_style_context().add_class("openpgp-mono")
|
||||
if not key.active:
|
||||
date.get_style_context().add_class('openpgp-inactive-color')
|
||||
date.get_style_context().add_class("openpgp-inactive-color")
|
||||
label_box.add(date)
|
||||
|
||||
box.add(label_box)
|
||||
@@ -122,12 +109,12 @@ class KeyRow(Gtk.ListBoxRow):
|
||||
self.destroy()
|
||||
|
||||
ConfirmationDialog(
|
||||
_('Delete Public Key?'),
|
||||
_('This will permanently delete this public key'),
|
||||
[DialogButton.make('Cancel'),
|
||||
DialogButton.make('Remove',
|
||||
text=_('Delete'),
|
||||
callback=_remove)],
|
||||
_("Delete Public Key?"),
|
||||
_("This will permanently delete this public key"),
|
||||
[
|
||||
DialogButton.make("Cancel"),
|
||||
DialogButton.make("Remove", text=_("Delete"), callback=_remove),
|
||||
],
|
||||
).show()
|
||||
|
||||
def set_trust(self, trust):
|
||||
@@ -140,22 +127,21 @@ class KeyRow(Gtk.ListBoxRow):
|
||||
def _format_fingerprint(fingerprint):
|
||||
fplen = len(fingerprint)
|
||||
wordsize = fplen // 8
|
||||
buf = ''
|
||||
buf = ""
|
||||
for w in range(0, fplen, wordsize):
|
||||
buf += '{0} '.format(fingerprint[w:w + wordsize])
|
||||
buf += "{0} ".format(fingerprint[w : w + wordsize])
|
||||
return buf.rstrip()
|
||||
|
||||
@staticmethod
|
||||
def _format_timestamp(timestamp):
|
||||
return time.strftime('%Y-%m-%d %H:%M:%S',
|
||||
time.localtime(timestamp))
|
||||
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timestamp))
|
||||
|
||||
|
||||
class TrustButton(Gtk.MenuButton):
|
||||
def __init__(self, row):
|
||||
Gtk.MenuButton.__init__(self)
|
||||
self._row = row
|
||||
self._css_class = ''
|
||||
self._css_class = ""
|
||||
self.set_popover(TrustPopver(row))
|
||||
self.update()
|
||||
|
||||
@@ -167,8 +153,8 @@ class TrustButton(Gtk.MenuButton):
|
||||
image.get_style_context().remove_class(self._css_class)
|
||||
|
||||
if not self._row.key.active:
|
||||
css_class = 'openpgp-inactive-color'
|
||||
tooltip = '%s - %s' % (_('Inactive'), tooltip)
|
||||
css_class = "openpgp-inactive-color"
|
||||
tooltip = "%s - %s" % (_("Inactive"), tooltip)
|
||||
|
||||
image.get_style_context().add_class(css_class)
|
||||
self._css_class = css_class
|
||||
@@ -188,8 +174,8 @@ class TrustPopver(Gtk.Popover):
|
||||
self._listbox.add(DeleteOption())
|
||||
self.add(self._listbox)
|
||||
self._listbox.show_all()
|
||||
self._listbox.connect('row-activated', self._activated)
|
||||
self.get_style_context().add_class('openpgp-trust-popover')
|
||||
self._listbox.connect("row-activated", self._activated)
|
||||
self.get_style_context().add_class("openpgp-trust-popover")
|
||||
|
||||
def _activated(self, listbox, row):
|
||||
self.popdown()
|
||||
@@ -215,8 +201,7 @@ class MenuOption(Gtk.ListBoxRow):
|
||||
box = Gtk.Box()
|
||||
box.set_spacing(6)
|
||||
|
||||
image = Gtk.Image.new_from_icon_name(self.icon,
|
||||
Gtk.IconSize.MENU)
|
||||
image = Gtk.Image.new_from_icon_name(self.icon, Gtk.IconSize.MENU)
|
||||
label = Gtk.Label(label=self.label)
|
||||
image.get_style_context().add_class(self.color)
|
||||
|
||||
@@ -229,9 +214,9 @@ class MenuOption(Gtk.ListBoxRow):
|
||||
class VerifiedOption(MenuOption):
|
||||
|
||||
type_ = Trust.VERIFIED
|
||||
icon = 'security-high-symbolic'
|
||||
label = _('Verified')
|
||||
color = 'encrypted-color'
|
||||
icon = "security-high-symbolic"
|
||||
label = _("Verified")
|
||||
color = "encrypted-color"
|
||||
|
||||
def __init__(self):
|
||||
MenuOption.__init__(self)
|
||||
@@ -240,9 +225,9 @@ class VerifiedOption(MenuOption):
|
||||
class NotTrustedOption(MenuOption):
|
||||
|
||||
type_ = Trust.NOT_TRUSTED
|
||||
icon = 'dialog-error-symbolic'
|
||||
label = _('Not Trusted')
|
||||
color = 'error-color'
|
||||
icon = "dialog-error-symbolic"
|
||||
label = _("Not Trusted")
|
||||
color = "error-color"
|
||||
|
||||
def __init__(self):
|
||||
MenuOption.__init__(self)
|
||||
@@ -251,9 +236,9 @@ class NotTrustedOption(MenuOption):
|
||||
class DeleteOption(MenuOption):
|
||||
|
||||
type_ = None
|
||||
icon = 'user-trash-symbolic'
|
||||
label = _('Delete')
|
||||
color = ''
|
||||
icon = "user-trash-symbolic"
|
||||
label = _("Delete")
|
||||
color = ""
|
||||
|
||||
def __init__(self):
|
||||
MenuOption.__init__(self)
|
||||
|
||||
@@ -18,13 +18,13 @@ import logging
|
||||
import threading
|
||||
from enum import IntEnum
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GLib
|
||||
from gi.repository import Gtk
|
||||
|
||||
from gajim.common import app
|
||||
from gajim.plugins.plugins_i18n import _
|
||||
|
||||
log = logging.getLogger('gajim.p.openpgp.wizard')
|
||||
log = logging.getLogger("gajim.p.openpgp.wizard")
|
||||
|
||||
|
||||
class Page(IntEnum):
|
||||
@@ -51,7 +51,7 @@ class KeyWizard(Gtk.Assistant):
|
||||
self.set_position(Gtk.WindowPosition.CENTER)
|
||||
|
||||
self.set_default_size(600, 400)
|
||||
self.get_style_context().add_class('dialog-margin')
|
||||
self.get_style_context().add_class("dialog-margin")
|
||||
|
||||
self._add_page(WelcomePage())
|
||||
# self._add_page(BackupKeyPage())
|
||||
@@ -60,9 +60,9 @@ class KeyWizard(Gtk.Assistant):
|
||||
self._add_page(SuccessfulPage())
|
||||
self._add_page(ErrorPage())
|
||||
|
||||
self.connect('prepare', self._on_page_change)
|
||||
self.connect('cancel', self._on_cancel)
|
||||
self.connect('close', self._on_cancel)
|
||||
self.connect("prepare", self._on_page_change)
|
||||
self.connect("cancel", self._on_cancel)
|
||||
self.connect("close", self._on_cancel)
|
||||
|
||||
self._remove_sidebar()
|
||||
self.show_all()
|
||||
@@ -79,12 +79,12 @@ class KeyWizard(Gtk.Assistant):
|
||||
main_box.remove(sidebar)
|
||||
|
||||
def _activate_encryption(self):
|
||||
action = app.window.lookup_action('set-encryption')
|
||||
action.activate(GLib.Variant('s', self._plugin.encryption_name))
|
||||
action = app.window.lookup_action("set-encryption")
|
||||
action.activate(GLib.Variant("s", self._plugin.encryption_name))
|
||||
|
||||
def _on_page_change(self, assistant, page):
|
||||
if self.get_current_page() == Page.NEWKEY:
|
||||
if self._client.get_module('OpenPGP').secret_key_available:
|
||||
if self._client.get_module("OpenPGP").secret_key_available:
|
||||
self.set_current_page(Page.SUCCESS)
|
||||
else:
|
||||
page.generate()
|
||||
@@ -98,15 +98,14 @@ class KeyWizard(Gtk.Assistant):
|
||||
class WelcomePage(Gtk.Box):
|
||||
|
||||
type_ = Gtk.AssistantPageType.INTRO
|
||||
title = _('Welcome')
|
||||
title = _("Welcome")
|
||||
complete = True
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
||||
self.set_spacing(18)
|
||||
title_label = Gtk.Label(label=_('Setup OpenPGP'))
|
||||
text_label = Gtk.Label(
|
||||
label=_('Gajim will now try to setup OpenPGP for you'))
|
||||
title_label = Gtk.Label(label=_("Setup OpenPGP"))
|
||||
text_label = Gtk.Label(label=_("Gajim will now try to setup OpenPGP for you"))
|
||||
self.add(title_label)
|
||||
self.add(text_label)
|
||||
|
||||
@@ -114,7 +113,7 @@ class WelcomePage(Gtk.Box):
|
||||
class RequestPage(Gtk.Box):
|
||||
|
||||
type_ = Gtk.AssistantPageType.INTRO
|
||||
title = _('Request OpenPGP Key')
|
||||
title = _("Request OpenPGP Key")
|
||||
complete = False
|
||||
|
||||
def __init__(self):
|
||||
@@ -146,7 +145,7 @@ class RequestPage(Gtk.Box):
|
||||
class NewKeyPage(RequestPage):
|
||||
|
||||
type_ = Gtk.AssistantPageType.PROGRESS
|
||||
title = _('Generating new Key')
|
||||
title = _("Generating new Key")
|
||||
complete = False
|
||||
|
||||
def __init__(self, assistant, client):
|
||||
@@ -155,14 +154,14 @@ class NewKeyPage(RequestPage):
|
||||
self._client = client
|
||||
|
||||
def generate(self):
|
||||
log.info('Creating Key')
|
||||
log.info("Creating Key")
|
||||
thread = threading.Thread(target=self.worker)
|
||||
thread.start()
|
||||
|
||||
def worker(self):
|
||||
text = None
|
||||
try:
|
||||
self._client.get_module('OpenPGP').generate_key()
|
||||
self._client.get_module("OpenPGP").generate_key()
|
||||
except Exception as error:
|
||||
text = str(error)
|
||||
|
||||
@@ -170,9 +169,9 @@ class NewKeyPage(RequestPage):
|
||||
|
||||
def finished(self, error):
|
||||
if error is None:
|
||||
self._client.get_module('OpenPGP').get_own_key_details()
|
||||
self._client.get_module('OpenPGP').set_public_key()
|
||||
self._client.get_module('OpenPGP').request_keylist()
|
||||
self._client.get_module("OpenPGP").get_own_key_details()
|
||||
self._client.get_module("OpenPGP").set_public_key()
|
||||
self._client.get_module("OpenPGP").request_keylist()
|
||||
self._assistant.set_current_page(Page.SUCCESS)
|
||||
else:
|
||||
error_page = self._assistant.get_nth_page(Page.ERROR)
|
||||
@@ -199,7 +198,7 @@ class NewKeyPage(RequestPage):
|
||||
class SuccessfulPage(Gtk.Box):
|
||||
|
||||
type_ = Gtk.AssistantPageType.SUMMARY
|
||||
title = _('Setup successful')
|
||||
title = _("Setup successful")
|
||||
complete = True
|
||||
|
||||
def __init__(self):
|
||||
@@ -207,12 +206,13 @@ class SuccessfulPage(Gtk.Box):
|
||||
self.set_spacing(12)
|
||||
self.set_homogeneous(True)
|
||||
|
||||
icon = Gtk.Image.new_from_icon_name('object-select-symbolic',
|
||||
Gtk.IconSize.DIALOG)
|
||||
icon.get_style_context().add_class('success-color')
|
||||
icon = Gtk.Image.new_from_icon_name(
|
||||
"object-select-symbolic", Gtk.IconSize.DIALOG
|
||||
)
|
||||
icon.get_style_context().add_class("success-color")
|
||||
icon.set_valign(Gtk.Align.END)
|
||||
label = Gtk.Label(label=_('Setup successful'))
|
||||
label.get_style_context().add_class('bold16')
|
||||
label = Gtk.Label(label=_("Setup successful"))
|
||||
label.get_style_context().add_class("bold16")
|
||||
label.set_valign(Gtk.Align.START)
|
||||
|
||||
self.add(icon)
|
||||
@@ -222,7 +222,7 @@ class SuccessfulPage(Gtk.Box):
|
||||
class ErrorPage(Gtk.Box):
|
||||
|
||||
type_ = Gtk.AssistantPageType.SUMMARY
|
||||
title = _('Setup failed')
|
||||
title = _("Setup failed")
|
||||
complete = True
|
||||
|
||||
def __init__(self):
|
||||
@@ -230,12 +230,13 @@ class ErrorPage(Gtk.Box):
|
||||
self.set_spacing(12)
|
||||
self.set_homogeneous(True)
|
||||
|
||||
icon = Gtk.Image.new_from_icon_name('dialog-error-symbolic',
|
||||
Gtk.IconSize.DIALOG)
|
||||
icon.get_style_context().add_class('error-color')
|
||||
icon = Gtk.Image.new_from_icon_name(
|
||||
"dialog-error-symbolic", Gtk.IconSize.DIALOG
|
||||
)
|
||||
icon.get_style_context().add_class("error-color")
|
||||
icon.set_valign(Gtk.Align.END)
|
||||
self._label = Gtk.Label()
|
||||
self._label.get_style_context().add_class('bold16')
|
||||
self._label.get_style_context().add_class("bold16")
|
||||
self._label.set_valign(Gtk.Align.START)
|
||||
|
||||
self.add(icon)
|
||||
|
||||
@@ -18,13 +18,14 @@ import logging
|
||||
|
||||
from openpgp.modules.util import Trust
|
||||
|
||||
log = logging.getLogger('gajim.p.openpgp.store')
|
||||
log = logging.getLogger("gajim.p.openpgp.store")
|
||||
|
||||
|
||||
class KeyData:
|
||||
'''
|
||||
"""
|
||||
Holds all data related to a certain key
|
||||
'''
|
||||
"""
|
||||
|
||||
def __init__(self, contact_data):
|
||||
self._contact_data = contact_data
|
||||
self.fingerprint = None
|
||||
@@ -40,11 +41,8 @@ class KeyData:
|
||||
|
||||
@trust.setter
|
||||
def trust(self, value):
|
||||
if value not in (Trust.NOT_TRUSTED,
|
||||
Trust.UNKNOWN,
|
||||
Trust.BLIND,
|
||||
Trust.VERIFIED):
|
||||
raise ValueError('Trust value not allowed: %s' % value)
|
||||
if value not in (Trust.NOT_TRUSTED, Trust.UNKNOWN, Trust.BLIND, Trust.VERIFIED):
|
||||
raise ValueError("Trust value not allowed: %s" % value)
|
||||
self._trust = value
|
||||
self._contact_data.set_trust(self.fingerprint, self._trust)
|
||||
|
||||
@@ -72,9 +70,10 @@ class KeyData:
|
||||
|
||||
|
||||
class ContactData:
|
||||
'''
|
||||
"""
|
||||
Holds all data related to a contact
|
||||
'''
|
||||
"""
|
||||
|
||||
def __init__(self, jid, storage, pgp):
|
||||
self.jid = jid
|
||||
self._key_store = {}
|
||||
@@ -84,8 +83,8 @@ class ContactData:
|
||||
@property
|
||||
def userid(self):
|
||||
if self.jid is None:
|
||||
raise ValueError('JID not set')
|
||||
return 'xmpp:%s' % self.jid
|
||||
raise ValueError("JID not set")
|
||||
return "xmpp:%s" % self.jid
|
||||
|
||||
@property
|
||||
def default_trust(self):
|
||||
@@ -96,12 +95,14 @@ class ContactData:
|
||||
|
||||
def db_values(self):
|
||||
for key in self._key_store.values():
|
||||
yield (self.jid,
|
||||
key.fingerprint,
|
||||
key.active,
|
||||
key.trust,
|
||||
key.timestamp,
|
||||
key.comment)
|
||||
yield (
|
||||
self.jid,
|
||||
key.fingerprint,
|
||||
key.active,
|
||||
key.trust,
|
||||
key.timestamp,
|
||||
key.comment,
|
||||
)
|
||||
|
||||
def add_from_key(self, key):
|
||||
try:
|
||||
@@ -109,7 +110,7 @@ class ContactData:
|
||||
except KeyError:
|
||||
keydata = KeyData.from_key(self, key, self.default_trust)
|
||||
self._key_store[key.fingerprint] = keydata
|
||||
log.info('Add from key: %s %s', self.jid, keydata.fingerprint)
|
||||
log.info("Add from key: %s %s", self.jid, keydata.fingerprint)
|
||||
return keydata
|
||||
|
||||
def add_from_db(self, row):
|
||||
@@ -118,11 +119,11 @@ class ContactData:
|
||||
except KeyError:
|
||||
keydata = KeyData.from_row(self, row)
|
||||
self._key_store[row.fingerprint] = keydata
|
||||
log.info('Add from row: %s %s', self.jid, row.fingerprint)
|
||||
log.info("Add from row: %s %s", self.jid, row.fingerprint)
|
||||
return keydata
|
||||
|
||||
def process_keylist(self, keylist):
|
||||
log.info('Process keylist: %s %s', self.jid, keylist)
|
||||
log.info("Process keylist: %s %s", self.jid, keylist)
|
||||
|
||||
if keylist is None:
|
||||
for keydata in self._key_store.values():
|
||||
@@ -133,7 +134,7 @@ class ContactData:
|
||||
missing_pub_keys = []
|
||||
fingerprints = set([key.fingerprint for key in keylist])
|
||||
if fingerprints == self._key_store.keys():
|
||||
log.info('No updates found')
|
||||
log.info("No updates found")
|
||||
for key in self._key_store.values():
|
||||
if not key.has_pubkey:
|
||||
missing_pub_keys.append(key.fingerprint)
|
||||
@@ -159,18 +160,20 @@ class ContactData:
|
||||
try:
|
||||
keydata = self._key_store[fingerprint]
|
||||
except KeyError:
|
||||
log.warning('Set public key on unknown fingerprint: %s %s',
|
||||
self.jid, fingerprint)
|
||||
log.warning(
|
||||
"Set public key on unknown fingerprint: %s %s", self.jid, fingerprint
|
||||
)
|
||||
else:
|
||||
keydata.has_pubkey = True
|
||||
log.info('Set public key: %s %s', self.jid, fingerprint)
|
||||
log.info("Set public key: %s %s", self.jid, fingerprint)
|
||||
|
||||
def get_keys(self, only_trusted=True):
|
||||
keys = list(self._key_store.values())
|
||||
if not only_trusted:
|
||||
return keys
|
||||
return [k for k in keys if k.active and k.trust in (Trust.VERIFIED,
|
||||
Trust.BLIND)]
|
||||
return [
|
||||
k for k in keys if k.active and k.trust in (Trust.VERIFIED, Trust.BLIND)
|
||||
]
|
||||
|
||||
def get_key(self, fingerprint):
|
||||
return self._key_store.get(fingerprint, None)
|
||||
@@ -185,9 +188,10 @@ class ContactData:
|
||||
|
||||
|
||||
class PGPContacts:
|
||||
'''
|
||||
"""
|
||||
Holds all contacts available for PGP encryption
|
||||
'''
|
||||
"""
|
||||
|
||||
def __init__(self, pgp, storage):
|
||||
self._contacts = {}
|
||||
self._storage = storage
|
||||
@@ -196,20 +200,20 @@ class PGPContacts:
|
||||
self._load_from_keyring()
|
||||
|
||||
def _load_from_keyring(self):
|
||||
log.info('Load keys from keyring')
|
||||
log.info("Load keys from keyring")
|
||||
keyring = self._pgp.get_keys()
|
||||
for key in keyring:
|
||||
log.info('Found: %s %s', key.jid, key.fingerprint)
|
||||
log.info("Found: %s %s", key.jid, key.fingerprint)
|
||||
self.set_public_key(key.jid, key.fingerprint)
|
||||
|
||||
def _load_from_storage(self):
|
||||
log.info('Load contacts from storage')
|
||||
log.info("Load contacts from storage")
|
||||
rows = self._storage.load_contacts()
|
||||
if rows is None:
|
||||
return
|
||||
|
||||
for row in rows:
|
||||
log.info('Found: %s %s', row.jid, row.fingerprint)
|
||||
log.info("Found: %s %s", row.jid, row.fingerprint)
|
||||
try:
|
||||
contact_data = self._contacts[row.jid]
|
||||
except KeyError:
|
||||
@@ -235,7 +239,7 @@ class PGPContacts:
|
||||
try:
|
||||
contact_data = self._contacts[jid]
|
||||
except KeyError:
|
||||
log.warning('ContactData not found: %s %s', jid, fingerprint)
|
||||
log.warning("ContactData not found: %s %s", jid, fingerprint)
|
||||
else:
|
||||
contact_data.set_public_key(fingerprint)
|
||||
|
||||
|
||||
@@ -14,24 +14,24 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OpenPGP Gajim Plugin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from nbxmpp.namespaces import Namespace
|
||||
from nbxmpp import Node
|
||||
from nbxmpp import StanzaMalformed
|
||||
from nbxmpp.errors import MalformedStanzaError
|
||||
from nbxmpp.errors import StanzaError
|
||||
from nbxmpp.exceptions import StanzaDecrypted
|
||||
from nbxmpp.modules.openpgp import create_message_stanza
|
||||
from nbxmpp.modules.openpgp import create_signcrypt_node
|
||||
from nbxmpp.modules.openpgp import parse_signcrypt
|
||||
from nbxmpp.modules.openpgp import PGPKeyMetadata
|
||||
from nbxmpp.namespaces import Namespace
|
||||
from nbxmpp.structs import EncryptionData
|
||||
from nbxmpp.structs import MessageProperties
|
||||
from nbxmpp.structs import StanzaHandler
|
||||
from nbxmpp.errors import StanzaError
|
||||
from nbxmpp.errors import MalformedStanzaError
|
||||
from nbxmpp.modules.openpgp import PGPKeyMetadata
|
||||
from nbxmpp.modules.openpgp import parse_signcrypt
|
||||
from nbxmpp.modules.openpgp import create_signcrypt_node
|
||||
from nbxmpp.modules.openpgp import create_message_stanza
|
||||
|
||||
from gajim.common import app
|
||||
from gajim.common import configpaths
|
||||
@@ -40,22 +40,22 @@ from gajim.common.modules.base import BaseModule
|
||||
from gajim.common.modules.util import event_node
|
||||
from gajim.common.structs import OutgoingMessage
|
||||
|
||||
from openpgp.modules.util import ENCRYPTION_NAME
|
||||
from openpgp.modules.util import NOT_ENCRYPTED_TAGS
|
||||
from openpgp.modules.util import Key
|
||||
from openpgp.modules.util import Trust
|
||||
from openpgp.modules.util import DecryptionFailed
|
||||
from openpgp.modules.util import prepare_stanza
|
||||
from openpgp.modules.key_store import PGPContacts
|
||||
from openpgp.backend.sql import Storage
|
||||
from openpgp.modules.key_store import PGPContacts
|
||||
from openpgp.modules.util import DecryptionFailed
|
||||
from openpgp.modules.util import ENCRYPTION_NAME
|
||||
from openpgp.modules.util import Key
|
||||
from openpgp.modules.util import NOT_ENCRYPTED_TAGS
|
||||
from openpgp.modules.util import prepare_stanza
|
||||
from openpgp.modules.util import Trust
|
||||
|
||||
if sys.platform == 'win32':
|
||||
if sys.platform == "win32":
|
||||
from openpgp.backend.pygpg import PythonGnuPG as PGPBackend
|
||||
else:
|
||||
from openpgp.backend.gpgme import GPGME as PGPBackend
|
||||
|
||||
|
||||
log = logging.getLogger('gajim.p.openpgp')
|
||||
log = logging.getLogger("gajim.p.openpgp")
|
||||
|
||||
|
||||
# Module name
|
||||
@@ -65,24 +65,26 @@ zeroconf = False
|
||||
|
||||
class OpenPGP(BaseModule):
|
||||
|
||||
_nbxmpp_extends = 'OpenPGP'
|
||||
_nbxmpp_extends = "OpenPGP"
|
||||
_nbxmpp_methods = [
|
||||
'set_keylist',
|
||||
'request_keylist',
|
||||
'set_public_key',
|
||||
'request_public_key',
|
||||
'set_secret_key',
|
||||
'request_secret_key',
|
||||
"set_keylist",
|
||||
"request_keylist",
|
||||
"set_public_key",
|
||||
"request_public_key",
|
||||
"set_secret_key",
|
||||
"request_secret_key",
|
||||
]
|
||||
|
||||
def __init__(self, client):
|
||||
BaseModule.__init__(self, client)
|
||||
|
||||
self.handlers = [
|
||||
StanzaHandler(name='message',
|
||||
callback=self.decrypt_message,
|
||||
ns=Namespace.OPENPGP,
|
||||
priority=9),
|
||||
StanzaHandler(
|
||||
name="message",
|
||||
callback=self.decrypt_message,
|
||||
ns=Namespace.OPENPGP,
|
||||
priority=9,
|
||||
),
|
||||
]
|
||||
|
||||
self._register_pubsub_handler(self._keylist_notification_received)
|
||||
@@ -90,7 +92,7 @@ class OpenPGP(BaseModule):
|
||||
self.own_jid = self._client.get_own_jid()
|
||||
|
||||
own_bare_jid = self.own_jid.bare
|
||||
path = Path(configpaths.get('MY_DATA')) / 'openpgp' / own_bare_jid
|
||||
path = Path(configpaths.get("MY_DATA")) / "openpgp" / own_bare_jid
|
||||
if not path.exists():
|
||||
path.mkdir(mode=0o700, parents=True)
|
||||
|
||||
@@ -98,7 +100,7 @@ class OpenPGP(BaseModule):
|
||||
self._storage = Storage(path)
|
||||
self._contacts = PGPContacts(self._pgp, self._storage)
|
||||
self._fingerprint, self._date = self.get_own_key_details()
|
||||
log.info('Own Fingerprint at start: %s', self._fingerprint)
|
||||
log.info("Own Fingerprint at start: %s", self._fingerprint)
|
||||
|
||||
@property
|
||||
def secret_key_available(self):
|
||||
@@ -112,27 +114,22 @@ class OpenPGP(BaseModule):
|
||||
self._pgp.generate_key()
|
||||
|
||||
def set_public_key(self):
|
||||
log.info('%s => Publish public key', self._account)
|
||||
log.info("%s => Publish public key", self._account)
|
||||
key = self._pgp.export_key(self._fingerprint)
|
||||
self._nbxmpp('OpenPGP').set_public_key(
|
||||
key, self._fingerprint, self._date)
|
||||
self._nbxmpp("OpenPGP").set_public_key(key, self._fingerprint, self._date)
|
||||
|
||||
def request_public_key(self, jid, fingerprint):
|
||||
log.info('%s => Request public key %s - %s',
|
||||
self._account, fingerprint, jid)
|
||||
self._nbxmpp('OpenPGP').request_public_key(
|
||||
jid,
|
||||
fingerprint,
|
||||
callback=self._public_key_received,
|
||||
user_data=fingerprint)
|
||||
log.info("%s => Request public key %s - %s", self._account, fingerprint, jid)
|
||||
self._nbxmpp("OpenPGP").request_public_key(
|
||||
jid, fingerprint, callback=self._public_key_received, user_data=fingerprint
|
||||
)
|
||||
|
||||
def _public_key_received(self, task):
|
||||
fingerprint = task.get_user_data()
|
||||
try:
|
||||
result = task.finish()
|
||||
except (StanzaError, MalformedStanzaError) as error:
|
||||
log.error('%s => Public Key not found: %s',
|
||||
self._account, error)
|
||||
log.error("%s => Public Key not found: %s", self._account, error)
|
||||
return
|
||||
|
||||
imported_key = self._pgp.import_key(result.key, result.jid)
|
||||
@@ -142,8 +139,8 @@ class OpenPGP(BaseModule):
|
||||
def set_keylist(self, keylist=None):
|
||||
if keylist is None:
|
||||
keylist = [PGPKeyMetadata(None, self._fingerprint, self._date)]
|
||||
log.info('%s => Publish keylist', self._account)
|
||||
self._nbxmpp('OpenPGP').set_keylist(keylist)
|
||||
log.info("%s => Publish keylist", self._account)
|
||||
self._nbxmpp("OpenPGP").set_keylist(keylist)
|
||||
|
||||
@event_node(Namespace.OPENPGP_PK)
|
||||
def _keylist_notification_received(self, _con, _stanza, properties):
|
||||
@@ -157,46 +154,43 @@ class OpenPGP(BaseModule):
|
||||
def request_keylist(self, jid=None):
|
||||
if jid is None:
|
||||
jid = self.own_jid
|
||||
log.info('%s => Fetch keylist %s', self._account, jid)
|
||||
log.info("%s => Fetch keylist %s", self._account, jid)
|
||||
|
||||
self._nbxmpp('OpenPGP').request_keylist(
|
||||
jid,
|
||||
callback=self._keylist_received,
|
||||
user_data=jid)
|
||||
self._nbxmpp("OpenPGP").request_keylist(
|
||||
jid, callback=self._keylist_received, user_data=jid
|
||||
)
|
||||
|
||||
def _keylist_received(self, task):
|
||||
jid = task.get_user_data()
|
||||
try:
|
||||
keylist = task.finish()
|
||||
except (StanzaError, MalformedStanzaError) as error:
|
||||
log.error('%s => Keylist query failed: %s',
|
||||
self._account, error)
|
||||
log.error("%s => Keylist query failed: %s", self._account, error)
|
||||
if self.own_jid.bare_match(jid) and self._fingerprint is not None:
|
||||
self.set_keylist()
|
||||
return
|
||||
|
||||
log.info('Keylist received from %s', jid)
|
||||
log.info("Keylist received from %s", jid)
|
||||
self._process_keylist(keylist, jid)
|
||||
|
||||
def _process_keylist(self, keylist, from_jid):
|
||||
if not keylist:
|
||||
log.warning('%s => Empty keylist received from %s',
|
||||
self._account, from_jid)
|
||||
log.warning("%s => Empty keylist received from %s", self._account, from_jid)
|
||||
self._contacts.process_keylist(self.own_jid, keylist)
|
||||
if self.own_jid.bare_match(from_jid) and self._fingerprint is not None:
|
||||
self.set_keylist()
|
||||
return
|
||||
|
||||
if self.own_jid.bare_match(from_jid):
|
||||
log.info('Received own keylist')
|
||||
log.info("Received own keylist")
|
||||
for key in keylist:
|
||||
log.info(key.fingerprint)
|
||||
for key in keylist:
|
||||
# Check if own fingerprint is published
|
||||
if key.fingerprint == self._fingerprint:
|
||||
log.info('Own key found in keys list')
|
||||
log.info("Own key found in keys list")
|
||||
return
|
||||
log.info('Own key not published')
|
||||
log.info("Own key not published")
|
||||
if self._fingerprint is not None:
|
||||
keylist.append(Key(self._fingerprint, self._date))
|
||||
self.set_keylist(keylist)
|
||||
@@ -228,31 +222,29 @@ class OpenPGP(BaseModule):
|
||||
try:
|
||||
payload, recipients, _timestamp = parse_signcrypt(signcrypt)
|
||||
except StanzaMalformed as error:
|
||||
log.warning('Decryption failed: %s', error)
|
||||
log.warning("Decryption failed: %s", error)
|
||||
log.warning(payload)
|
||||
return
|
||||
|
||||
if not any(map(self.own_jid.bare_match, recipients)):
|
||||
log.warning('to attr not valid')
|
||||
log.warning("to attr not valid")
|
||||
log.warning(signcrypt)
|
||||
return
|
||||
|
||||
keys = self._contacts.get_keys(remote_jid)
|
||||
fingerprints = [key.fingerprint for key in keys]
|
||||
if fingerprint not in fingerprints:
|
||||
log.warning('Invalid fingerprint on message: %s', fingerprint)
|
||||
log.warning('Expected: %s', fingerprints)
|
||||
log.warning("Invalid fingerprint on message: %s", fingerprint)
|
||||
log.warning("Expected: %s", fingerprints)
|
||||
return
|
||||
|
||||
log.info('Received OpenPGP message from: %s', properties.jid)
|
||||
log.info("Received OpenPGP message from: %s", properties.jid)
|
||||
prepare_stanza(stanza, payload)
|
||||
|
||||
trust = self._contacts.get_trust(remote_jid, fingerprint)
|
||||
|
||||
properties.encrypted = EncryptionData(
|
||||
protocol=ENCRYPTION_NAME,
|
||||
key=fingerprint,
|
||||
trust=trust
|
||||
protocol=ENCRYPTION_NAME, key=fingerprint, trust=trust
|
||||
)
|
||||
|
||||
raise StanzaDecrypted
|
||||
@@ -262,39 +254,38 @@ class OpenPGP(BaseModule):
|
||||
|
||||
keys = self._contacts.get_keys(remote_jid)
|
||||
if not keys:
|
||||
log.error('Droping stanza to %s, because we have no key', remote_jid)
|
||||
log.error("Droping stanza to %s, because we have no key", remote_jid)
|
||||
return
|
||||
|
||||
keys += self._contacts.get_keys(self.own_jid)
|
||||
keys += [Key(self._fingerprint, None)]
|
||||
|
||||
payload = create_signcrypt_node(message.get_stanza(),
|
||||
[remote_jid],
|
||||
NOT_ENCRYPTED_TAGS)
|
||||
payload = create_signcrypt_node(
|
||||
message.get_stanza(), [remote_jid], NOT_ENCRYPTED_TAGS
|
||||
)
|
||||
|
||||
encrypted_payload, error = self._pgp.encrypt(payload, keys)
|
||||
if error:
|
||||
log.error('Error: %s', error)
|
||||
text = message.get_text(with_fallback=False) or ''
|
||||
log.error("Error: %s", error)
|
||||
text = message.get_text(with_fallback=False) or ""
|
||||
app.ged.raise_event(
|
||||
MessageNotSent(client=self._client,
|
||||
jid=str(remote_jid),
|
||||
message=text,
|
||||
error=error,
|
||||
time=time.time()))
|
||||
MessageNotSent(
|
||||
client=self._client,
|
||||
jid=str(remote_jid),
|
||||
message=text,
|
||||
error=error,
|
||||
time=time.time(),
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
create_message_stanza(
|
||||
message.get_stanza(),
|
||||
encrypted_payload,
|
||||
bool(message.get_text())
|
||||
message.get_stanza(), encrypted_payload, bool(message.get_text())
|
||||
)
|
||||
|
||||
message.set_encryption(
|
||||
EncryptionData(
|
||||
protocol=ENCRYPTION_NAME,
|
||||
key='Unknown',
|
||||
trust=Trust.VERIFIED
|
||||
protocol=ENCRYPTION_NAME, key="Unknown", trust=Trust.VERIFIED
|
||||
)
|
||||
)
|
||||
|
||||
@@ -302,12 +293,12 @@ class OpenPGP(BaseModule):
|
||||
|
||||
@staticmethod
|
||||
def print_msg_to_log(stanza):
|
||||
""" Prints a stanza in a fancy way to the log """
|
||||
log.debug('-'*15)
|
||||
stanzastr = '\n' + stanza.__str__(fancy=True)
|
||||
"""Prints a stanza in a fancy way to the log"""
|
||||
log.debug("-" * 15)
|
||||
stanzastr = "\n" + stanza.__str__(fancy=True)
|
||||
stanzastr = stanzastr[0:-1]
|
||||
log.debug(stanzastr)
|
||||
log.debug('-'*15)
|
||||
log.debug("-" * 15)
|
||||
|
||||
def get_keys(self, jid=None, only_trusted=True):
|
||||
if jid is None:
|
||||
@@ -324,4 +315,4 @@ class OpenPGP(BaseModule):
|
||||
|
||||
|
||||
def get_instance(*args, **kwargs):
|
||||
return OpenPGP(*args, **kwargs), 'OpenPGP'
|
||||
return OpenPGP(*args, **kwargs), "OpenPGP"
|
||||
|
||||
@@ -14,24 +14,23 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OpenPGP Gajim Plugin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from enum import IntEnum
|
||||
from collections import namedtuple
|
||||
from enum import IntEnum
|
||||
|
||||
from nbxmpp.namespaces import Namespace
|
||||
|
||||
|
||||
ENCRYPTION_NAME = 'OpenPGP'
|
||||
ENCRYPTION_NAME = "OpenPGP"
|
||||
|
||||
NOT_ENCRYPTED_TAGS = [
|
||||
('no-store', Namespace.HINTS),
|
||||
('store', Namespace.HINTS),
|
||||
('no-copy', Namespace.HINTS),
|
||||
('no-permanent-store', Namespace.HINTS),
|
||||
('origin-id', Namespace.SID),
|
||||
('thread', None)
|
||||
("no-store", Namespace.HINTS),
|
||||
("store", Namespace.HINTS),
|
||||
("no-copy", Namespace.HINTS),
|
||||
("no-permanent-store", Namespace.HINTS),
|
||||
("origin-id", Namespace.SID),
|
||||
("thread", None),
|
||||
]
|
||||
|
||||
Key = namedtuple('Key', 'fingerprint date')
|
||||
Key = namedtuple("Key", "fingerprint date")
|
||||
|
||||
|
||||
class Trust(IntEnum):
|
||||
@@ -42,8 +41,8 @@ class Trust(IntEnum):
|
||||
|
||||
|
||||
def prepare_stanza(stanza, payload):
|
||||
delete_nodes(stanza, 'openpgp', Namespace.OPENPGP)
|
||||
delete_nodes(stanza, 'body')
|
||||
delete_nodes(stanza, "openpgp", Namespace.OPENPGP)
|
||||
delete_nodes(stanza, "body")
|
||||
|
||||
nodes = [(node.getName(), node.getNamespace()) for node in payload]
|
||||
for name, namespace in nodes:
|
||||
@@ -56,7 +55,7 @@ def prepare_stanza(stanza, payload):
|
||||
def delete_nodes(stanza, name, namespace=None):
|
||||
attrs = None
|
||||
if namespace is not None:
|
||||
attrs = {'xmlns': Namespace.OPENPGP}
|
||||
attrs = {"xmlns": Namespace.OPENPGP}
|
||||
nodes = stanza.getTags(name, attrs)
|
||||
for node in nodes:
|
||||
stanza.delChild(node)
|
||||
|
||||
@@ -17,22 +17,21 @@
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from nbxmpp.namespaces import Namespace
|
||||
from gi.repository import Gtk
|
||||
from nbxmpp import JID
|
||||
from nbxmpp.namespaces import Namespace
|
||||
|
||||
from gajim.common import app
|
||||
from gajim.common import ged
|
||||
from gajim.common import configpaths
|
||||
from gajim.common import ged
|
||||
from gajim.common.const import CSSPriority
|
||||
|
||||
from gajim.gtk.dialogs import SimpleDialog
|
||||
|
||||
from gajim.plugins import GajimPlugin
|
||||
from gajim.plugins.plugins_i18n import _
|
||||
|
||||
from openpgp.modules.util import ENCRYPTION_NAME
|
||||
|
||||
try:
|
||||
from openpgp.modules import openpgp
|
||||
except (ImportError, OSError) as e:
|
||||
@@ -40,7 +39,7 @@ except (ImportError, OSError) as e:
|
||||
else:
|
||||
ERROR_MSG = None
|
||||
|
||||
log = logging.getLogger('gajim.p.openpgp')
|
||||
log = logging.getLogger("gajim.p.openpgp")
|
||||
|
||||
|
||||
class OpenPGPPlugin(GajimPlugin):
|
||||
@@ -52,23 +51,21 @@ class OpenPGPPlugin(GajimPlugin):
|
||||
return
|
||||
|
||||
self.events_handlers = {
|
||||
'signed-in': (ged.PRECORE, self.signed_in),
|
||||
}
|
||||
"signed-in": (ged.PRECORE, self.signed_in),
|
||||
}
|
||||
|
||||
self.modules = [openpgp]
|
||||
|
||||
self.encryption_name = ENCRYPTION_NAME
|
||||
self.config_dialog = None
|
||||
self.gui_extension_points = {
|
||||
'encrypt' + self.encryption_name: (self._encrypt_message, None),
|
||||
'send_message' + self.encryption_name: (
|
||||
self._before_sendmessage, None),
|
||||
'encryption_dialog' + self.encryption_name: (
|
||||
self.on_encryption_button_clicked, None),
|
||||
'encryption_state' + self.encryption_name: (
|
||||
self.encryption_state, None),
|
||||
'update_caps': (self._update_caps, None),
|
||||
}
|
||||
"encrypt" + self.encryption_name: (self._encrypt_message, None),
|
||||
"send_message" + self.encryption_name: (self._before_sendmessage, None),
|
||||
"encryption_dialog"
|
||||
+ self.encryption_name: (self.on_encryption_button_clicked, None),
|
||||
"encryption_state" + self.encryption_name: (self.encryption_state, None),
|
||||
"update_caps": (self._update_caps, None),
|
||||
}
|
||||
|
||||
self.connections = {}
|
||||
|
||||
@@ -80,74 +77,78 @@ class OpenPGPPlugin(GajimPlugin):
|
||||
self._load_css()
|
||||
|
||||
def _load_css(self):
|
||||
path = Path(__file__).parent / 'gtk' / 'style.css'
|
||||
path = Path(__file__).parent / "gtk" / "style.css"
|
||||
try:
|
||||
with path.open('r') as f:
|
||||
with path.open("r") as f:
|
||||
css = f.read()
|
||||
except Exception as exc:
|
||||
log.error('Error loading css: %s', exc)
|
||||
log.error("Error loading css: %s", exc)
|
||||
return
|
||||
|
||||
try:
|
||||
provider = Gtk.CssProvider()
|
||||
provider.load_from_data(bytes(css.encode('utf-8')))
|
||||
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
|
||||
provider,
|
||||
CSSPriority.DEFAULT_THEME)
|
||||
provider.load_from_data(bytes(css.encode("utf-8")))
|
||||
Gtk.StyleContext.add_provider_for_screen(
|
||||
Gdk.Screen.get_default(), provider, CSSPriority.DEFAULT_THEME
|
||||
)
|
||||
except Exception:
|
||||
log.exception('Error loading application css')
|
||||
log.exception("Error loading application css")
|
||||
|
||||
@staticmethod
|
||||
def _create_paths():
|
||||
keyring_path = Path(configpaths.get('MY_DATA')) / 'openpgp'
|
||||
keyring_path = Path(configpaths.get("MY_DATA")) / "openpgp"
|
||||
if not keyring_path.exists():
|
||||
keyring_path.mkdir()
|
||||
|
||||
def signed_in(self, event):
|
||||
client = app.get_client(event.account)
|
||||
if client.get_module('OpenPGP').secret_key_available:
|
||||
log.info('%s => Publish keylist and public key after sign in',
|
||||
event.account)
|
||||
client.get_module('OpenPGP').request_keylist()
|
||||
client.get_module('OpenPGP').set_public_key()
|
||||
if client.get_module("OpenPGP").secret_key_available:
|
||||
log.info(
|
||||
"%s => Publish keylist and public key after sign in", event.account
|
||||
)
|
||||
client.get_module("OpenPGP").request_keylist()
|
||||
client.get_module("OpenPGP").set_public_key()
|
||||
|
||||
def activate(self):
|
||||
for account in app.settings.get_active_accounts():
|
||||
client = app.get_client(account)
|
||||
client.get_module('Caps').update_caps()
|
||||
client.get_module("Caps").update_caps()
|
||||
if app.account_is_connected(account):
|
||||
if client.get_module('OpenPGP').secret_key_available:
|
||||
log.info('%s => Publish keylist and public key '
|
||||
'after plugin activation', account)
|
||||
client.get_module('OpenPGP').request_keylist()
|
||||
client.get_module('OpenPGP').set_public_key()
|
||||
if client.get_module("OpenPGP").secret_key_available:
|
||||
log.info(
|
||||
"%s => Publish keylist and public key "
|
||||
"after plugin activation",
|
||||
account,
|
||||
)
|
||||
client.get_module("OpenPGP").request_keylist()
|
||||
client.get_module("OpenPGP").set_public_key()
|
||||
|
||||
def deactivate(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def _update_caps(_account, features):
|
||||
features.append('%s+notify' % Namespace.OPENPGP_PK)
|
||||
features.append("%s+notify" % Namespace.OPENPGP_PK)
|
||||
|
||||
def activate_encryption(self, chat_control):
|
||||
account = chat_control.account
|
||||
jid = chat_control.contact.jid
|
||||
client = app.get_client(account)
|
||||
if client.get_module('OpenPGP').secret_key_available:
|
||||
keys = client.get_module('OpenPGP').get_keys(
|
||||
jid, only_trusted=False)
|
||||
if client.get_module("OpenPGP").secret_key_available:
|
||||
keys = client.get_module("OpenPGP").get_keys(jid, only_trusted=False)
|
||||
if not keys:
|
||||
client.get_module('OpenPGP').request_keylist(JID.from_string(jid))
|
||||
client.get_module("OpenPGP").request_keylist(JID.from_string(jid))
|
||||
return True
|
||||
|
||||
from openpgp.gtk.wizard import KeyWizard
|
||||
|
||||
KeyWizard(self, account, chat_control)
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def encryption_state(_chat_control, state):
|
||||
state['authenticated'] = True
|
||||
state['visible'] = True
|
||||
state["authenticated"] = True
|
||||
state["visible"] = True
|
||||
|
||||
@staticmethod
|
||||
def on_encryption_button_clicked(chat_control):
|
||||
@@ -155,6 +156,7 @@ class OpenPGPPlugin(GajimPlugin):
|
||||
jid = chat_control.contact.jid
|
||||
|
||||
from openpgp.gtk.key import KeyDialog
|
||||
|
||||
KeyDialog(account, jid, app.window)
|
||||
|
||||
def _before_sendmessage(self, chat_control):
|
||||
@@ -162,20 +164,21 @@ class OpenPGPPlugin(GajimPlugin):
|
||||
jid = chat_control.contact.jid
|
||||
client = app.get_client(account)
|
||||
|
||||
if not client.get_module('OpenPGP').secret_key_available:
|
||||
if not client.get_module("OpenPGP").secret_key_available:
|
||||
from openpgp.gtk.wizard import KeyWizard
|
||||
|
||||
KeyWizard(self, account, chat_control)
|
||||
return
|
||||
|
||||
keys = client.get_module('OpenPGP').get_keys(jid)
|
||||
keys = client.get_module("OpenPGP").get_keys(jid)
|
||||
if not keys:
|
||||
SimpleDialog(
|
||||
_('Not Trusted'),
|
||||
_('There was no trusted and active key found'))
|
||||
_("Not Trusted"), _("There was no trusted and active key found")
|
||||
)
|
||||
chat_control.sendmessage = False
|
||||
|
||||
@staticmethod
|
||||
def _encrypt_message(client, obj, callback):
|
||||
if not client.get_module('OpenPGP').secret_key_available:
|
||||
if not client.get_module("OpenPGP").secret_key_available:
|
||||
return
|
||||
client.get_module('OpenPGP').encrypt_message(obj, callback)
|
||||
client.get_module("OpenPGP").encrypt_message(obj, callback)
|
||||
|
||||
Reference in New Issue
Block a user