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.
This commit is contained in:
js 2008-06-08 15:27:05 +00:00
parent 0d645437d8
commit c2eb4b5a9f
13 changed files with 4 additions and 1205 deletions

View File

@ -71,51 +71,6 @@
<signal name="activate" handler="_on_toggle_e2e_menuitem_activate"/>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="otr_submenu">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="label" translatable="yes">Off-the-Record Encryption</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="otr_submenu_menu">
<child>
<widget class="GtkMenuItem" id="otr_settings_menuitem">
<property name="visible">True</property>
<property name="label" translatable="yes">OTR settings / fingerprint</property>
<property name="use_underline">True</property>
<signal name="activate" handler="_on_otr_settings_menuitem_activate"/>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="smp_otr_menuitem">
<property name="visible">True</property>
<property name="label" translatable="yes">Authenticate contact</property>
<property name="use_underline">True</property>
<signal name="activate" handler="_on_smp_otr_menuitem_activate"/>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="start_otr_menuitem">
<property name="visible">True</property>
<property name="label" translatable="yes">Start / Refresh OTR</property>
<property name="use_underline">True</property>
<signal name="activate" handler="_on_start_otr_menuitem_activate"/>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="end_otr_menuitem">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="label" translatable="yes">End OTR </property>
<property name="use_underline">True</property>
<signal name="activate" handler="_on_end_otr_menuitem_activate"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>

View File

