Philipp Hörist pushed to branch master at gajim / gajim

Commits:

4 changed files:

Changes:

  • gajim/common/helpers.py
    ... ... @@ -48,7 +48,6 @@
    48 48
     import socket
    
    49 49
     import string
    
    50 50
     import sys
    
    51
    -import tempfile
    
    52 51
     import unicodedata
    
    53 52
     import weakref
    
    54 53
     import webbrowser
    
    ... ... @@ -83,6 +82,7 @@
    83 82
     from nbxmpp.structs import ProxyData
    
    84 83
     from packaging.requirements import Requirement
    
    85 84
     from packaging.version import Version as V
    
    85
    +from qrcode.image.pil import PilImage as QrcPilImage
    
    86 86
     
    
    87 87
     from gajim.common import app
    
    88 88
     from gajim.common import configpaths
    
    ... ... @@ -370,9 +370,6 @@ def get_contact_dict_for_account(account: str) -> dict[str, types.BareContact]:
    370 370
     
    
    371 371
     
    
    372 372
     def generate_qr_code(content: str) -> GdkPixbuf.Pixbuf | None:
    
    373
    -    image_path = os.path.join(
    
    374
    -        tempfile.gettempdir(),
    
    375
    -        f'{get_random_string()}.png')
    
    376 373
         qr = qrcode.QRCode(version=None,
    
    377 374
                            error_correction=qrcode.constants.ERROR_CORRECT_L,
    
    378 375
                            box_size=6,
    
    ... ... @@ -380,9 +377,11 @@ def generate_qr_code(content: str) -> GdkPixbuf.Pixbuf | None:
    380 377
         qr.add_data(content)
    
    381 378
         qr.make(fit=True)
    
    382 379
     
    
    383
    -    img = qr.make_image(fill_color='black', back_color='white')
    
    384
    -    img.save(image_path)
    
    385
    -    return GdkPixbuf.Pixbuf.new_from_file(image_path)
    
    380
    +    img = qr.make_image(image_factory=QrcPilImage).convert('RGB')
    
    381
    +    return GdkPixbuf.Pixbuf.new_from_bytes(
    
    382
    +        GLib.Bytes.new(img.tobytes()),
    
    383
    +        GdkPixbuf.Colorspace.RGB, False, 8,
    
    384
    +        img.width, img.height, img.width*3)
    
    386 385
     
    
    387 386
     
    
    388 387
     def play_sound(sound_event: str,
    

  • gajim/common/modules/omemo.py
    ... ... @@ -50,6 +50,7 @@
    50 50
     from omemo_dr.exceptions import KeyExchangeMessage
    
    51 51
     from omemo_dr.exceptions import MessageNotForDevice
    
    52 52
     from omemo_dr.exceptions import SelfMessage
    
    53
    +from omemo_dr.identitykey import IdentityKey
    
    53 54
     from omemo_dr.session_manager import OMEMOSessionManager
    
    54 55
     from omemo_dr.structs import OMEMOBundle
    
    55 56
     from omemo_dr.structs import OMEMOConfig
    
    ... ... @@ -61,6 +62,7 @@
    61 62
     from gajim.common.const import EncryptionData
    
    62 63
     from gajim.common.const import EncryptionInfoMsg
    
    63 64
     from gajim.common.const import Trust as GajimTrust
    
    65
    +from gajim.common.const import XmppUriQuery
    
    64 66
     from gajim.common.events import EncryptionInfo
    
    65 67
     from gajim.common.events import MucAdded
    
    66 68
     from gajim.common.events import MucDiscoUpdate
    
    ... ... @@ -92,6 +94,8 @@
    92 94
         ('origin-id', Namespace.SID),
    
    93 95
     ]
    
    94 96
     
    
    97
    +DeviceIdT = int
    
    98
    +IdentityT = tuple[DeviceIdT, IdentityKey]
    
    95 99
     
    
    96 100
     class OMEMO(BaseModule):
    
    97 101
     
    
    ... ... @@ -646,6 +650,25 @@ def _debug_print_stanza(self, stanza: Any) -> None:
    646 650
             stanzastr = stanzastr[0:-1]
    
    647 651
             self._log.debug(stanzastr)
    
    648 652
     
    
    653
    +    def compose_trust_uri(self, jid: JID) -> str:
    
    654
    +        verified_identities = [
    
    655
    +            (info.device_id, info.public_key)
    
    656
    +            for info in self._backend.get_identity_infos(
    
    657
    +                jid.bare, only_active=True, trust=OMEMOTrust.VERIFIED)
    
    658
    +        ]
    
    659
    +        if self._client.is_own_jid(jid):
    
    660
    +            verified_identities.insert(0, self._backend.get_our_identity())
    
    661
    +        return compose_trust_uri(jid, verified_identities)
    
    662
    +
    
    649 663
         def cleanup(self) -> None:
    
    650 664
             self._backend.destroy()
    
    651 665
             del self._backend
    
    666
    +
    
    667
    +
    
    668
    +def compose_trust_uri(jid: JID, devices: list[IdentityT]) -> str:
    
    669
    +    query = (
    
    670
    +        XmppUriQuery.MESSAGE.value,
    
    671
    +        [(f'omemo-sid-{sid}', ik.get_fingerprint()) for sid, ik in devices]
    
    672
    +    ) if devices else None
    
    673
    +    uri = jid.new_as_bare().to_iri(query)
    
    674
    +    return uri

  • gajim/gtk/chat_banner.py
    ... ... @@ -334,13 +334,13 @@ def _update_share_box(self) -> None:
    334 334
             self._ui.jid_label.set_text(str(self._contact.jid))
    
    335 335
     
    
    336 336
         def _get_share_uri(self) -> str:
    
    337
    +        assert self._client is not None
    
    337 338
             assert self._contact is not None
    
    338 339
             jid = self._contact.get_address()
    
    339 340
             if self._contact.is_groupchat:
    
    340 341
                 return jid.to_iri(XmppUriQuery.JOIN.value)
    
    341 342
             else:
    
    342
    -            # TODO: add verified OMEMO FPs
    
    343
    -            return jid.to_iri()
    
    343
    +            return self._client.get_module('OMEMO').compose_trust_uri(jid)
    
    344 344
     
    
    345 345
         def _on_share_clicked(self, _button: Gtk.Button) -> None:
    
    346 346
             # Generate QR code on demand (i.e. not when switching chats)
    

  • gajim/gtk/omemo_trust_manager.py
    ... ... @@ -25,22 +25,20 @@
    25 25
     import logging
    
    26 26
     import time
    
    27 27
     
    
    28
    -from gi.repository import GdkPixbuf
    
    29 28
     from gi.repository import Gtk
    
    30
    -from nbxmpp.protocol import JID
    
    31 29
     from omemo_dr.const import OMEMOTrust
    
    32 30
     from omemo_dr.structs import IdentityInfo
    
    33 31
     
    
    34 32
     from gajim.common import app
    
    35 33
     from gajim.common import ged
    
    36 34
     from gajim.common import types
    
    37
    -from gajim.common.const import XmppUriQuery
    
    38 35
     from gajim.common.events import AccountConnected
    
    39 36
     from gajim.common.events import AccountDisconnected
    
    40 37
     from gajim.common.ged import EventHelper
    
    41 38
     from gajim.common.helpers import generate_qr_code
    
    42 39
     from gajim.common.i18n import _
    
    43 40
     from gajim.common.modules.contacts import BareContact
    
    41
    +from gajim.common.modules.omemo import compose_trust_uri
    
    44 42
     
    
    45 43
     from .builder import get_builder
    
    46 44
     from .dialogs import ConfirmationDialog
    
    ... ... @@ -196,25 +194,12 @@ def _load_fingerprints(self, contact: types.ChatContactT) -> None:
    196 194
                     str(contact.jid)):
    
    197 195
                 self._ui.list.add(KeyRow(contact, identity_info))
    
    198 196
     
    
    199
    -    @staticmethod
    
    200
    -    def _get_qrcode(jid: JID,
    
    201
    -                    sid: int,
    
    202
    -                    fingerprint: str
    
    203
    -                    ) -> GdkPixbuf.Pixbuf | None:
    
    204
    -
    
    205
    -        qry = (XmppUriQuery.MESSAGE.value, [(f'omemo-sid-{sid}', fingerprint)])
    
    206
    -        ver_string = jid.new_as_bare().to_iri(qry)
    
    207
    -        log.debug('Verification String: %s', ver_string)
    
    208
    -        return generate_qr_code(ver_string)
    
    209
    -
    
    210 197
         def _load_qrcode(self) -> None:
    
    211
    -        client = app.get_client(self._account)
    
    212
    -        our_device_id, our_identity_key =\
    
    213
    -            self._omemo.backend.get_our_identity()
    
    214
    -        pixbuf = self._get_qrcode(client.get_own_jid(),
    
    215
    -                                  our_device_id,
    
    216
    -                                  our_identity_key.get_fingerprint())
    
    217
    -        self._ui.qr_code_image.set_from_pixbuf(pixbuf)
    
    198
    +        uri = compose_trust_uri(
    
    199
    +            app.get_client(self._account).get_own_jid(),
    
    200
    +            [self._omemo.backend.get_our_identity()])
    
    201
    +        log.debug('Trust URI: %s', uri)
    
    202
    +        self._ui.qr_code_image.set_from_pixbuf(generate_qr_code(uri))
    
    218 203
     
    
    219 204
         def _on_show_inactive(self, switch: Gtk.Switch, _param: Any) -> None:
    
    220 205
             self._ui.list.invalidate_filter()