Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉric Araujo <merwok@netwok.org>2010-02-10 19:59:17 +0300
committerÉric Araujo <merwok@netwok.org>2010-02-10 19:59:17 +0300
commit0408b35cfb1d92217d53d2a6e512c56e2206bf98 (patch)
tree9075583f2f0a2bb20bf37ec96d9ed3f6f88cbf83 /src/session.py
parentd1a9a6983a7f120a55a668f8165da802e43586e9 (diff)
convert tabs to spaces in source code thanks to reindent.py
also use 2to3 -f ws_comma to fix some whitespace
Diffstat (limited to 'src/session.py')
-rw-r--r--src/session.py998
1 files changed, 498 insertions, 500 deletions
diff --git a/src/session.py b/src/session.py
index 6a830fe13..0154df6c5 100644
--- a/src/session.py
+++ b/src/session.py
@@ -38,503 +38,501 @@ 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):
- '''extracts chatstate from a <message/> 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 <message> 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:
- if form.getType() == 'form' and 'security' in form.asDict():
- security_options = [x[1] for x in form.getField('security').getOptions()]
- if security_options == ['none']:
- self.respond_archiving(form)
- else:
- # bob responds
-
- # 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
-
- elif self.status == 'requested-archiving' and form.getType() == \
- 'submit':
- try:
- self.archiving_accepted(form)
- except exceptions.NegotiationError, details:
- self.fail_bad_negotiation(details)
-
- 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-archiving' and form.getType() == \
- 'result':
- try:
- self.we_accept_archiving(form)
- 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):
+ '''extracts chatstate from a <message/> 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 <message> 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:
+ if form.getType() == 'form' and 'security' in form.asDict():
+ security_options = [x[1] for x in form.getField('security').getOptions()]
+ if security_options == ['none']:
+ self.respond_archiving(form)
+ else:
+ # bob responds
+
+ # 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
+
+ elif self.status == 'requested-archiving' and form.getType() == \
+ 'submit':
+ try:
+ self.archiving_accepted(form)
+ except exceptions.NegotiationError, details:
+ self.fail_bad_negotiation(details)
+
+ 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-archiving' and form.getType() == \
+ 'result':
+ try:
+ self.we_accept_archiving(form)
+ 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)