Changeset 9771

Show
Ignore:
Timestamp:
06/08/08 17:27:05 (3 months ago)
Author:
js
Message:

Completely remove OTR.

Sorry, it just wasn't maintainable. The problem is the current libotr
API. I'm sick of working around the strange libotr API, sick of getting
HTML messages, sick of losing messages. The final argument for
completely removing it was that we can't get the message ID of a sent
msg anymore - which we need. I tried to work around this as well, but
there seems to be no way to wait for a signal in glib the way I would
need it for the workaround (I wanted to emit a signal in inject_message
and then wait for it after the call to otr_message_fragment_and_send
so the signal can pass us the message id). And the last reason is that
we're heading towards a new release and thus want to stabilize the code,
thus don't have time to work around even more libotr API strangeness.
I will give feedback to the libotr developers, who are currently
planning a new API, so that we can hopefully see OTR support once again
as soon as libotr4 is released.

Kjell already announced that he will continue his branch:
https://code.launchpad.net/~afflux/gajim/otr

I really hope the libotr devs will provide a sane API with libotr4 so
we can integrate OTR support again.

Oh, and I added one more try/except block for OS X.

Location:
trunk
Files:
2 removed
11 modified

Legend:

Unmodified
Added
Removed
  • trunk/data/glade/chat_control_popup_menu.glade

    r9649 r9771  
    7373    </child> 
    7474    <child> 
    75       <widget class="GtkMenuItem" id="otr_submenu"> 
    76         <property name="visible">True</property> 
    77         <property name="sensitive">False</property> 
    78         <property name="label" translatable="yes">Off-the-Record Encryption</property> 
    79         <property name="use_underline">True</property> 
    80         <child> 
    81           <widget class="GtkMenu" id="otr_submenu_menu"> 
    82             <child> 
    83               <widget class="GtkMenuItem" id="otr_settings_menuitem"> 
    84                 <property name="visible">True</property> 
    85                 <property name="label" translatable="yes">OTR settings / fingerprint</property> 
    86                 <property name="use_underline">True</property> 
    87                 <signal name="activate" handler="_on_otr_settings_menuitem_activate"/> 
    88               </widget> 
    89             </child> 
    90             <child> 
    91               <widget class="GtkMenuItem" id="smp_otr_menuitem"> 
    92                 <property name="visible">True</property> 
    93                 <property name="label" translatable="yes">Authenticate contact</property> 
    94                 <property name="use_underline">True</property> 
    95                 <signal name="activate" handler="_on_smp_otr_menuitem_activate"/> 
    96               </widget> 
    97             </child> 
    98             <child> 
    99               <widget class="GtkMenuItem" id="start_otr_menuitem"> 
    100                 <property name="visible">True</property> 
    101                 <property name="label" translatable="yes">Start / Refresh OTR</property> 
    102                 <property name="use_underline">True</property> 
    103                 <signal name="activate" handler="_on_start_otr_menuitem_activate"/> 
    104               </widget> 
    105             </child> 
    106             <child> 
    107               <widget class="GtkMenuItem" id="end_otr_menuitem"> 
    108                 <property name="visible">True</property> 
    109                 <property name="sensitive">False</property> 
    110                 <property name="label" translatable="yes">End OTR </property> 
    111                 <property name="use_underline">True</property> 
    112                 <signal name="activate" handler="_on_end_otr_menuitem_activate"/> 
    113               </widget> 
    114             </child> 
    115           </widget> 
    116         </child> 
    117       </widget> 
    118     </child> 
    119     <child> 
    12075      <widget class="GtkSeparatorMenuItem" id="separatormenuitem1"> 
    12176        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> 
  • trunk/src/chat_control.py

    r9761 r9771  
    11361136                self.status_tooltip = gtk.Tooltips() 
    11371137 
    1138                 if gajim.otr_module: 
    1139                         self.update_otr(True) 
    1140  
    11411138                self.update_ui() 
    11421139                # restore previous conversation 
     
    12071204                # The name banner is drawn here 
    12081205                ChatControlBase.update_ui(self) 
    1209  
    1210         def get_otr_status(self): 
    1211                 if not self.session: 
    1212                         return 0 
    1213  
    1214                 ctx = gajim.otr_module.otrl_context_find( 
    1215                         self.session.conn.otr_userstates, 
    1216                         self.contact.get_full_jid().encode(), 
    1217                         gajim.get_jid_from_account(self.account).encode(), 
    1218                         gajim.OTR_PROTO, 1, (gajim.otr_add_appdata, 
    1219                         self.account))[0] 
    1220  
    1221                 if ctx.msgstate == gajim.otr_module.OTRL_MSGSTATE_ENCRYPTED: 
    1222                         if ctx.active_fingerprint.trust: 
    1223                                 return 2 
    1224                         else: 
    1225                                 return 1 
    1226                 elif ctx.msgstate == gajim.otr_module.OTRL_MSGSTATE_FINISHED: 
    1227                         return 3 
    1228                 return 0 
    1229  
    1230         def update_otr(self, print_status=False): 
    1231                 otr_status_text = '' 
    1232                 otr_status = self.get_otr_status() 
    1233                 authenticated = False 
    1234  
    1235                 if otr_status > 0: 
    1236                         enc_status = True 
    1237                 else: 
    1238                         enc_status = False 
    1239  
    1240                 if otr_status == 1: 
    1241                         otr_status_text = u'*unauthenticated* secure OTR ' + \ 
    1242                                 u'connection' 
    1243                 elif otr_status == 2: 
    1244                         otr_status_text = u'authenticated secure OTR ' + \ 
    1245                                 u'connection' 
    1246                         authenticated = True 
    1247                 elif otr_status == 3: 
    1248                         otr_status_text = u'finished OTR connection' 
    1249  
    1250                 self._show_lock_image(enc_status, u'OTR', enc_status, True, 
    1251                         authenticated) 
    1252                 if print_status and otr_status_text != '': 
    1253                         self.print_conversation_line(u'[OTR] %s' % \ 
    1254                                 otr_status_text, 'status', '', None) 
    12551206 
    12561207        def _update_banner_state_image(self): 
     
    16591610                                # ESessions 
    16601611                                if not encrypted: 
    1661                                         msg = _('The following message was ' + \ 
    1662                                                 'NOT encrypted') 
    1663                                         ChatControlBase.print_conversation_line( 
    1664                                                 self, msg, 'status', '', tim) 
    1665                         elif gajim.otr_module and self.get_otr_status() > 0: 
    1666                                 # OTR 
    1667                                 # TODO: This is not shown when the window 
    1668                                 #       isn't open - needs fixing! 
    1669                                 if not encrypted and frm == '': 
    16701612                                        msg = _('The following message was ' + \ 
    16711613                                                'NOT encrypted') 
     
    17971739                toggle_gpg_menuitem = xml.get_widget('toggle_gpg_menuitem') 
    17981740                toggle_e2e_menuitem = xml.get_widget('toggle_e2e_menuitem') 
    1799                 otr_submenu = xml.get_widget('otr_submenu') 
    1800                 otr_settings_menuitem = xml.get_widget('otr_settings_menuitem') 
    1801                 smp_otr_menuitem = xml.get_widget('smp_otr_menuitem') 
    1802                 start_otr_menuitem = xml.get_widget('start_otr_menuitem') 
    1803                 end_otr_menuitem = xml.get_widget('end_otr_menuitem') 
    18041741                send_file_menuitem = xml.get_widget('send_file_menuitem') 
    18051742                information_menuitem = xml.get_widget('information_menuitem') 
     
    18941831                self.handlers[id] = convert_to_gc_menuitem 
    18951832 
    1896                 if gajim.otr_module: 
    1897                         otr_submenu.set_sensitive(True) 
    1898                         id = otr_settings_menuitem.connect('activate', 
    1899                                 self._on_otr_settings_menuitem_activate) 
    1900                         self.handlers[id] = otr_settings_menuitem 
    1901                         id = start_otr_menuitem.connect('activate', 
    1902                                 self._on_start_otr_menuitem_activate) 
    1903                         self.handlers[id] = start_otr_menuitem 
    1904                         id = end_otr_menuitem.connect('activate', 
    1905                                 self._on_end_otr_menuitem_activate) 
    1906                         self.handlers[id] = end_otr_menuitem 
    1907                         id = smp_otr_menuitem.connect('activate', 
    1908                                 self._on_smp_otr_menuitem_activate) 
    1909                         self.handlers[id] = smp_otr_menuitem 
    1910  
    1911                         ctx = gajim.otr_module.otrl_context_find(gajim.connections[self.account].otr_userstates, 
    1912                                 self.contact.get_full_jid().encode(), 
    1913                                 gajim.get_jid_from_account(self.account).encode(), gajim.OTR_PROTO, 1, 
    1914                                 (gajim.otr_add_appdata, self.account))[0] 
    1915                         # can end only when PLAINTEXT 
    1916                         end_otr_menuitem.set_sensitive(ctx.msgstate != 
    1917                                 gajim.otr_module.OTRL_MSGSTATE_PLAINTEXT) 
    1918                         # can SMP only when ENCRYPTED 
    1919                         smp_otr_menuitem.set_sensitive(ctx.msgstate == 
    1920                                 gajim.otr_module.OTRL_MSGSTATE_ENCRYPTED) 
    1921  
    19221833                menu.connect('selection-done', self.destroy_menu, 
    19231834                        send_file_menuitem, convert_to_gc_menuitem, 
     
    24072318                        self.session.negotiate_e2e(False) 
    24082319 
    2409         def _on_start_otr_menuitem_activate(self, widget): 
    2410                 # ?OTR? gets replaced with a better message internally in otrl_message_sending 
    2411                 MessageControl.send_message(self, u'?OTR?', type='chat') 
    2412         def _on_end_otr_menuitem_activate(self, widget): 
    2413                 fjid = self.contact.get_full_jid() 
    2414                 gajim.otr_module.otrl_message_disconnect( 
    2415                         self.session.conn.otr_userstates, (gajim.otr_ui_ops, 
    2416                         {'account': self.account, 'urgent': True}), 
    2417                         gajim.get_jid_from_account(self.account).encode(), 
    2418                         gajim.OTR_PROTO, fjid.encode()) 
    2419                 gajim.otr_ui_ops.gajim_log(_('Private conversation with ' \ 
    2420                         '%s lost.') % fjid, self.account, fjid.encode()) 
    2421                 self.update_otr() 
    2422         def _on_otr_settings_menuitem_activate(self, widget): 
    2423                 gajim.otr_windows.ContactOtrWindow(self.contact, self.account, self) 
    2424         def _on_smp_otr_menuitem_activate(self, widget): 
    2425                 ctx = gajim.otr_module.otrl_context_find(gajim.connections[self.account].otr_userstates, 
    2426                         self.contact.get_full_jid().encode(), 
    2427                         gajim.get_jid_from_account(self.account).encode(), gajim.OTR_PROTO, 1, 
    2428                         (gajim.otr_add_appdata, self.account))[0] 
    2429                 ctx.app_data.show(False) 
    2430  
    24312320        def got_connected(self): 
    24322321                ChatControlBase.got_connected(self) 
  • trunk/src/common/config.py

    r9764 r9771  
    314314                        'answer_receipt' : [opt_bool, True, _('Answer to receipt requests')], 
    315315                        'request_receipt' : [opt_bool, True, _('Sent receipt requests')], 
    316                         'otr_flags': [opt_int, 58 ], 
    317316                        'publish_mood': [opt_bool, True], 
    318317                        'publish_activity': [opt_bool, True], 
     
    373372                        'gpg_enabled': [ opt_bool, False, _('Is OpenPGP enabled for this contact?')], 
    374373                        'speller_language': [ opt_str, '', _('Language for which we want to check misspelled words')], 
    375                         'otr_flags': [opt_int, -1 ], 
    376374                }, {}), 
    377375                'rooms': ({ 
  • trunk/src/common/connection_handlers.py

    r9764 r9771  
    12191219                self.sessions = {} 
    12201220 
    1221                 if gajim.otr_module: 
    1222                         self.otr_userstates = gajim.otr_module.otrl_userstate_create() 
    1223  
    12241221        def _FeatureNegCB(self, con, stanza, session): 
    12251222                gajim.log.debug('FeatureNegCB') 
     
    17051702                        receipt.setThread(thread_id) 
    17061703                        con.send(receipt) 
    1707  
    1708                 # We don't trust libotr, that's why we only pass the message 
    1709                 # to it if necessary. otrl_proto_message_type does this check. 
    1710                 if gajim.otr_module and not xep_200_encrypted \ 
    1711                 and isinstance(msgtxt, unicode) and \ 
    1712                 gajim.otr_module.otrl_proto_message_type(msgtxt.encode()) != \ 
    1713                 gajim.otr_module.OTRL_MSGTYPE_NOTOTR: 
    1714                         # set to encrypted if it's really encrypted. 
    1715                         if gajim.otr_module.otrl_proto_message_type( 
    1716                         msgtxt.encode()) != \ 
    1717                         gajim.otr_module.OTRL_MSGTYPE_TAGGEDPLAINTEXT: 
    1718                                 encrypted = True 
    1719  
    1720                         # TODO: Do we really need .encode()? 
    1721                         # yes we do. OTR can't handle unicode. 
    1722                         otr_msg_tuple = \ 
    1723                                 gajim.otr_module.otrl_message_receiving( 
    1724                                 self.otr_userstates, 
    1725                                 (gajim.otr_ui_ops, {'account': self.name}), 
    1726                                 gajim.get_jid_from_account(self.name).encode(), 
    1727                                 gajim.OTR_PROTO, 
    1728                                 frm.encode(), 
    1729                                 msgtxt.encode(), 
    1730                                 (gajim.otr_add_appdata, self.name)) 
    1731                         msgtxt = unicode(otr_msg_tuple[1]) 
    1732  
    1733                         html_node = msg.getTag('html') 
    1734                         if html_node: 
    1735                                 msg.delChild(html_node) 
    1736                         msg.setBody(msgtxt) 
    1737  
    1738                         if gajim.otr_module.otrl_tlv_find( 
    1739                         otr_msg_tuple[2], 
    1740                         gajim.otr_module.OTRL_TLV_DISCONNECTED) != None: 
    1741                                 gajim.otr_ui_ops.gajim_log(_('%s ' \ 
    1742                                         'has ended his/her private ' \ 
    1743                                         'conversation with you. You should ' \ 
    1744                                         'do the same.') % frm, 
    1745                                         self.name, 
    1746                                         frm.encode()) 
    1747  
    1748                                 ctrls = gajim.interface.msg_win_mgr.get_chat_controls(jid, self.name) 
    1749                                 for ctrl in ctrls: 
    1750                                         ctrl.update_otr() 
    1751  
    1752                         ctx = gajim.otr_module. \ 
    1753                                 otrl_context_find( 
    1754                                 self.otr_userstates, 
    1755                                 frm.encode(), 
    1756                                 gajim.get_jid_from_account( 
    1757                                 self.name).encode(), 
    1758                                 gajim.OTR_PROTO, 1, 
    1759                                 (gajim.otr_add_appdata, 
    1760                                 self.name))[0] 
    1761                         tlvs = otr_msg_tuple[2] 
    1762                         ctx.app_data.handle_tlv(tlvs) 
    1763  
    1764                         if msgtxt == '': 
    1765                                 return 
    1766                 elif msgtxt != None and msgtxt != '': 
    1767                         gajim.otr_dont_append_tag[frm] = True 
    1768  
    1769                         # We're also here if we just don't 
    1770                         # support OTR. Thus, we should strip 
    1771                         # the tags from plaintext messages 
    1772                         # since they look ugly. 
    1773                         msgtxt = msgtxt.replace('\x20\x09\x20' \ 
    1774                                 '\x20\x09\x09\x09\x09\x20\x09' \ 
    1775                                 '\x20\x09\x20\x09\x20\x20', '') 
    1776                         msgtxt = msgtxt.replace('\x20\x09\x20' \ 
    1777                                 '\x09\x20\x20\x09\x20', '') 
    1778                         msgtxt = msgtxt.replace('\x20\x20\x09' \ 
    1779                                 '\x09\x20\x20\x09\x20', '') 
    17801704 
    17811705                if mtype != 'groupchat': 
  • trunk/src/common/connection.py

    r9763 r9771  
    897897                self.connect_and_auth() 
    898898 
    899                 if gajim.otr_module: 
    900                         try: 
    901                                 gajim.otr_module.otrl_privkey_read(self.otr_userstates, 
    902                                         os.path.join(gajim.gajimpaths.root, 
    903                                         '%s.key' % self.name).encode()) 
    904                                 gajim.otr_module.otrl_privkey_read_fingerprints( 
    905                                         self.otr_userstates, os.path.join( 
    906                                         gajim.gajimpaths.root, '%s.fpr' % 
    907                                         self.name).encode(), 
    908                                         (gajim.otr_add_appdata, self.name)) 
    909                         except Exception, e: 
    910                                 if not hasattr(e, 'os_errno') or e.os_errno != 2: 
    911                                         raise 
    912  
    913899        def _init_roster(self, con): 
    914900                self.connection = con 
  • trunk/src/common/gajim.py

    r9699 r9771  
    165165        if system('gpg -h >/dev/null 2>&1'): 
    166166                HAVE_GPG = False 
    167  
    168 OTR_PROTO = "xmpp" 
    169 otr_userstates = {} 
    170 otr_policy = {} 
    171  
    172 # list of (full) jids not to attempt OTR with 
    173 otr_dont_append_tag = {} 
    174167 
    175168gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'} 
  • trunk/src/features_window.py

    r9661 r9771  
    100100                                _('Requires python-crypto.'), 
    101101                                _('Requires python-crypto.')), 
    102                         _('Off the Record Encryption'): (self.otr_available, 
    103                                 _('Encrypting chatmessages in a way that even works through gateways.'), 
    104                                 _('Requires pyotr and libotr (see http://trac.gajim.org/wiki/OTR).'), 
    105                                 _('Requires pyotr and libotr (see http://trac.gajim.org/wiki/OTR).')), 
    106102                        _('RST Generator'): (self.docutils_available, 
    107103                                _('Generate XHTML output from RST code (see http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html).'), 
     
    313309                return gajim.HAVE_PYCRYPTO 
    314310 
    315         def otr_available(self): 
    316                 if gajim.otr_module: 
    317                         return True 
    318                 return False 
    319  
    320311        def docutils_available(self): 
    321312                try: 
  • trunk/src/gajim.py

    r9768 r9771  
    266266from common import optparser 
    267267from common import dataforms 
    268  
    269 from common.xmpp import Message as XmppMessage 
    270  
    271 try: 
    272         import otr, otr_windows 
    273         gajim.otr_module = otr 
    274         gajim.otr_windows = otr_windows 
    275 except ImportError: 
    276         gajim.otr_module = None 
    277         gajim.otr_windows = None 
    278  
    279 def add_appdata(data, context): 
    280         account = data 
    281         context.app_data = otr_windows.ContactOtrSMPWindow( 
    282                 unicode(context.username), account) 
    283  
    284 gajim.otr_add_appdata = add_appdata 
    285  
    286 def otr_dialog_destroy(widget, *args, **kwargs): 
    287         widget.destroy() 
    288  
    289 class OtrlMessageAppOps: 
    290         def gajim_log(self, msg, account, fjid, no_print=False): 
    291                 if not isinstance(fjid, unicode): 
    292                         fjid = unicode(fjid) 
    293                 if not isinstance(account, unicode): 
    294                         account = unicode(account) 
    295                 resource=gajim.get_resource_from_jid(fjid) 
    296                 tim = time.localtime() 
    297  
    298                 if not no_print: 
    299                         ctrl = self.get_control(fjid, account) 
    300                         if ctrl: 
    301                                 ctrl.print_conversation_line(u'[OTR] %s' % \ 
    302                                         msg, 'status', '', None) 
    303                 id = gajim.logger.write('chat_msg_recv', fjid, 
    304                         message='[OTR: %s]' % msg, tim=tim) 
    305                 # gajim.logger.write() only marks a message as unread 
    306                 # (and so only returns an id) when fjid is a real contact 
    307                 # (NOT if it's a GC private chat) 
    308                 if id: 
    309                         gajim.logger.set_read_messages([id]) 
    310  
    311         def get_control(self, fjid, account): 
    312                 # first try to get the window with the full jid 
    313                 ctrls = gajim.interface.msg_win_mgr.get_chat_controls(fjid, account) 
    314                 if ctrls: 
    315                         # got one, be happy 
    316                         return ctrls[0] 
    317  
    318                 # otherwise try without the resource 
    319                 ctrls = gajim.interface.msg_win_mgr.get_chat_controls( 
    320                         gajim.get_jid_without_resource(fjid), account) 
    321                 # but only use it when it is not a GC window 
    322                 if ctrls and ctrls[0].TYPE_ID == message_control.TYPE_CHAT: 
    323                         return ctrls[0] 
    324  
    325         def policy(self, opdata=None, context=None): 
    326                 policy = gajim.config.get_per('contacts', context.username, 
    327                         "otr_flags") 
    328                 if policy <= 0: 
    329                         policy = gajim.config.get_per('contacts', 
    330                                 gajim.get_jid_without_resource( 
    331                                 context.username), 'otr_flags') 
    332                 if policy <= 0: 
    333                         policy = gajim.config.get_per('accounts', 
    334                                 opdata['account'], 'otr_flags') 
    335                 return policy 
    336  
    337         def create_privkey(self, opdata='', accountname='', protocol=''): 
    338                 dialog = gtk.Dialog( 
    339                         title   = _('Generating...'), 
    340                         parent  = gajim.interface.roster.window, 
    341                         flags   = gtk.DIALOG_MODAL, 
    342                         buttons = (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) 
    343                 permlabel = gtk.Label(_('Generating a private key for %s...') \ 
    344                         % accountname) 
    345                 permlabel.set_padding(20, 20) 
    346                 dialog.set_response_sensitive(gtk.RESPONSE_CLOSE, False) 
    347                 dialog.connect('destroy', otr_dialog_destroy) 
    348                 dialog.connect('response', otr_dialog_destroy) 
    349                 dialog.vbox.pack_start(permlabel) 
    350                 dialog.get_root_window().raise_() 
    351                 dialog.show_all() 
    352                 dialog.map() 
    353                 for c in dialog.get_children(): 
    354                         c.show_now() 
    355                         c.map() 
    356  
    357                 while gtk.events_pending(): 
    358                         gtk.main_iteration(block = False) 
    359  
    360                 otr.otrl_privkey_generate( 
    361                         gajim.connections[opdata['account']].otr_userstates, 
    362                         os.path.join(gajimpaths.root, 
    363                         '%s.key' % opdata['account']).encode(), 
    364                         accountname, gajim.OTR_PROTO) 
    365                 permlabel.set_text(_('Generating a private key for %s...\n' \ 
    366                         'done.') % accountname) 
    367                 dialog.set_response_sensitive(gtk.RESPONSE_CLOSE, True) 
    368  
    369         def is_logged_in(self, opdata={}, accountname='', protocol='', 
    370         recipient=""): 
    371                 contact = gajim.contacts.get_contact_from_full_jid( 
    372                         opdata['account'], recipient) 
    373                 if contact: 
    374                         return contact.show \ 
    375                                 in ['dnd', 'xa', 'chat', 'online', 'away', 
    376                                 'invisible'] 
    377                 return 0 
    378  
    379         def inject_message(self, opdata=None, accountname='', protocol='', 
    380         recipient='', message=''): 
    381                 msg_type = otr.otrl_proto_message_type(message) 
    382  
    383                 if 'kwargs' not in opdata or 'urgent' in opdata: 
    384                         # don't use send_message here to have the message 
    385                         # sent immediatly. This results in being able to 
    386                         # disconnect from OTR sessions before quitting 
    387                         stanza = XmppMessage(to = recipient, 
    388                                 body = message, typ='chat') 
    389                         gajim.connections[opdata['account']].connection. \ 
    390                                 send(stanza, now = True) 
    391                         return 
    392  
    393                 if msg_type == otr.OTRL_MSGTYPE_QUERY: 
    394                         # split away XHTML-contaminated explanatory message 
    395                         message = unicode(message.splitlines()[0]) 
    396                         message += _(u'\nThis user has requested an ' \ 
    397                                 'Off-the-Record private conversation. ' \ 
    398                                 'However, you do not have a plugin to ' \ 
    399                                 'support that.\n' \ 
    400                                 'See http://otr.cypherpunks.ca/ for more ' \ 
    401                                 'information.') 
    402  
    403                         gajim.connections[opdata['account']].connection.send( 
    404                                 common.xmpp.Message(to = recipient, 
    405                                 body = message, typ = 'chat')) 
    406                         return 
    407  
    408                 gajim.connections[opdata['account']].send_message(recipient, 
    409                         message, **opdata['kwargs']) 
    410  
    411         def notify(sef, opdata=None, username='', **kwargs): 
    412                 self.gajim_log('Notify: ' + str(kwargs), opdata['account'],  
    413                         username) 
    414  
    415         def display_otr_message(self, opdata=None, username="", msg="", **kwargs): 
    416                 self.gajim_log('OTR Message: ' + msg, opdata['account'], 
    417                         username) 
    418                 return 0 
    419  
    420         def update_context_list(self, **kwargs): 
    421                 # FIXME stub FIXME # 
    422                 pass 
    423  
    424         def protocol_name(self, opdata=None, protocol=""): 
    425                 return 'XMPP' 
    426  
    427         def new_fingerprint(self, opdata=None, username='', fingerprint='', 
    428         **kwargs): 
    429                 self.gajim_log('New fingerprint for %s: %s' % (username, 
    430                         otr.otrl_privkey_hash_to_human(fingerprint)), 
    431                         opdata['account'], username) 
    432  
    433         def write_fingerprints(self, opdata=''): 
    434                 otr.otrl_privkey_write_fingerprints( 
    435                         gajim.connections[opdata['account']].otr_userstates, 
    436                         os.path.join(gajimpaths.root, '%s.fpr' % \ 
    437                         opdata['account']).encode()) 
    438  
    439         def gone_secure(self, opdata='', context=None): 
    440                 trust = context.active_fingerprint.trust \ 
    441                         and 'verified' or 'unverified' 
    442                 self.gajim_log('%s secured OTR connection started' % trust, 
    443                         opdata['account'], context.username, no_print = True) 
    444  
    445                 ctrl = self.get_control(context.username, opdata['account']) 
    446                 if ctrl: 
    447                         ctrl.update_otr(True) 
    448  
    449         def gone_insecure(self, opdata=''