@ -1,322 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.2 on Wed Mar 26 13:56:40 2008 -->
<glade-interface>
<widget class="GtkWindow" id="otr_settings_window">
<property name="resizable">False</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<child>
<widget class="GtkNotebook" id="notebook1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkVBox" id="otr_fp_vbox">
<property name="visible">True</property>
<property name="border_width">5</property>
<property name="spacing">5</property>
<property name="homogeneous">True</property>
<child>
<widget class="GtkLabel" id="our_fp_label">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Your fingerprint:
&lt;span weight="bold" face="monospace"&gt;01234567 89ABCDEF 01234567 89ABCDEF 01234567&lt;/span&gt;</property>
<property name="use_markup">True</property>
</widget>
</child>
<child>
<widget class="GtkLabel" id="their_fp_label">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Purported fingerprint for asdfasdf@xyzxyzxyz.de:
&lt;span weight="bold" face="monospace"&gt;01234567 89ABCDEF 01234567 89ABCDEF 01234567&lt;/span&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<child>
<widget class="GtkComboBox" id="verified_combobox">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="active">1</property>
<property name="items">I have NOT
I have</property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="xalign">0.20000000298023224</property>
<property name="label" translatable="yes">verified that the purported fingerprint is in fact the correct fingerprint for that contact.</property>
<property name="wrap">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Authentication</property>
</widget>
<packing>
<property name="type">tab</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<widget class="GtkFrame" id="frame2">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<child>
<widget class="GtkVBox" id="otr_settings_vbox">
<property name="visible">True</property>
<property name="border_width">5</property>
<property name="spacing">5</property>
<property name="homogeneous">True</property>
<child>
<widget class="GtkCheckButton" id="otr_policy_allow_v1_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">OTR version 1 allowed</property>
<property name="response_id">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
</child>
<child>
<widget class="GtkCheckButton" id="otr_policy_allow_v2_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">OTR version 2 allowed</property>
<property name="response_id">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="otr_policy_require_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Encryption required</property>
<property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="otr_policy_send_tag_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Show others we understand OTR</property>
<property name="response_id">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="position">3</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="otr_policy_start_on_tag_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Automatically initiate encryption if partner understands OTR</property>
<property name="response_id">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="position">4</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="otr_policy_start_on_error_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Automatically start OTR when an OTR error occured</property>
<property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="position">5</property>
</packing>
</child>
</widget>
</child>
<child>
<widget class="GtkCheckButton" id="otr_default_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Use the default settings</property>
<property name="response_id">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">OTR Settings</property>
</widget>
<packing>
<property name="type">tab</property>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
</widget>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="settings_cancel_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="settings_ok_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-ok</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
<widget class="GtkWindow" id="otr_smp_window">
<property name="resizable">False</property>
<child>
<widget class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<child>
<widget class="GtkVBox" id="vbox4">
<property name="visible">True</property>
<property name="border_width">5</property>
<property name="spacing">5</property>
<child>
<widget class="GtkLabel" id="desc_label">
<property name="visible">True</property>
<property name="label" translatable="yes">label</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
</widget>
</child>
<child>
<widget class="GtkEntry" id="secret_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
<child>
<widget class="GtkHBox" id="hbox3">
<property name="visible">True</property>
<property name="border_width">5</property>
<child>
<widget class="GtkProgressBar" id="progressbar">
<property name="visible">True</property>
<property name="text" translatable="yes"></property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox2">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="smp_cancel_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="smp_ok_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-ok</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@ -1135,9 +1135,6 @@ class ChatControl(ChatControlBase):
self.status_tooltip = gtk.Tooltips()
if gajim.otr_module:
self.update_otr(True)
self.update_ui()
# restore previous conversation
self.restore_conversation()
@ -1207,52 +1204,6 @@ class ChatControl(ChatControlBase):
# The name banner is drawn here
ChatControlBase.update_ui(self)
def get_otr_status(self):
if not self.session:
return 0
ctx = gajim.otr_module.otrl_context_find(
self.session.conn.otr_userstates,
self.contact.get_full_jid().encode(),
gajim.get_jid_from_account(self.account).encode(),
gajim.OTR_PROTO, 1, (gajim.otr_add_appdata,
self.account))[0]
if ctx.msgstate == gajim.otr_module.OTRL_MSGSTATE_ENCRYPTED:
if ctx.active_fingerprint.trust:
return 2
else:
return 1
elif ctx.msgstate == gajim.otr_module.OTRL_MSGSTATE_FINISHED:
return 3
return 0
def update_otr(self, print_status=False):
otr_status_text = ''
otr_status = self.get_otr_status()
authenticated = False
if otr_status > 0:
enc_status = True
else:
enc_status = False
if otr_status == 1:
otr_status_text = u'*unauthenticated* secure OTR ' + \
u'connection'
elif otr_status == 2:
otr_status_text = u'authenticated secure OTR ' + \
u'connection'
authenticated = True
elif otr_status == 3:
otr_status_text = u'finished OTR connection'
self._show_lock_image(enc_status, u'OTR', enc_status, True,
authenticated)
if print_status and otr_status_text != '':
self.print_conversation_line(u'[OTR] %s' % \
otr_status_text, 'status', '', None)
def _update_banner_state_image(self):
contact = gajim.contacts.get_contact_with_highest_priority(self.account,
self.contact.jid)
@ -1662,15 +1613,6 @@ class ChatControl(ChatControlBase):
'NOT encrypted')
ChatControlBase.print_conversation_line(
self, msg, 'status', '', tim)
elif gajim.otr_module and self.get_otr_status() > 0:
# OTR
# TODO: This is not shown when the window
# isn't open - needs fixing!
if not encrypted and frm == '':
msg = _('The following message was ' + \
'NOT encrypted')
ChatControlBase.print_conversation_line(
self, msg, 'status', '', tim)
else:
# GPG encryption
if encrypted and not self.gpg_is_active:
@ -1796,11 +1738,6 @@ class ChatControl(ChatControlBase):
history_menuitem = xml.get_widget('history_menuitem')
toggle_gpg_menuitem = xml.get_widget('toggle_gpg_menuitem')
toggle_e2e_menuitem = xml.get_widget('toggle_e2e_menuitem')
otr_submenu = xml.get_widget('otr_submenu')
otr_settings_menuitem = xml.get_widget('otr_settings_menuitem')
smp_otr_menuitem = xml.get_widget('smp_otr_menuitem')
start_otr_menuitem = xml.get_widget('start_otr_menuitem')
end_otr_menuitem = xml.get_widget('end_otr_menuitem')
send_file_menuitem = xml.get_widget('send_file_menuitem')
information_menuitem = xml.get_widget('information_menuitem')
convert_to_gc_menuitem = xml.get_widget('convert_to_groupchat')
@ -1893,32 +1830,6 @@ class ChatControl(ChatControlBase):
self._on_convert_to_gc_menuitem_activate)
self.handlers[id] = convert_to_gc_menuitem
if gajim.otr_module:
otr_submenu.set_sensitive(True)
id = otr_settings_menuitem.connect('activate',
self._on_otr_settings_menuitem_activate)
self.handlers[id] = otr_settings_menuitem
id = start_otr_menuitem.connect('activate',
self._on_start_otr_menuitem_activate)
self.handlers[id] = start_otr_menuitem
id = end_otr_menuitem.connect('activate',
self._on_end_otr_menuitem_activate)
self.handlers[id] = end_otr_menuitem
id = smp_otr_menuitem.connect('activate',
self._on_smp_otr_menuitem_activate)
self.handlers[id] = smp_otr_menuitem
ctx = gajim.otr_module.otrl_context_find(gajim.connections[self.account].otr_userstates,
self.contact.get_full_jid().encode(),
gajim.get_jid_from_account(self.account).encode(), gajim.OTR_PROTO, 1,
(gajim.otr_add_appdata, self.account))[0]
# can end only when PLAINTEXT
end_otr_menuitem.set_sensitive(ctx.msgstate !=
gajim.otr_module.OTRL_MSGSTATE_PLAINTEXT)
# can SMP only when ENCRYPTED
smp_otr_menuitem.set_sensitive(ctx.msgstate ==
gajim.otr_module.OTRL_MSGSTATE_ENCRYPTED)
menu.connect('selection-done', self.destroy_menu,
send_file_menuitem, convert_to_gc_menuitem,
information_menuitem, history_menuitem)
@ -2406,28 +2317,6 @@ class ChatControl(ChatControlBase):
# XXX decide whether to use 4 or 3 message negotiation
self.session.negotiate_e2e(False)
def _on_start_otr_menuitem_activate(self, widget):
# ?OTR? gets replaced with a better message internally in otrl_message_sending
MessageControl.send_message(self, u'?OTR?', type='chat')
def _on_end_otr_menuitem_activate(self, widget):
fjid = self.contact.get_full_jid()
gajim.otr_module.otrl_message_disconnect(
self.session.conn.otr_userstates, (gajim.otr_ui_ops,
{'account': self.account, 'urgent': True}),
gajim.get_jid_from_account(self.account).encode(),
gajim.OTR_PROTO, fjid.encode())
gajim.otr_ui_ops.gajim_log(_('Private conversation with ' \
'%s lost.') % fjid, self.account, fjid.encode())
self.update_otr()
def _on_otr_settings_menuitem_activate(self, widget):
gajim.otr_windows.ContactOtrWindow(self.contact, self.account, self)
def _on_smp_otr_menuitem_activate(self, widget):
ctx = gajim.otr_module.otrl_context_find(gajim.connections[self.account].otr_userstates,
self.contact.get_full_jid().encode(),
gajim.get_jid_from_account(self.account).encode(), gajim.OTR_PROTO, 1,
(gajim.otr_add_appdata, self.account))[0]
ctx.app_data.show(False)
def got_connected(self):
ChatControlBase.got_connected(self)
# Refreshing contact

