# Copyright (C) 2019 Philipp Hörist # Copyright (C) 2019 Pavel R. # Copyright (C) 2022 Bohdan Horbeshko # This file is part of Gajim OTR Plugin. # # Gajim OTR Plugin is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # This software is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You can always obtain full license text at . # TODO: Fingerprints authentication GUI # TODO: SMP authentication GUI ERROR = None import logging from gajim.plugins import GajimPlugin from gajim.common import app from gajim.common.modules.contacts import BareContact from gi.repository import Gtk log = logging.getLogger('gajim.p.otr') try: from Cryptodome import * except ImportError as e: log.error(e) ERROR = 'Cryptodome is missing' if not ERROR: try: from . import module except Exception as error: log.error(error) ERROR = 'Error: %s' % error # ... class OTRPlugin(GajimPlugin): log = logging.getLogger('gajim.p.otr') # init plugin # def init(self): self.activatable = (not ERROR) if ERROR: self.available_text = (ERROR) return self.encryption_name = 'OTR' self.description = 'Provides Off-the-Record encryption' self.modules = [module] self.gui_extension_points = { 'encrypt' + self.encryption_name: (self._encrypt_message, None), 'message_actions_box': (self._message_actions_box_activate, self._message_actions_box_deactivate), 'switch_contact': (self._switch_contact, None), } self.switch = None self.switch_box = None @staticmethod def _get_box(): return app.window.get_chat_stack().get_message_action_box()._ui.box def activate(self): if app.window is not None: box = self._get_box() self._actions_hack_activate(box) def deactivate(self): box = self._get_box() self._actions_hack_deactivate(box) @staticmethod def get_otr(account): return app.connections[account].get_module('OTR') # activate encryption # @staticmethod def activate_encryption(ctl): return True # encrypt file (just return same file) @staticmethod def encrypt_file(file, account, callback): callback(file) def toggle_otr(self): print('toggle') # encrypt message # def _encrypt_message(self,con,event,callback): if not event.message or event.type_ != 'chat': return # drop empty and non-chat messages otr = self.get_otr(event.account) otr.otr.encrypt(event,callback) def _message_actions_box_activate(self, grid, box): if self.switch_box is None: self._actions_hack_activate(box) def _message_actions_box_deactivate(self, grid, box): if self.switch_box is not None: self._actions_hack_deactivate(box) def _actions_hack_activate(self, box): self.switch_box = Gtk.VBox() label = Gtk.Label(label='OTR') self.switch = Gtk.Switch() self.switch_box.pack_start(label, False, True, 0) self.switch_box.pack_start(self.switch, False, True, 0) self.switch_box.set_center_widget(self.switch) box.pack_start(self.switch_box, False, True, 0) self.switch.connect('activate', self.toggle_otr) if app.window is not None and hasattr(app.window, '_chat_page'): self._update_switch_visibility(app.window.get_chat_stack()._get_current_contact()) def _actions_hack_deactivate(self, box): box.remove(self.switch_box) self.switch_box = None self.switch = None def _update_switch_visibility(self, contact): if isinstance(contact, BareContact): otr = self.get_otr(contact._account) self.switch.set_active(contact.jid.new_as_bare() in otr.otr.ctxs) self.switch_box.show_all() else: self.switch_box.hide() def _switch_contact(self, contact): self._update_switch_visibility(contact)