From fedd7dc8e22950f0dbe297443860662368c249d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Araujo?= Date: Mon, 8 Feb 2010 15:08:40 +0100 Subject: convert tabs to spaces in source code thanks to reindent.py holy diff batman! --- src/session.py | 966 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 482 insertions(+), 484 deletions(-) (limited to 'src/session.py') diff --git a/src/session.py b/src/session.py index 1725cc593..ad9f7c4f8 100644 --- a/src/session.py +++ b/src/session.py @@ -38,487 +38,485 @@ 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') - - self.control = None - - def detach_from_control(self): - if self.control: - self.control.set_session(None) - - def acknowledge_termination(self): - self.detach_from_control() - stanza_session.EncryptedStanzaSession.acknowledge_termination(self) - - def terminate(self, send_termination = True): - stanza_session.EncryptedStanzaSession.terminate(self, send_termination) - self.detach_from_control() - - def get_chatstate(self, msg, msgtxt): - """ - Extract chatstate from a stanza - """ - composing_xep = None - chatstate = None - - # chatstates - look for chatstate tags in a message if not delayed - delayed = msg.getTag('x', namespace=common.xmpp.NS_DELAY) is not None - if not delayed: - composing_xep = False - children = msg.getChildren() - for child in children: - if child.getNamespace() == 'http://jabber.org/protocol/chatstates': - chatstate = child.getName() - composing_xep = 'XEP-0085' - break - # No XEP-0085 support, fallback to XEP-0022 - if not chatstate: - chatstate_child = msg.getTag('x', namespace=common.xmpp.NS_EVENT) - if chatstate_child: - chatstate = 'active' - composing_xep = 'XEP-0022' - if not msgtxt and chatstate_child.getTag('composing'): - chatstate = 'composing' - - return (composing_xep, chatstate) - - def received(self, full_jid_with_resource, msgtxt, tim, encrypted, msg): - """ - Dispatch a received stanza - """ - msg_type = msg.getType() - subject = msg.getSubject() - resource = gajim.get_resource_from_jid(full_jid_with_resource) - if self.resource != resource: - self.resource = resource - if self.control and self.control.resource: - self.control.change_resource(self.resource) - - if not msg_type or msg_type not in ('chat', 'groupchat', 'error'): - msg_type = 'normal' - - msg_id = None - - # XEP-0172 User Nickname - user_nick = msg.getTagData('nick') - if not user_nick: - user_nick = '' - - form_node = None - for xtag in msg.getTags('x'): - if xtag.getNamespace() == common.xmpp.NS_DATA: - form_node = xtag - break - - composing_xep, chatstate = self.get_chatstate(msg, msgtxt) - - xhtml = msg.getXHTML() - - if msg_type == 'chat': - if not msg.getTag('body') and chatstate is None: - return - - log_type = 'chat_msg_recv' - else: - log_type = 'single_msg_recv' - - if self.is_loggable() and msgtxt: - try: - msg_id = gajim.logger.write(log_type, full_jid_with_resource, - msgtxt, tim=tim, subject=subject) - except exceptions.PysqliteOperationalError, e: - self.conn.dispatch('ERROR', (_('Disk WriteError'), str(e))) - except exceptions.DatabaseMalformed: - pritext = _('Database Error') - sectext = _('The database file (%s) cannot be read. Try to repair ' - 'it (see http://trac.gajim.org/wiki/DatabaseBackup) or remove ' - 'it (all history will be lost).') % common.logger.LOG_DB_PATH - self.conn.dispatch('ERROR', (pritext, sectext)) - - treat_as = gajim.config.get('treat_incoming_messages') - if treat_as: - msg_type = treat_as - - jid = gajim.get_jid_without_resource(full_jid_with_resource) - resource = gajim.get_resource_from_jid(full_jid_with_resource) - - if gajim.config.get('ignore_incoming_xhtml'): - xhtml = None - if gajim.jid_is_transport(jid): - jid = jid.replace('@', '') - - groupchat_control = gajim.interface.msg_win_mgr.get_gc_control(jid, - self.conn.name) - - if not groupchat_control and \ - jid in gajim.interface.minimized_controls[self.conn.name]: - groupchat_control = gajim.interface.minimized_controls[self.conn.name]\ - [jid] - - pm = False - if groupchat_control and groupchat_control.type_id == \ - message_control.TYPE_GC and resource: - # It's a Private message - pm = True - msg_type = 'pm' - - highest_contact = gajim.contacts.get_contact_with_highest_priority( - self.conn.name, jid) - - # does this resource have the highest priority of any available? - is_highest = not highest_contact or not highest_contact.resource or \ - resource == highest_contact.resource or highest_contact.show == \ - 'offline' - - # Handle chat states - contact = gajim.contacts.get_contact(self.conn.name, jid, resource) - if contact: - if contact.composing_xep != 'XEP-0085': # We cache xep85 support - contact.composing_xep = composing_xep - if self.control and self.control.type_id == message_control.TYPE_CHAT: - if chatstate is not None: - # other peer sent us reply, so he supports jep85 or jep22 - contact.chatstate = chatstate - if contact.our_chatstate == 'ask': # we were jep85 disco? - contact.our_chatstate = 'active' # no more - self.control.handle_incoming_chatstate() - elif contact.chatstate != 'active': - # got no valid jep85 answer, peer does not support it - contact.chatstate = False - elif chatstate == 'active': - # Brand new message, incoming. - contact.our_chatstate = chatstate - contact.chatstate = chatstate - if msg_id: # Do not overwrite an existing msg_id with None - contact.msg_id = msg_id - - # THIS MUST BE AFTER chatstates handling - # AND BEFORE playsound (else we ear sounding on chatstates!) - if not msgtxt: # empty message text - return - - if gajim.config.get_per('accounts', self.conn.name, - 'ignore_unknown_contacts') and not gajim.contacts.get_contacts( - self.conn.name, jid) and not pm: - return - - if not contact: - # contact is not in the roster, create a fake one to display - # notification - contact = gajim.contacts.create_not_in_roster_contact(jid=jid, - account=self.conn.name, resource=resource) - - advanced_notif_num = notify.get_advanced_notification('message_received', - self.conn.name, contact) - - if not pm and is_highest: - jid_of_control = jid - else: - jid_of_control = full_jid_with_resource - - if not self.control: - ctrl = gajim.interface.msg_win_mgr.get_control(jid_of_control, - self.conn.name) - if ctrl: - self.control = ctrl - self.control.set_session(self) - - # Is it a first or next message received ? - first = False - if not self.control and not gajim.events.get_events(self.conn.name, \ - jid_of_control, [msg_type]): - first = True - - if pm: - nickname = resource - if self.control: - # print if a control is open - self.control.print_conversation(msgtxt, tim=tim, xhtml=xhtml, - encrypted=encrypted) - else: - # otherwise pass it off to the control to be queued - groupchat_control.on_private_message(nickname, msgtxt, tim, - xhtml, self, msg_id=msg_id, encrypted=encrypted) - else: - self.roster_message(jid, msgtxt, tim, encrypted, msg_type, - subject, resource, msg_id, user_nick, advanced_notif_num, - xhtml=xhtml, form_node=form_node) - - nickname = gajim.get_name_from_jid(self.conn.name, jid) - - # Check and do wanted notifications - msg = msgtxt - if subject: - msg = _('Subject: %s') % subject + '\n' + msg - focused = False - - if self.control: - parent_win = self.control.parent_win - if parent_win and self.control == parent_win.get_active_control() and \ - parent_win.window.has_focus: - focused = True - - notify.notify('new_message', jid_of_control, self.conn.name, [msg_type, - first, nickname, msg, focused], advanced_notif_num) - - if gajim.interface.remote_ctrl: - gajim.interface.remote_ctrl.raise_signal('NewMessage', (self.conn.name, - [full_jid_with_resource, msgtxt, tim, encrypted, msg_type, subject, - chatstate, msg_id, composing_xep, user_nick, xhtml, form_node])) - - def roster_message(self, jid, msg, tim, encrypted=False, msg_type='', - subject=None, resource='', msg_id=None, user_nick='', - advanced_notif_num=None, xhtml=None, form_node=None): - """ - Display the message or show notification in the roster - """ - contact = None - # if chat window will be for specific resource - resource_for_chat = resource - - fjid = jid - - # Try to catch the contact with correct resource - if resource: - fjid = jid + '/' + resource - contact = gajim.contacts.get_contact(self.conn.name, jid, resource) - - highest_contact = gajim.contacts.get_contact_with_highest_priority( - self.conn.name, jid) - if not contact: - # If there is another resource, it may be a message from an invisible - # resource - lcontact = gajim.contacts.get_contacts(self.conn.name, jid) - if (len(lcontact) > 1 or (lcontact and lcontact[0].resource and \ - lcontact[0].show != 'offline')) and jid.find('@') > 0: - contact = gajim.contacts.copy_contact(highest_contact) - contact.resource = resource - if resource: - fjid = jid + '/' + resource - contact.priority = 0 - contact.show = 'offline' - contact.status = '' - gajim.contacts.add_contact(self.conn.name, contact) - - else: - # Default to highest prio - fjid = jid - resource_for_chat = None - contact = highest_contact - - if not contact: - # contact is not in roster - contact = gajim.interface.roster.add_to_not_in_the_roster( - self.conn.name, jid, user_nick) - - if not self.control: - ctrl = gajim.interface.msg_win_mgr.get_control(fjid, self.conn.name) - if ctrl: - self.control = ctrl - self.control.set_session(self) - else: - # if no control exists and message comes from highest prio, the new - # control shouldn't have a resource - if highest_contact and contact.resource == highest_contact.resource\ - and not jid == gajim.get_jid_from_account(self.conn.name): - fjid = jid - resource_for_chat = None - - # Do we have a queue? - no_queue = len(gajim.events.get_events(self.conn.name, fjid)) == 0 - - popup = helpers.allow_popup_window(self.conn.name, advanced_notif_num) - - if msg_type == 'normal' and popup: # it's single message to be autopopuped - dialogs.SingleMessageWindow(self.conn.name, contact.jid, - action='receive', from_whom=jid, subject=subject, message=msg, - resource=resource, session=self, form_node=form_node) - return - - # We print if window is opened and it's not a single message - if self.control and msg_type != 'normal': - typ = '' - - if msg_type == 'error': - typ = 'error' - - self.control.print_conversation(msg, typ, tim=tim, encrypted=encrypted, - subject=subject, xhtml=xhtml) - - if msg_id: - gajim.logger.set_read_messages([msg_id]) - - return - - # We save it in a queue - type_ = 'chat' - event_type = 'message_received' - - if msg_type == 'normal': - type_ = 'normal' - event_type = 'single_message_received' - - show_in_roster = notify.get_show_in_roster(event_type, self.conn.name, - contact, self) - show_in_systray = notify.get_show_in_systray(event_type, self.conn.name, - contact) - - event = gajim.events.create_event(type_, (msg, subject, msg_type, tim, - encrypted, resource, msg_id, xhtml, self, form_node), - show_in_roster=show_in_roster, show_in_systray=show_in_systray) - - gajim.events.add_event(self.conn.name, fjid, event) - - if popup: - if not self.control: - self.control = gajim.interface.new_chat(contact, - self.conn.name, resource=resource_for_chat, session=self) - - if len(gajim.events.get_events(self.conn.name, fjid)): - self.control.read_queue() - else: - if no_queue: # We didn't have a queue: we change icons - gajim.interface.roster.draw_contact(jid, self.conn.name) - - gajim.interface.roster.show_title() # we show the * or [n] - # Select the big brother contact in roster, it's visible because it has - # events. - family = gajim.contacts.get_metacontacts_family(self.conn.name, jid) - if family: - nearby_family, bb_jid, bb_account = \ - gajim.contacts.get_nearby_family_and_big_brother(family, - self.conn.name) - else: - bb_jid, bb_account = jid, self.conn.name - gajim.interface.roster.select_contact(bb_jid, bb_account) - - # ---- ESessions stuff --- - - 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(): - # 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) - - 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\n' - 'Continue 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(str(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=jid, account=account, - resource=resource, show=self.conn.get_status()) - - gajim.interface.new_chat(contact, account, resource=resource, - session=self) - - negotiation.FeatureNegotiationWindow(account, self.jid, self, form) - -# vim: se ts=3: + def __init__(self, conn, jid, thread_id, type_='chat'): + stanza_session.EncryptedStanzaSession.__init__(self, conn, jid, thread_id, + type_='chat') + + self.control = None + + def detach_from_control(self): + if self.control: + self.control.set_session(None) + + def acknowledge_termination(self): + self.detach_from_control() + stanza_session.EncryptedStanzaSession.acknowledge_termination(self) + + def terminate(self, send_termination = True): + stanza_session.EncryptedStanzaSession.terminate(self, send_termination) + self.detach_from_control() + + def get_chatstate(self, msg, msgtxt): + """ + Extract chatstate from a stanza + """ + composing_xep = None + chatstate = None + + # chatstates - look for chatstate tags in a message if not delayed + delayed = msg.getTag('x', namespace=common.xmpp.NS_DELAY) is not None + if not delayed: + composing_xep = False + children = msg.getChildren() + for child in children: + if child.getNamespace() == 'http://jabber.org/protocol/chatstates': + chatstate = child.getName() + composing_xep = 'XEP-0085' + break + # No XEP-0085 support, fallback to XEP-0022 + if not chatstate: + chatstate_child = msg.getTag('x', namespace=common.xmpp.NS_EVENT) + if chatstate_child: + chatstate = 'active' + composing_xep = 'XEP-0022' + if not msgtxt and chatstate_child.getTag('composing'): + chatstate = 'composing' + + return (composing_xep, chatstate) + + def received(self, full_jid_with_resource, msgtxt, tim, encrypted, msg): + """ + Dispatch a received stanza + """ + msg_type = msg.getType() + subject = msg.getSubject() + resource = gajim.get_resource_from_jid(full_jid_with_resource) + if self.resource != resource: + self.resource = resource + if self.control and self.control.resource: + self.control.change_resource(self.resource) + + if not msg_type or msg_type not in ('chat', 'groupchat', 'error'): + msg_type = 'normal' + + msg_id = None + + # XEP-0172 User Nickname + user_nick = msg.getTagData('nick') + if not user_nick: + user_nick = '' + + form_node = None + for xtag in msg.getTags('x'): + if xtag.getNamespace() == common.xmpp.NS_DATA: + form_node = xtag + break + + composing_xep, chatstate = self.get_chatstate(msg, msgtxt) + + xhtml = msg.getXHTML() + + if msg_type == 'chat': + if not msg.getTag('body') and chatstate is None: + return + + log_type = 'chat_msg_recv' + else: + log_type = 'single_msg_recv' + + if self.is_loggable() and msgtxt: + try: + msg_id = gajim.logger.write(log_type, full_jid_with_resource, + msgtxt, tim=tim, subject=subject) + except exceptions.PysqliteOperationalError, e: + self.conn.dispatch('ERROR', (_('Disk WriteError'), str(e))) + except exceptions.DatabaseMalformed: + pritext = _('Database Error') + sectext = _('The database file (%s) cannot be read. Try to repair ' + 'it (see http://trac.gajim.org/wiki/DatabaseBackup) or remove ' + 'it (all history will be lost).') % common.logger.LOG_DB_PATH + self.conn.dispatch('ERROR', (pritext, sectext)) + + treat_as = gajim.config.get('treat_incoming_messages') + if treat_as: + msg_type = treat_as + + jid = gajim.get_jid_without_resource(full_jid_with_resource) + resource = gajim.get_resource_from_jid(full_jid_with_resource) + + if gajim.config.get('ignore_incoming_xhtml'): + xhtml = None + if gajim.jid_is_transport(jid): + jid = jid.replace('@', '') + + groupchat_control = gajim.interface.msg_win_mgr.get_gc_control(jid, + self.conn.name) + + if not groupchat_control and \ + jid in gajim.interface.minimized_controls[self.conn.name]: + groupchat_control = gajim.interface.minimized_controls[self.conn.name]\ + [jid] + + pm = False + if groupchat_control and groupchat_control.type_id == \ + message_control.TYPE_GC and resource: + # It's a Private message + pm = True + msg_type = 'pm' + + highest_contact = gajim.contacts.get_contact_with_highest_priority( + self.conn.name, jid) + + # does this resource have the highest priority of any available? + is_highest = not highest_contact or not highest_contact.resource or \ + resource == highest_contact.resource or highest_contact.show == \ + 'offline' + + # Handle chat states + contact = gajim.contacts.get_contact(self.conn.name, jid, resource) + if contact: + if contact.composing_xep != 'XEP-0085': # We cache xep85 support + contact.composing_xep = composing_xep + if self.control and self.control.type_id == message_control.TYPE_CHAT: + if chatstate is not None: + # other peer sent us reply, so he supports jep85 or jep22 + contact.chatstate = chatstate + if contact.our_chatstate == 'ask': # we were jep85 disco? + contact.our_chatstate = 'active' # no more + self.control.handle_incoming_chatstate() + elif contact.chatstate != 'active': + # got no valid jep85 answer, peer does not support it + contact.chatstate = False + elif chatstate == 'active': + # Brand new message, incoming. + contact.our_chatstate = chatstate + contact.chatstate = chatstate + if msg_id: # Do not overwrite an existing msg_id with None + contact.msg_id = msg_id + + # THIS MUST BE AFTER chatstates handling + # AND BEFORE playsound (else we ear sounding on chatstates!) + if not msgtxt: # empty message text + return + + if gajim.config.get_per('accounts', self.conn.name, + 'ignore_unknown_contacts') and not gajim.contacts.get_contacts( + self.conn.name, jid) and not pm: + return + + if not contact: + # contact is not in the roster, create a fake one to display + # notification + contact = gajim.contacts.create_not_in_roster_contact(jid=jid, + account=self.conn.name, resource=resource) + + advanced_notif_num = notify.get_advanced_notification('message_received', + self.conn.name, contact) + + if not pm and is_highest: + jid_of_control = jid + else: + jid_of_control = full_jid_with_resource + + if not self.control: + ctrl = gajim.interface.msg_win_mgr.get_control(jid_of_control, + self.conn.name) + if ctrl: + self.control = ctrl + self.control.set_session(self) + + # Is it a first or next message received ? + first = False + if not self.control and not gajim.events.get_events(self.conn.name, \ + jid_of_control, [msg_type]): + first = True + + if pm: + nickname = resource + if self.control: + # print if a control is open + self.control.print_conversation(msgtxt, tim=tim, xhtml=xhtml, + encrypted=encrypted) + else: + # otherwise pass it off to the control to be queued + groupchat_control.on_private_message(nickname, msgtxt, tim, + xhtml, self, msg_id=msg_id, encrypted=encrypted) + else: + self.roster_message(jid, msgtxt, tim, encrypted, msg_type, + subject, resource, msg_id, user_nick, advanced_notif_num, + xhtml=xhtml, form_node=form_node) + + nickname = gajim.get_name_from_jid(self.conn.name, jid) + + # Check and do wanted notifications + msg = msgtxt + if subject: + msg = _('Subject: %s') % subject + '\n' + msg + focused = False + + if self.control: + parent_win = self.control.parent_win + if parent_win and self.control == parent_win.get_active_control() and \ + parent_win.window.has_focus: + focused = True + + notify.notify('new_message', jid_of_control, self.conn.name, [msg_type, + first, nickname, msg, focused], advanced_notif_num) + + if gajim.interface.remote_ctrl: + gajim.interface.remote_ctrl.raise_signal('NewMessage', (self.conn.name, + [full_jid_with_resource, msgtxt, tim, encrypted, msg_type, subject, + chatstate, msg_id, composing_xep, user_nick, xhtml, form_node])) + + def roster_message(self, jid, msg, tim, encrypted=False, msg_type='', + subject=None, resource='', msg_id=None, user_nick='', + advanced_notif_num=None, xhtml=None, form_node=None): + """ + Display the message or show notification in the roster + """ + contact = None + # if chat window will be for specific resource + resource_for_chat = resource + + fjid = jid + + # Try to catch the contact with correct resource + if resource: + fjid = jid + '/' + resource + contact = gajim.contacts.get_contact(self.conn.name, jid, resource) + + highest_contact = gajim.contacts.get_contact_with_highest_priority( + self.conn.name, jid) + if not contact: + # If there is another resource, it may be a message from an invisible + # resource + lcontact = gajim.contacts.get_contacts(self.conn.name, jid) + if (len(lcontact) > 1 or (lcontact and lcontact[0].resource and \ + lcontact[0].show != 'offline')) and jid.find('@') > 0: + contact = gajim.contacts.copy_contact(highest_contact) + contact.resource = resource + if resource: + fjid = jid + '/' + resource + contact.priority = 0 + contact.show = 'offline' + contact.status = '' + gajim.contacts.add_contact(self.conn.name, contact) + + else: + # Default to highest prio + fjid = jid + resource_for_chat = None + contact = highest_contact + + if not contact: + # contact is not in roster + contact = gajim.interface.roster.add_to_not_in_the_roster( + self.conn.name, jid, user_nick) + + if not self.control: + ctrl = gajim.interface.msg_win_mgr.get_control(fjid, self.conn.name) + if ctrl: + self.control = ctrl + self.control.set_session(self) + else: + # if no control exists and message comes from highest prio, the new + # control shouldn't have a resource + if highest_contact and contact.resource == highest_contact.resource\ + and not jid == gajim.get_jid_from_account(self.conn.name): + fjid = jid + resource_for_chat = None + + # Do we have a queue? + no_queue = len(gajim.events.get_events(self.conn.name, fjid)) == 0 + + popup = helpers.allow_popup_window(self.conn.name, advanced_notif_num) + + if msg_type == 'normal' and popup: # it's single message to be autopopuped + dialogs.SingleMessageWindow(self.conn.name, contact.jid, + action='receive', from_whom=jid, subject=subject, message=msg, + resource=resource, session=self, form_node=form_node) + return + + # We print if window is opened and it's not a single message + if self.control and msg_type != 'normal': + typ = '' + + if msg_type == 'error': + typ = 'error' + + self.control.print_conversation(msg, typ, tim=tim, encrypted=encrypted, + subject=subject, xhtml=xhtml) + + if msg_id: + gajim.logger.set_read_messages([msg_id]) + + return + + # We save it in a queue + type_ = 'chat' + event_type = 'message_received' + + if msg_type == 'normal': + type_ = 'normal' + event_type = 'single_message_received' + + show_in_roster = notify.get_show_in_roster(event_type, self.conn.name, + contact, self) + show_in_systray = notify.get_show_in_systray(event_type, self.conn.name, + contact) + + event = gajim.events.create_event(type_, (msg, subject, msg_type, tim, + encrypted, resource, msg_id, xhtml, self, form_node), + show_in_roster=show_in_roster, show_in_systray=show_in_systray) + + gajim.events.add_event(self.conn.name, fjid, event) + + if popup: + if not self.control: + self.control = gajim.interface.new_chat(contact, + self.conn.name, resource=resource_for_chat, session=self) + + if len(gajim.events.get_events(self.conn.name, fjid)): + self.control.read_queue() + else: + if no_queue: # We didn't have a queue: we change icons + gajim.interface.roster.draw_contact(jid, self.conn.name) + + gajim.interface.roster.show_title() # we show the * or [n] + # Select the big brother contact in roster, it's visible because it has + # events. + family = gajim.contacts.get_metacontacts_family(self.conn.name, jid) + if family: + nearby_family, bb_jid, bb_account = \ + gajim.contacts.get_nearby_family_and_big_brother(family, + self.conn.name) + else: + bb_jid, bb_account = jid, self.conn.name + gajim.interface.roster.select_contact(bb_jid, bb_account) + + # ---- ESessions stuff --- + + 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(): + # 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) + + 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\n' + 'Continue 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(str(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=jid, account=account, + resource=resource, show=self.conn.get_status()) + + gajim.interface.new_chat(contact, account, resource=resource, + session=self) + + negotiation.FeatureNegotiationWindow(account, self.jid, self, form) -- cgit v1.2.3