moved session negotiation handling from gajim.py to session.py
This commit is contained in:
parent
984268d845
commit
8b4627049b
|
@ -1218,33 +1218,6 @@ class ConnectionHandlersBase:
|
|||
# keep track of sessions this connection has with other JIDs
|
||||
self.sessions = {}
|
||||
|
||||
def _FeatureNegCB(self, con, stanza, session):
|
||||
gajim.log.debug('FeatureNegCB')
|
||||
feature = stanza.getTag(name='feature', namespace=common.xmpp.NS_FEATURE)
|
||||
form = common.xmpp.DataForm(node=feature.getTag('x'))
|
||||
|
||||
if form['FORM_TYPE'] == 'urn:xmpp:ssn':
|
||||
self.dispatch('SESSION_NEG', (stanza.getFrom(), session, form))
|
||||
else:
|
||||
reply = stanza.buildReply()
|
||||
reply.setType('error')
|
||||
|
||||
reply.addChild(feature)
|
||||
reply.addChild(node=common.xmpp.ErrorNode('service-unavailable', typ='cancel'))
|
||||
|
||||
con.send(reply)
|
||||
|
||||
raise common.xmpp.NodeProcessed
|
||||
|
||||
def _InitE2ECB(self, con, stanza, session):
|
||||
gajim.log.debug('InitE2ECB')
|
||||
init = stanza.getTag(name='init', namespace=common.xmpp.NS_ESESSION_INIT)
|
||||
form = common.xmpp.DataForm(node=init.getTag('x'))
|
||||
|
||||
self.dispatch('SESSION_NEG', (stanza.getFrom(), session, form))
|
||||
|
||||
raise common.xmpp.NodeProcessed
|
||||
|
||||
def get_or_create_session(self, jid, thread_id):
|
||||
'''returns an existing session between this connection and 'jid', returns a new one if none exist.'''
|
||||
|
||||
|
@ -1717,10 +1690,32 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
|
|||
# check if the message is a XEP-0020 feature negotiation request
|
||||
if msg.getTag('feature', namespace=common.xmpp.NS_FEATURE):
|
||||
if gajim.HAVE_PYCRYPTO:
|
||||
self._FeatureNegCB(con, msg, session)
|
||||
feature = msg.getTag(name='feature', namespace=common.xmpp.NS_FEATURE)
|
||||
form = common.xmpp.DataForm(node=feature.getTag('x'))
|
||||
|
||||
if form['FORM_TYPE'] == 'urn:xmpp:ssn':
|
||||
session.handle_negotiation(form)
|
||||
else:
|
||||
reply = msg.buildReply()
|
||||
reply.setType('error')
|
||||
|
||||
reply.addChild(feature)
|
||||
err = common.xmpp.ErrorNode('service-unavailable', typ='cancel')
|
||||
reply.addChild(node=err)
|
||||
|
||||
con.send(reply)
|
||||
|
||||
raise common.xmpp.NodeProcessed
|
||||
|
||||
return
|
||||
|
||||
if msg.getTag('init', namespace=common.xmpp.NS_ESESSION_INIT):
|
||||
self._InitE2ECB(con, msg, session)
|
||||
init = msg.getTag(name='init', namespace=common.xmpp.NS_ESESSION_INIT)
|
||||
form = common.xmpp.DataForm(node=init.getTag('x'))
|
||||
|
||||
session.handle_negotiation(form)
|
||||
|
||||
raise common.xmpp.NodeProcessed
|
||||
|
||||
tim = msg.getTimestamp()
|
||||
tim = helpers.datetime_tuple(tim)
|
||||
|
|
149
src/gajim.py
149
src/gajim.py
|
@ -246,7 +246,6 @@ import math
|
|||
import gtkgui_helpers
|
||||
import notify
|
||||
import message_control
|
||||
import negotiation
|
||||
|
||||
from chat_control import ChatControlBase
|
||||
from chat_control import ChatControl
|
||||
|
@ -1752,153 +1751,6 @@ class Interface:
|
|||
else:
|
||||
print 'failed decrypt, unable to find a control to notify you in.'
|
||||
|
||||
def handle_session_negotiation(self, account, data):
|
||||
jid, session, form = data
|
||||
|
||||
if form.getField('accept') and not form['accept'] in ('1', 'true'):
|
||||
session.cancelled_negotiation()
|
||||
return
|
||||
|
||||
# encrypted session states. these are described in stanza_session.py
|
||||
|
||||
try:
|
||||
# bob responds
|
||||
if form.getType() == 'form' and 'security' in form.asDict():
|
||||
def continue_with_negotiation(*args):
|
||||
if len(args):
|
||||
self.dialog.destroy()
|
||||
|
||||
# we don't support 3-message negotiation as the responder
|
||||
if 'dhkeys' in form.asDict():
|
||||
session.fail_bad_negotiation('3 message negotiation not supported when responding', ('dhkeys',))
|
||||
return
|
||||
|
||||
negotiated, not_acceptable, ask_user = session.verify_options_bob(form)
|
||||
|
||||
if ask_user:
|
||||
def accept_nondefault_options(is_checked):
|
||||
self.dialog.destroy()
|
||||
negotiated.update(ask_user)
|
||||
session.respond_e2e_bob(form, negotiated, not_acceptable)
|
||||
|
||||
def reject_nondefault_options():
|
||||
self.dialog.destroy()
|
||||
for key in ask_user.keys():
|
||||
not_acceptable.append(key)
|
||||
session.respond_e2e_bob(form, negotiated, not_acceptable)
|
||||
|
||||
self.dialog = dialogs.YesNoDialog(_('Confirm these session options'),
|
||||
_('''The remote client wants to negotiate an session with these features:
|
||||
|
||||
%s
|
||||
|
||||
Are these options acceptable?''') % (negotiation.describe_features(ask_user)),
|
||||
on_response_yes=accept_nondefault_options,
|
||||
on_response_no=reject_nondefault_options)
|
||||
else:
|
||||
session.respond_e2e_bob(form, negotiated, not_acceptable)
|
||||
|
||||
def ignore_negotiation(widget):
|
||||
self.dialog.destroy()
|
||||
return
|
||||
|
||||
continue_with_negotiation()
|
||||
|
||||
return
|
||||
|
||||
# alice accepts
|
||||
elif session.status == 'requested-e2e' and form.getType() == 'submit':
|
||||
negotiated, not_acceptable, ask_user = session.verify_options_alice(form)
|
||||
|
||||
if session.sigmai:
|
||||
def _cb(on_success):
|
||||
negotiation.show_sas_dialog(session, jid, session.sas, on_success)
|
||||
|
||||
session.check_identity = _cb
|
||||
|
||||
if ask_user:
|
||||
def accept_nondefault_options(is_checked):
|
||||
dialog.destroy()
|
||||
|
||||
negotiated.update(ask_user)
|
||||
|
||||
try:
|
||||
session.accept_e2e_alice(form, negotiated)
|
||||
except exceptions.NegotiationError, details:
|
||||
session.fail_bad_negotiation(details)
|
||||
|
||||
def reject_nondefault_options():
|
||||
session.reject_negotiation()
|
||||
dialog.destroy()
|
||||
|
||||
dialog = dialogs.YesNoDialog(_('Confirm these session options'),
|
||||
_('The remote client selected these options:\n\n%s\n\nContinue with the session?') % (negotiation.describe_features(ask_user)),
|
||||
on_response_yes = accept_nondefault_options,
|
||||
on_response_no = reject_nondefault_options)
|
||||
else:
|
||||
try:
|
||||
session.accept_e2e_alice(form, negotiated)
|
||||
except exceptions.NegotiationError, details:
|
||||
session.fail_bad_negotiation(details)
|
||||
|
||||
return
|
||||
elif session.status == 'responded-e2e' and form.getType() == 'result':
|
||||
|
||||
def _cb(on_success):
|
||||
negotiation.show_sas_dialog(session, jid, session.sas, on_success)
|
||||
|
||||
session.check_identity = _cb
|
||||
|
||||
try:
|
||||
session.accept_e2e_bob(form)
|
||||
except exceptions.NegotiationError, details:
|
||||
session.fail_bad_negotiation(details)
|
||||
|
||||
return
|
||||
elif session.status == 'identified-alice' and form.getType() == 'result':
|
||||
def _cb(on_success):
|
||||
negotiation.show_sas_dialog(session, jid, session.sas, on_success)
|
||||
|
||||
session.check_identity = _cb
|
||||
|
||||
try:
|
||||
session.final_steps_alice(form)
|
||||
except exceptions.NegotiationError, details:
|
||||
session.fail_bad_negotiation(details)
|
||||
|
||||
return
|
||||
except exceptions.Cancelled:
|
||||
# user cancelled the negotiation
|
||||
|
||||
session.reject_negotiation()
|
||||
|
||||
return
|
||||
|
||||
if form.getField('terminate') and\
|
||||
form.getField('terminate').getValue() in ('1', 'true'):
|
||||
jid = str(jid)
|
||||
|
||||
session.acknowledge_termination()
|
||||
|
||||
conn = gajim.connections[account]
|
||||
conn.delete_session(jid, session.thread_id)
|
||||
|
||||
return
|
||||
|
||||
# non-esession negotiation. this isn't very useful, but i'm keeping it around
|
||||
# to test my test suite.
|
||||
if form.getType() == 'form':
|
||||
if not session.control:
|
||||
resource = jid.getResource()
|
||||
contact = gajim.contacts.get_contact(account, str(jid), resource)
|
||||
if not contact:
|
||||
connection = gajim.connections[account]
|
||||
contact = gajim.contacts.create_contact(jid = jid.getStripped(),
|
||||
resource = resource, show = connection.get_status())
|
||||
self.new_chat(contact, account, resource = resource, session = session)
|
||||
|
||||
negotiation.FeatureNegotiationWindow(account, jid, session, form)
|
||||
|
||||
def handle_event_privacy_lists_received(self, account, data):
|
||||
# ('PRIVACY_LISTS_RECEIVED', account, list)
|
||||
if not self.instances.has_key(account):
|
||||
|
@ -2195,7 +2047,6 @@ class Interface:
|
|||
'UNIQUE_ROOM_ID_UNSUPPORTED': \
|
||||
self.handle_event_unique_room_id_unsupported,
|
||||
'UNIQUE_ROOM_ID_SUPPORTED': self.handle_event_unique_room_id_supported,
|
||||
'SESSION_NEG': self.handle_session_negotiation,
|
||||
'GPG_PASSWORD_REQUIRED': self.handle_event_gpg_password_required,
|
||||
'SSL_ERROR': self.handle_event_ssl_error,
|
||||
'FINGERPRINT_ERROR': self.handle_event_fingerprint_error,
|
||||
|
|
139
src/session.py
139
src/session.py
|
@ -7,12 +7,13 @@ from common import contacts
|
|||
|
||||
import common.xmpp
|
||||
|
||||
import dialogs
|
||||
|
||||
import message_control
|
||||
|
||||
import notify
|
||||
|
||||
import dialogs
|
||||
import negotiation
|
||||
|
||||
class ChatControlSession(stanza_session.EncryptedStanzaSession):
|
||||
def __init__(self, conn, jid, thread_id, type = 'chat'):
|
||||
stanza_session.EncryptedStanzaSession.__init__(self, conn, jid, thread_id, type = 'chat')
|
||||
|
@ -330,3 +331,137 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession):
|
|||
gajim.interface.roster.show_title() # we show the * or [n]
|
||||
# Select contact row in roster.
|
||||
gajim.interface.roster.select_contact(jid, self.conn.name)
|
||||
|
||||
# ---- ESessions stuff ---
|
||||
|
||||
def check_identity(self, on_success):
|
||||
negotiation.show_sas_dialog(self, self.jid, self.sas, on_success)
|
||||
|
||||
def handle_negotiation(self, form):
|
||||
if form.getField('accept') and not form['accept'] in ('1', 'true'):
|
||||
self.cancelled_negotiation()
|
||||
return
|
||||
|
||||
# encrypted session states. these are described in stanza_session.py
|
||||
|
||||
try:
|
||||
# bob responds
|
||||
if form.getType() == 'form' and 'security' in form.asDict():
|
||||
def continue_with_negotiation(*args):
|
||||
if len(args):
|
||||
self.dialog.destroy()
|
||||
|
||||
# we don't support 3-message negotiation as the responder
|
||||
if 'dhkeys' in form.asDict():
|
||||
self.fail_bad_negotiation('3 message negotiation not supported when responding', ('dhkeys',))
|
||||
return
|
||||
|
||||
negotiated, not_acceptable, ask_user = self.verify_options_bob(form)
|
||||
|
||||
if ask_user:
|
||||
def accept_nondefault_options(is_checked):
|
||||
self.dialog.destroy()
|
||||
negotiated.update(ask_user)
|
||||
self.respond_e2e_bob(form, negotiated, not_acceptable)
|
||||
|
||||
def reject_nondefault_options():
|
||||
self.dialog.destroy()
|
||||
for key in ask_user.keys():
|
||||
not_acceptable.append(key)
|
||||
self.respond_e2e_bob(form, negotiated, not_acceptable)
|
||||
|
||||
self.dialog = dialogs.YesNoDialog(_('Confirm these session options'),
|
||||
_('''The remote client wants to negotiate an session with these features:
|
||||
|
||||
%s
|
||||
|
||||
Are these options acceptable?''') % (negotiation.describe_features(ask_user)),
|
||||
on_response_yes=accept_nondefault_options,
|
||||
on_response_no=reject_nondefault_options)
|
||||
else:
|
||||
self.respond_e2e_bob(form, negotiated, not_acceptable)
|
||||
|
||||
def ignore_negotiation(widget):
|
||||
self.dialog.destroy()
|
||||
return
|
||||
|
||||
continue_with_negotiation()
|
||||
|
||||
return
|
||||
|
||||
# alice accepts
|
||||
elif self.status == 'requested-e2e' and form.getType() == 'submit':
|
||||
negotiated, not_acceptable, ask_user = self.verify_options_alice(form)
|
||||
|
||||
if ask_user:
|
||||
def accept_nondefault_options(is_checked):
|
||||
dialog.destroy()
|
||||
|
||||
negotiated.update(ask_user)
|
||||
|
||||
try:
|
||||
self.accept_e2e_alice(form, negotiated)
|
||||
except exceptions.NegotiationError, details:
|
||||
self.fail_bad_negotiation(details)
|
||||
|
||||
def reject_nondefault_options():
|
||||
self.reject_negotiation()
|
||||
dialog.destroy()
|
||||
|
||||
dialog = dialogs.YesNoDialog(_('Confirm these session options'),
|
||||
_('The remote client selected these options:\n\n%s\n\nContinue with the session?') % (negotiation.describe_features(ask_user)),
|
||||
on_response_yes = accept_nondefault_options,
|
||||
on_response_no = reject_nondefault_options)
|
||||
else:
|
||||
try:
|
||||
self.accept_e2e_alice(form, negotiated)
|
||||
except exceptions.NegotiationError, details:
|
||||
self.fail_bad_negotiation(details)
|
||||
|
||||
return
|
||||
elif self.status == 'responded-e2e' and form.getType() == 'result':
|
||||
try:
|
||||
self.accept_e2e_bob(form)
|
||||
except exceptions.NegotiationError, details:
|
||||
self.fail_bad_negotiation(details)
|
||||
|
||||
return
|
||||
elif self.status == 'identified-alice' and form.getType() == 'result':
|
||||
try:
|
||||
self.final_steps_alice(form)
|
||||
except exceptions.NegotiationError, details:
|
||||
self.fail_bad_negotiation(details)
|
||||
|
||||
return
|
||||
except exceptions.Cancelled:
|
||||
# user cancelled the negotiation
|
||||
|
||||
self.reject_negotiation()
|
||||
|
||||
return
|
||||
|
||||
if form.getField('terminate') and\
|
||||
form.getField('terminate').getValue() in ('1', 'true'):
|
||||
self.acknowledge_termination()
|
||||
|
||||
self.conn.delete_session(self.jid, self.thread_id)
|
||||
|
||||
return
|
||||
|
||||
# non-esession negotiation. this isn't very useful, but i'm keeping it around
|
||||
# to test my test suite.
|
||||
if form.getType() == 'form':
|
||||
if not self.control:
|
||||
jid, resource = gajim.get_room_and_nick_from_fjid(self.jid)
|
||||
|
||||
account = self.conn.name
|
||||
contact = gajim.contacts.get_contact(account, self.jid, resource)
|
||||
|
||||
if not contact:
|
||||
contact = gajim.contacts.create_contact(jid = jidk,
|
||||
resource = resource, show = self.conn.get_status())
|
||||
|
||||
gajim.interface.new_chat(contact, account,
|
||||
resource = resource, session = self)
|
||||
|
||||
negotiation.FeatureNegotiationWindow(account, self.jid, self, form)
|
||||
|
|
Loading…
Reference in New Issue