View File

@ -313,7 +313,6 @@ class Config:
'use_env_http_proxy' : [opt_bool, False],
'answer_receipt' : [opt_bool, True, _('Answer to receipt requests')],
'request_receipt' : [opt_bool, True, _('Sent receipt requests')],
'otr_flags': [opt_int, 58 ],
'publish_mood': [opt_bool, True],
'publish_activity': [opt_bool, True],
'publish_tune': [opt_bool, False],
@ -372,7 +371,6 @@ class Config:
'contacts': ({
'gpg_enabled': [ opt_bool, False, _('Is OpenPGP enabled for this contact?')],
'speller_language': [ opt_str, '', _('Language for which we want to check misspelled words')],
'otr_flags': [opt_int, -1 ],
}, {}),
'rooms': ({
'speller_language': [ opt_str, '', _('Language for which we want to check misspelled words')],

View File

@ -896,20 +896,6 @@ class Connection(ConnectionHandlers):
self.on_connect_auth = self._init_roster
self.connect_and_auth()
if gajim.otr_module:
try:
gajim.otr_module.otrl_privkey_read(self.otr_userstates,
os.path.join(gajim.gajimpaths.root,
'%s.key' % self.name).encode())
gajim.otr_module.otrl_privkey_read_fingerprints(
self.otr_userstates, os.path.join(
gajim.gajimpaths.root, '%s.fpr' %
self.name).encode(),
(gajim.otr_add_appdata, self.name))
except Exception, e:
if not hasattr(e, 'os_errno') or e.os_errno != 2:
raise
def _init_roster(self, con):
self.connection = con
if not self.connection:

View File

@ -1218,9 +1218,6 @@ class ConnectionHandlersBase:
# keep track of sessions this connection has with other JIDs
self.sessions = {}
if gajim.otr_module:
self.otr_userstates = gajim.otr_module.otrl_userstate_create()
def _FeatureNegCB(self, con, stanza, session):
gajim.log.debug('FeatureNegCB')
feature = stanza.getTag(name='feature', namespace=common.xmpp.NS_FEATURE)
@ -1705,79 +1702,6 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
receipt.setThread(thread_id)
con.send(receipt)
# We don't trust libotr, that's why we only pass the message
# to it if necessary. otrl_proto_message_type does this check.
if gajim.otr_module and not xep_200_encrypted \
and isinstance(msgtxt, unicode) and \
gajim.otr_module.otrl_proto_message_type(msgtxt.encode()) != \
gajim.otr_module.OTRL_MSGTYPE_NOTOTR:
# set to encrypted if it's really encrypted.
if gajim.otr_module.otrl_proto_message_type(
msgtxt.encode()) != \
gajim.otr_module.OTRL_MSGTYPE_TAGGEDPLAINTEXT:
encrypted = True
# TODO: Do we really need .encode()?
# yes we do. OTR can't handle unicode.
otr_msg_tuple = \
gajim.otr_module.otrl_message_receiving(
self.otr_userstates,
(gajim.otr_ui_ops, {'account': self.name}),
gajim.get_jid_from_account(self.name).encode(),
gajim.OTR_PROTO,
frm.encode(),
msgtxt.encode(),
(gajim.otr_add_appdata, self.name))
msgtxt = unicode(otr_msg_tuple[1])
html_node = msg.getTag('html')
if html_node:
msg.delChild(html_node)
msg.setBody(msgtxt)
if gajim.otr_module.otrl_tlv_find(
otr_msg_tuple[2],
gajim.otr_module.OTRL_TLV_DISCONNECTED) != None:
gajim.otr_ui_ops.gajim_log(_('%s ' \
'has ended his/her private ' \
'conversation with you. You should ' \
'do the same.') % frm,
self.name,
frm.encode())
ctrls = gajim.interface.msg_win_mgr.get_chat_controls(jid, self.name)
for ctrl in ctrls:
ctrl.update_otr()
ctx = gajim.otr_module. \
otrl_context_find(
self.otr_userstates,
frm.encode(),
gajim.get_jid_from_account(
self.name).encode(),
gajim.OTR_PROTO, 1,
(gajim.otr_add_appdata,
self.name))[0]
tlvs = otr_msg_tuple[2]
ctx.app_data.handle_tlv(tlvs)
if msgtxt == '':
return
elif msgtxt != None and msgtxt != '':
gajim.otr_dont_append_tag[frm] = True
# We're also here if we just don't
# support OTR. Thus, we should strip
# the tags from plaintext messages
# since they look ugly.
msgtxt = msgtxt.replace('\x20\x09\x20' \
'\x20\x09\x09\x09\x09\x20\x09' \
'\x20\x09\x20\x09\x20\x20', '')
msgtxt = msgtxt.replace('\x20\x09\x20' \
'\x09\x20\x20\x09\x20', '')
msgtxt = msgtxt.replace('\x20\x20\x09' \
'\x09\x20\x20\x09\x20', '')
if mtype != 'groupchat':
session = self.get_or_create_session(frm, thread_id)

View File

@ -165,13 +165,6 @@ else:
if system('gpg -h >/dev/null 2>&1'):
HAVE_GPG = False
OTR_PROTO = "xmpp"
otr_userstates = {}
otr_policy = {}
# list of (full) jids not to attempt OTR with
otr_dont_append_tag = {}
gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'}
gajim_common_features = [xmpp.NS_BYTESTREAM, xmpp.NS_SI,
xmpp.NS_FILE, xmpp.NS_MUC, xmpp.NS_MUC_USER,

View File

@ -99,10 +99,6 @@ class FeaturesWindow:
_('Encrypting chatmessages.'),
_('Requires python-crypto.'),
_('Requires python-crypto.')),
_('Off the Record Encryption'): (self.otr_available,
_('Encrypting chatmessages in a way that even works through gateways.'),
_('Requires pyotr and libotr (see http://trac.gajim.org/wiki/OTR).'),
_('Requires pyotr and libotr (see http://trac.gajim.org/wiki/OTR).')),
_('RST Generator'): (self.docutils_available,
_('Generate XHTML output from RST code (see http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html).'),
_('Requires python-docutils.'),
@ -312,11 +308,6 @@ class FeaturesWindow:
from common import gajim
return gajim.HAVE_PYCRYPTO
def otr_available(self):
if gajim.otr_module:
return True
return False
def docutils_available(self):
try:
import docutils

View File

@ -266,214 +266,6 @@ from common import helpers
from common import optparser
from common import dataforms
from common.xmpp import Message as XmppMessage
try:
import otr, otr_windows
gajim.otr_module = otr
gajim.otr_windows = otr_windows
except ImportError:
gajim.otr_module = None
gajim.otr_windows = None
def add_appdata(data, context):
account = data
context.app_data = otr_windows.ContactOtrSMPWindow(
unicode(context.username), account)
gajim.otr_add_appdata = add_appdata
def otr_dialog_destroy(widget, *args, **kwargs):
widget.destroy()
class OtrlMessageAppOps:
def gajim_log(self, msg, account, fjid, no_print=False):
if not isinstance(fjid, unicode):
fjid = unicode(fjid)
if not isinstance(account, unicode):
account = unicode(account)
resource=gajim.get_resource_from_jid(fjid)
tim = time.localtime()
if not no_print:
ctrl = self.get_control(fjid, account)
if ctrl:
ctrl.print_conversation_line(u'[OTR] %s' % \
msg, 'status', '', None)
id = gajim.logger.write('chat_msg_recv', fjid,
message='[OTR: %s]' % msg, tim=tim)
# gajim.logger.write() only marks a message as unread
# (and so only returns an id) when fjid is a real contact
# (NOT if it's a GC private chat)
if id:
gajim.logger.set_read_messages([id])
def get_control(self, fjid, account):
# first try to get the window with the full jid
ctrls = gajim.interface.msg_win_mgr.get_chat_controls(fjid, account)
if ctrls:
# got one, be happy
return ctrls[0]
# otherwise try without the resource
ctrls = gajim.interface.msg_win_mgr.get_chat_controls(
gajim.get_jid_without_resource(fjid), account)
# but only use it when it is not a GC window
if ctrls and ctrls[0].TYPE_ID == message_control.TYPE_CHAT:
return ctrls[0]
def policy(self, opdata=None, context=None):
policy = gajim.config.get_per('contacts', context.username,
"otr_flags")
if policy <= 0:
policy = gajim.config.get_per('contacts',
gajim.get_jid_without_resource(
context.username), 'otr_flags')
if policy <= 0:
policy = gajim.config.get_per('accounts',
opdata['account'], 'otr_flags')
return policy
def create_privkey(self, opdata='', accountname='', protocol=''):
dialog = gtk.Dialog(
title = _('Generating...'),
parent = gajim.interface.roster.window,
flags = gtk.DIALOG_MODAL,
buttons = (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
permlabel = gtk.Label(_('Generating a private key for %s...') \
% accountname)
permlabel.set_padding(20, 20)
dialog.set_response_sensitive(gtk.RESPONSE_CLOSE, False)
dialog.connect('destroy', otr_dialog_destroy)
dialog.connect('response', otr_dialog_destroy)
dialog.vbox.pack_start(permlabel)
dialog.get_root_window().raise_()
dialog.show_all()
dialog.map()
for c in dialog.get_children():
c.show_now()
c.map()
while gtk.events_pending():
gtk.main_iteration(block = False)
otr.otrl_privkey_generate(
gajim.connections[opdata['account']].otr_userstates,
os.path.join(gajimpaths.root,
'%s.key' % opdata['account']).encode(),
accountname, gajim.OTR_PROTO)
permlabel.set_text(_('Generating a private key for %s...\n' \
'done.') % accountname)
dialog.set_response_sensitive(gtk.RESPONSE_CLOSE, True)
def is_logged_in(self, opdata={}, accountname='', protocol='',
recipient=""):
contact = gajim.contacts.get_contact_from_full_jid(
opdata['account'], recipient)
if contact:
return contact.show \
in ['dnd', 'xa', 'chat', 'online', 'away',
'invisible']
return 0
def inject_message(self, opdata=None, accountname='', protocol='',
recipient='', message=''):
msg_type = otr.otrl_proto_message_type(message)
if 'kwargs' not in opdata or 'urgent' in opdata:
# don't use send_message here to have the message
# sent immediatly. This results in being able to
# disconnect from OTR sessions before quitting
stanza = XmppMessage(to = recipient,
body = message, typ='chat')
gajim.connections[opdata['account']].connection. \
send(stanza, now = True)
return
if msg_type == otr.OTRL_MSGTYPE_QUERY:
# split away XHTML-contaminated explanatory message
message = unicode(message.splitlines()[0])
message += _(u'\nThis user has requested an ' \
'Off-the-Record private conversation. ' \
'However, you do not have a plugin to ' \
'support that.\n' \
'See http://otr.cypherpunks.ca/ for more ' \
'information.')
gajim.connections[opdata['account']].connection.send(
common.xmpp.Message(to = recipient,
body = message, typ = 'chat'))
return
gajim.connections[opdata['account']].send_message(recipient,
message, **opdata['kwargs'])
def notify(sef, opdata=None, username='', **kwargs):
self.gajim_log('Notify: ' + str(kwargs), opdata['account'],
username)
def display_otr_message(self, opdata=None, username="", msg="", **kwargs):
self.gajim_log('OTR Message: ' + msg, opdata['account'],
username)
return 0
def update_context_list(self, **kwargs):
# FIXME stub FIXME #
pass
def protocol_name(self, opdata=None, protocol=""):
return 'XMPP'
def new_fingerprint(self, opdata=None, username='', fingerprint='',
**kwargs):
self.gajim_log('New fingerprint for %s: %s' % (username,
otr.otrl_privkey_hash_to_human(fingerprint)),
opdata['account'], username)
def write_fingerprints(self, opdata=''):
otr.otrl_privkey_write_fingerprints(
gajim.connections[opdata['account']].otr_userstates,
os.path.join(gajimpaths.root, '%s.fpr' % \
opdata['account']).encode())
def gone_secure(self, opdata='', context=None):
trust = context.active_fingerprint.trust \
and 'verified' or 'unverified'
self.gajim_log('%s secured OTR connection started' % trust,
opdata['account'], context.username, no_print = True)
ctrl = self.get_control(context.username, opdata['account'])
if ctrl:
ctrl.update_otr(True)
def gone_insecure(self, opdata='', context=None):
self.gajim_log('Private conversation with %s lost.',
opdata['account'], context.username)
ctrl = self.get_control(context.username, opdata['account'])
if ctrl:
ctrl.update_otr(True)
def still_secure(self, opdata=None, context=None, is_reply=0):
ctrl = self.get_control(context.username, opdata['account'])
if ctrl:
ctrl.update_otr(True)
self.gajim_log('OTR connection was refreshed',
opdata['account'], context.username)
def log_message(self, opdata=None, message=''):
gajim.log.debug(message)
def max_message_size(self, **kwargs):
return 0
def account_name(self, opdata=None, account='', protocol=''):
return gajim.get_name_from_jid(opdata['account'],
unicode(account))
gajim.otr_ui_ops = OtrlMessageAppOps()
if verbose: gajim.verbose = True
del verbose

View File

@ -163,46 +163,6 @@ class MessageControl:
self.set_session(sess)
xep_200 = bool(self.session) and self.session.enable_encryption
if gajim.otr_module and not xep_200 and (jid not in gajim.otr_dont_append_tag):
if type == 'chat' and isinstance(message, unicode):
d = {'kwargs': {'keyID': keyID, 'type': type,
'chatstate': chatstate,
'msg_id': msg_id,
'composing_xep': composing_xep,
'resource': self.resource,
'user_nick': user_nick,
'session': self.session,
'original_message': original_message},
'account': self.account}
new_msg = gajim.otr_module.otrl_message_sending(
self.session.conn.otr_userstates,
(gajim.otr_ui_ops, d),
gajim.get_jid_from_account(
self.account).encode(),
gajim.OTR_PROTO,
self.contact.get_full_jid().encode(),
message.encode(), None,
(gajim.otr_add_appdata, self.account))
ctx = gajim.otr_module.otrl_context_find(
self.session.conn.otr_userstates,
self.contact.get_full_jid().encode(),
gajim.get_jid_from_account(
self.account).encode(),
gajim.OTR_PROTO, 1,
(gajim.otr_add_appdata,
self.account))[0]
# we send all because inject_message can filter
# on HTML stuff then
gajim.otr_module.otrl_message_fragment_and_send(
(gajim.otr_ui_ops, d), ctx, new_msg,
gajim.otr_module.OTRL_FRAGMENT_SEND_ALL)
return
# Send and update history
return conn.send_message(jid, message, keyID, type = type,
chatstate = chatstate, msg_id = msg_id, composing_xep = composing_xep,

View File

@ -1,357 +0,0 @@
#!/usr/bin/env python
## otr_windows.py
##
##
## Copyright (C) 2008 Kjell Braden <fnord@pentabarf.de>
##
## This file is part of Gajim.
##
## Gajim 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.
##
## Gajim 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 should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
import gtkgui_helpers
from common import gajim
our_fp_text = _('Your fingerprint:\n' \
'<span weight="bold" face="monospace">%s</span>')
their_fp_text = _('Purported fingerprint for %s:\n' \
'<span weight="bold" face="monospace">%s</span>')
class ContactOtrSMPWindow:
def gw(self, n):
# shorthand for self.xml.get_widget(n)
return self.xml.get_widget(n)
def __init__(self, fjid, account):
self.fjid = fjid
self.account = account
self.xml = gtkgui_helpers.get_glade('contact_otr_window.glade')
self.window = self.xml.get_widget('otr_smp_window')
# the contact may be unknown to gajim if ContactOtrSMPWindow
# is created very early
self.contact = gajim.contacts.get_contact_from_full_jid(
account, fjid)
if self.contact:
self.window.set_title(_('OTR settings for %s') % \
self.contact.get_full_jid())
self.ctx = gajim.otr_module.otrl_context_find(
gajim.connections[self.account].otr_userstates,
self.fjid.encode(), gajim.get_jid_from_account(
self.account).encode(), gajim.OTR_PROTO, 1,
(gajim.otr_add_appdata, self.account))[0]
self.gw('smp_cancel_button').connect('clicked',
self._on_destroy)
self.gw('smp_ok_button').connect('clicked', self._apply)
def show(self, response):
# re-initialize if contact was unknown when we
# initially initialized
if not self.contact:
self.__init__(self.fjid, self.account)
# the contact MUST be known when showing the dialog
assert(self.contact)
self.smp_running = False
self.finished = False
self.gw('smp_cancel_button').set_sensitive(True)
self.gw('smp_ok_button').set_sensitive(True)
self.gw('progressbar').set_fraction(0)
self.gw('secret_entry').set_text('')
self.response = response
if response:
self.gw('desc_label').set_markup(_('<b>%s is trying ' \
'to authenticate you using a secret only ' \
'known to him/her and you.</b> Please enter ' \
'your secret below.') % \
self.contact.get_full_jid())
else:
self.gw('desc_label').set_markup(_('<b>You are ' \
'trying to authenticate %s using a secret' \
'only known to him/her and yourself.</b>' \
'Please enter your secret below.') % \
self.contact.get_full_jid())
self.window.show_all()
def _abort(self, text=None):
self.smp_running = False
gajim.otr_module.otrl_message_abort_smp(
gajim.connections[self.account].otr_userstates,
(gajim.otr_ui_ops, {'account': self.account}), self.ctx)
if text:
gajim.otr_ui_ops.gajim_log(text, self.account,
self.contact.get_full_jid())
def _finish(self, text):
self.smp_running = False
self.finished = True
self.gw('smp_cancel_button').set_sensitive(False)
self.gw('smp_ok_button').set_sensitive(True)
self.gw('progressbar').set_fraction(1)
gajim.otr_ui_ops.gajim_log(text, self.account,
self.contact.get_full_jid())
self.gw('desc_label').set_markup(text)
for ctrl in gajim.interface.msg_win_mgr.get_chat_controls(
self.contact.jid, self.account):
ctrl.update_otr(True)
gajim.otr_ui_ops.write_fingerprints({'account': self.account})
def handle_tlv(self, tlvs):
if not self.contact:
self.__init__(self.fjid, self.account)
if tlvs:
nextTLV = self.ctx.smstate.nextExpected;
tlv = gajim.otr_module.otrl_tlv_find(tlvs,
gajim.otr_module.OTRL_TLV_SMP1)
if tlv:
if nextTLV != \
gajim.otr_module.OTRL_SMP_EXPECT1:
self._abort()
else:
self.show(True)
self.gw('progressbar'). \
set_fraction(0.3)
tlv = gajim.otr_module.otrl_tlv_find(tlvs,
gajim.otr_module.OTRL_TLV_SMP2)
if tlv:
if nextTLV != gajim.otr_module.OTRL_SMP_EXPECT2:
self._abort()
else:
self.ctx.smstate.nextExpected = \
gajim.otr_module. \
OTRL_SMP_EXPECT4
self.gw('progressbar').set_fraction(0.6)
tlv = gajim.otr_module.otrl_tlv_find(tlvs,
gajim.otr_module.OTRL_TLV_SMP3)
if tlv:
if nextTLV != gajim.otr_module.OTRL_SMP_EXPECT3:
self._abort()
else:
self.ctx.smstate.nextExpected = \
gajim.otr_module. \
OTRL_SMP_EXPECT1;
if self.ctx.active_fingerprint.trust:
self._finish(_('SMP ' \
'verifying succeeded'))
else:
self._finish(_('SMP ' \
'verifying failed'))
tlv = gajim.otr_module.otrl_tlv_find(tlvs,
gajim.otr_module.OTRL_TLV_SMP4)
if tlv:
if nextTLV != gajim.otr_module.OTRL_SMP_EXPECT4:
self._abort()
else:
self.ctx.smstate.nextExpected = \
gajim.otr_module. \
OTRL_SMP_EXPECT1;
if self.ctx.active_fingerprint.trust:
self._finish(_('SMP ' \
'verifying succeeded'))
else:
self._finish(_('SMP ' \
'verifying failed'))
tlv = gajim.otr_module.otrl_tlv_find(tlvs,
gajim.otr_module.OTRL_TLV_SMP_ABORT)
if tlv:
self._finish(_('SMP verifying aborted'))
def _on_destroy(self, widget):
if self.smp_running:
self._abort(_('user aborted SMP authentication'))
self.window.hide_all()
def _apply(self, widget):
if self.finished:
self.window.hide_all()
return
secret = self.gw('secret_entry').get_text()
if self.response:
gajim.otr_module.otrl_message_respond_smp(
gajim.connections[self.account].otr_userstates,
(gajim.otr_ui_ops, {'account': self.account}),
self.ctx, secret)
else:
gajim.otr_module.otrl_message_initiate_smp(
gajim.connections[self.account].otr_userstates,
(gajim.otr_ui_ops, {'account': self.account}),
self.ctx, secret)
self.gw('progressbar').set_fraction(0.3)
self.smp_running = True
widget.set_sensitive(False)
class ContactOtrWindow:
def gw(self, n):
# shorthand for self.xml.get_widget(n)
return self.xml.get_widget(n)
def __init__(self, contact, account, ctrl=None):
self.contact = contact
self.account = account
self.ctrl = ctrl
self.ctx = gajim.otr_module.otrl_context_find(
gajim.connections[self.account].otr_userstates,
self.contact.get_full_jid().encode(),
gajim.get_jid_from_account(self.account).encode(),
gajim.OTR_PROTO, 1, (gajim.otr_add_appdata,
self.account))[0]
self.xml = gtkgui_helpers.get_glade('contact_otr_window.glade')
self.window = self.xml.get_widget('otr_settings_window')
self.gw('settings_cancel_button').connect('clicked',
self._on_destroy)
self.gw('settings_ok_button').connect('clicked', self._apply)
self.gw('otr_default_checkbutton').connect('toggled',
self._otr_default_checkbutton_toggled)
self.window.set_title(_('OTR settings for %s') % \
self.contact.get_full_jid())
# always set the label containing our fingerprint
self.gw('our_fp_label').set_markup(our_fp_text % \
gajim.otr_module.otrl_privkey_fingerprint(
gajim.connections[self.account].otr_userstates,
gajim.get_jid_from_account(self.account).encode(),
gajim.OTR_PROTO))
if self.ctx.msgstate != \
gajim.otr_module.OTRL_MSGSTATE_ENCRYPTED:
# make the fingerprint widgets insensitive
# when not encrypted
for widget in self.gw('otr_fp_vbox').get_children():
widget.set_sensitive(False)
# show that the fingerprint is unknown
self.gw('their_fp_label').set_markup(
their_fp_text % (self.contact.get_full_jid(),
_('unknown')))
self.gw('verified_combobox').set_active(-1)
else:
# make the fingerprint widgets sensitive when encrypted
for widget in self.gw('otr_fp_vbox').get_children():
widget.set_sensitive(True)
# show their fingerprint
self.gw('their_fp_label').set_markup(
their_fp_text%(self.contact.get_full_jid(),
gajim.otr_module.otrl_privkey_hash_to_human(
self.ctx.active_fingerprint.fingerprint)))
# set the trust combobox
if self.ctx.active_fingerprint.trust:
self.gw('verified_combobox').set_active(1)
else:
self.gw('verified_combobox').set_active(0)
otr_flags = gajim.config.get_per('contacts', self.contact.jid,
'otr_flags')
if otr_flags >= 0:
self.gw('otr_default_checkbutton').set_active(0)
for w in self.gw('otr_settings_vbox').get_children():
w.set_sensitive(True)
else:
# per-user settings not available,
# using default settings
otr_flags = gajim.config.get_per('accounts',
self.account, 'otr_flags')
self.gw('otr_default_checkbutton').set_active(1)
for w in self.gw('otr_settings_vbox').get_children():
w.set_sensitive(False)
self.gw('otr_policy_allow_v1_checkbutton').set_active(
otr_flags & gajim.otr_module.OTRL_POLICY_ALLOW_V1)
self.gw('otr_policy_allow_v2_checkbutton').set_active(
otr_flags & gajim.otr_module.OTRL_POLICY_ALLOW_V2)
self.gw('otr_policy_require_checkbutton').set_active(
otr_flags & gajim.otr_module.OTRL_POLICY_REQUIRE_ENCRYPTION)
self.gw('otr_policy_send_tag_checkbutton').set_active(
otr_flags & \
gajim.otr_module.OTRL_POLICY_SEND_WHITESPACE_TAG)
self.gw('otr_policy_start_on_tag_checkbutton').set_active(
otr_flags & \
gajim.otr_module.OTRL_POLICY_WHITESPACE_START_AKE)
self.gw('otr_policy_start_on_error_checkbutton').set_active(
otr_flags & \
gajim.otr_module.OTRL_POLICY_ERROR_START_AKE)
self.window.show_all()
def _on_destroy(self, widget):
self.window.destroy()
def _apply(self, widget):
# -1 when nothing is selected
# (ie. the connection is not encrypted)
trust_state = self.gw('verified_combobox').get_active()
if trust_state == 1 and not self.ctx.active_fingerprint.trust:
gajim.otr_module.otrl_context_set_trust(
self.ctx.active_fingerprint, 'verified')
gajim.otr_ui_ops.write_fingerprints(
{'account': self.account})
elif trust_state == 0:
gajim.otr_module.otrl_context_set_trust(
self.ctx.active_fingerprint, '')
gajim.otr_ui_ops.write_fingerprints(
{'account': self.account})
if not self.ctrl:
self.ctrl = gajim.interface.msg_win_mgr.get_control(
self.contact.jid, self.account)
if self.ctrl:
self.ctrl.update_otr(True)
if self.gw('otr_default_checkbutton').get_active():
# default is enabled, so remove any user-specific
# settings if available
gajim.config.set_per('contacts',
self.contact.jid, 'otr_flags', -1)
else:
# build the flags using the checkboxes
flags = 0
flags += self.gw('otr_policy_allow_v1_checkbutton'). \
get_active() and gajim.otr_module. \
OTRL_POLICY_ALLOW_V1
flags += self.gw('otr_policy_allow_v2_checkbutton'). \
get_active() and gajim.otr_module. \
OTRL_POLICY_ALLOW_V2
flags += self.gw('otr_policy_require_checkbutton'). \
get_active() and gajim.otr_module. \
OTRL_POLICY_REQUIRE_ENCRYPTION
flags += self.gw('otr_policy_send_tag_checkbutton'). \
get_active() and gajim.otr_module. \
OTRL_POLICY_SEND_WHITESPACE_TAG
flags += self.gw(
'otr_policy_start_on_tag_checkbutton'). \
get_active() and gajim.otr_module. \
OTRL_POLICY_WHITESPACE_START_AKE
flags += self.gw(
'otr_policy_start_on_error_checkbutton'). \
get_active() and gajim.otr_module. \
OTRL_POLICY_ERROR_START_AKE
gajim.config.add_per('contacts', self.contact.jid)
gajim.config.set_per('contacts', self.contact.jid,
'otr_flags', flags)
self._on_destroy(widget)
def _otr_default_checkbutton_toggled(self, widget):
for w in self.gw('otr_settings_vbox').get_children():
w.set_sensitive(not widget.get_active())

View File

@ -1837,19 +1837,6 @@ class RosterWindow:
elif gajim.sleeper_state[account] not in ('autoaway', 'autoxa'):
gajim.sleeper_state[account] = 'off'
if gajim.otr_module:
# disconnect from ENCRYPTED OTR contexts when going
# offline/invisible
if status == 'offline' or status == 'invisible':
ctx = gajim.connections[account].otr_userstates.context_root
while ctx is not None:
if ctx.msgstate == gajim.otr_module.OTRL_MSGSTATE_ENCRYPTED:
disconnected = True
gajim.otr_module.otrl_message_disconnect(gajim.connections[
account].otr_userstates, (gajim.otr_ui_ops,
{'account': account,'urgent': True}), ctx.accountname,
ctx.protocol, ctx.username)
ctx = ctx.next
if to:
gajim.connections[account].send_custom_status(status, txt, to)
else:

View File

@ -72,7 +72,10 @@ class StatusIcon(systray.Systray):
self.status_icon.set_tooltip(text)
if gajim.events.get_nb_systray_events():
if sys.platform == 'darwin':
osx.nsapp.requestUserAttention()
try:
osx.nsapp.requestUserAttention()
except NameError:
pass
state = 'event'
self.status_icon.set_blinking(True)
else: