diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index a081612b6..6c9126039 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -761,6 +761,10 @@ class ConnectionHandlersBase: self._nec_iq_error_received) gajim.ged.register_event_handler('presence-received', ged.CORE, self._nec_presence_received) + gajim.ged.register_event_handler('message-received', ged.CORE, + self._nec_message_received) + gajim.ged.register_event_handler('decrypted-message-received', ged.CORE, + self._nec_decrypted_message_received) def _nec_iq_error_received(self, obj): if obj.conn.name != self.name: @@ -935,6 +939,104 @@ class ConnectionHandlersBase: self.dispatch('DB_ERROR', (pritext, sectext)) our_jid = gajim.get_jid_from_account(self.name) + def _nec_message_received(self, obj): + if obj.conn.name != self.name: + return + if obj.encrypted == 'xep200': + try: + obj.stanza = obj.session.decrypt_stanza(obj.stanza) + obj.msgtxt = obj.stanza.getBody() + except Exception: + gajim.nec.push_incoming_event(FailedDecryptEvent(None, + conn=self, msg_obj=obj)) + return + + if obj.enc_tag and self.USE_GPG: + encmsg = obj.enc_tag.getData() + + keyID = gajim.config.get_per('accounts', self.name, 'keyid') + if keyID: + def decrypt_thread(encmsg, keyID, obj): + decmsg = self.gpg.decrypt(encmsg, keyID) + # \x00 chars are not allowed in C (so in GTK) + obj.msgtxt = helpers.decode_string(decmsg.replace('\x00', + '')) + obj.encrypted = 'xep27' + gajim.thread_interface(decrypt_thread, [encmsg, keyID, obj], + self._on_message_decrypted, [obj]) + return + self._on_message_decrypted(None, obj) + + def _on_message_decrypted(self, output, obj): + gajim.nec.push_incoming_event(DecryptedMessageReceivedEvent(None, + conn=self, msg_obj=obj)) + + def _nec_decrypted_message_received(self, obj): + if obj.conn.name != self.name: + return + + # Receipt requested + # TODO: We shouldn't answer if we're invisible! + contact = gajim.contacts.get_contact(self.name, obj.jid) + nick = obj.resource + gc_contact = gajim.contacts.get_gc_contact(self.name, obj.jid, nick) + if obj.receipt_request_tag and gajim.config.get_per('accounts', + self.name, 'answer_receipts') and ((contact and contact.sub \ + not in (u'to', u'none')) or gc_contact) and obj.mtype != 'error': + receipt = common.xmpp.Message(to=obj.fjid, typ='chat') + receipt.setID(obj.id_) + receipt.setTag('received', namespace='urn:xmpp:receipts', + attrs={'id': obj.id_}) + + if obj.thread_id: + receipt.setThread(obj.thread_id) + self.connection.send(receipt) + + # We got our message's receipt + if obj.receipt_received_tag and obj.session.control and \ + gajim.config.get_per('accounts', self.name, 'request_receipt'): + obj.session.control.conv_textview.hide_xep0184_warning(obj.id_) + + if obj.mtype == 'error': + self.dispatch_error_message(obj.stanza, obj.msgtxt, + obj.session, obj.fjid, obj.timestamp) + return True + elif obj.mtype == 'groupchat': + gajim.nec.push_incoming_event(GcMessageReceivedEvent(None, + conn=self, msg_obj=obj)) + return True + elif obj.invite_tag is not None: + gajim.nec.push_incoming_event(GcInvitationReceivedEvent(None, + conn=self, msg_obj=obj)) + return True + + # process and dispatch an error message + def dispatch_error_message(self, msg, msgtxt, session, frm, tim): + error_msg = msg.getErrorMsg() + + if not error_msg: + error_msg = msgtxt + msgtxt = None + + subject = msg.getSubject() + + if session.is_loggable(): + try: + gajim.logger.write('error', frm, error_msg, tim=tim, + subject=subject) + except exceptions.PysqliteOperationalError, e: + self.dispatch('DB_ERROR', (_('Disk Write Error'), 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.dispatch('DB_ERROR', (pritext, sectext)) + gajim.nec.push_incoming_event(MessageErrorEvent(None, conn=self, + fjid=frm, error_code=msg.getErrorCode(), error_msg=error_msg, + msg=msgtxt, time_=tim, session=session)) + def _LastResultCB(self, con, iq_obj): log.debug('LastResultCB') gajim.nec.push_incoming_event(LastResultReceivedEvent(None, conn=self, @@ -1160,10 +1262,6 @@ ConnectionJingle, ConnectionIBBytestream): ged.CORE, self._nec_unsubscribed_presence_received) gajim.ged.register_event_handler('unsubscribed-presence-received', ged.POSTGUI, self._nec_unsubscribed_presence_received_end) - gajim.ged.register_event_handler('message-received', ged.CORE, - self._nec_message_received) - gajim.ged.register_event_handler('decrypted-message-received', ged.CORE, - self._nec_decrypted_message_received) gajim.ged.register_event_handler('agent-removed', ged.CORE, self._nec_agent_removed) @@ -1435,104 +1533,6 @@ ConnectionJingle, ConnectionIBBytestream): gajim.nec.push_incoming_event(NetworkEvent('raw-message-received', conn=self, stanza=msg, account=self.name)) - def _nec_message_received(self, obj): - if obj.conn.name != self.name: - return - if obj.encrypted == 'xep200': - try: - obj.stanza = obj.session.decrypt_stanza(obj.stanza) - obj.msgtxt = obj.stanza.getBody() - except Exception: - gajim.nec.push_incoming_event(FailedDecryptEvent(None, - conn=self, msg_obj=obj)) - return - - if obj.enc_tag and self.USE_GPG: - encmsg = obj.enc_tag.getData() - - keyID = gajim.config.get_per('accounts', self.name, 'keyid') - if keyID: - def decrypt_thread(encmsg, keyID, obj): - decmsg = self.gpg.decrypt(encmsg, keyID) - # \x00 chars are not allowed in C (so in GTK) - obj.msgtxt = helpers.decode_string(decmsg.replace('\x00', - '')) - obj.encrypted = 'xep27' - gajim.thread_interface(decrypt_thread, [encmsg, keyID, obj], - self._on_message_decrypted, [obj]) - return - self._on_message_decrypted(None, obj) - - def _on_message_decrypted(self, output, obj): - gajim.nec.push_incoming_event(DecryptedMessageReceivedEvent(None, - conn=self, msg_obj=obj)) - - def _nec_decrypted_message_received(self, obj): - if obj.conn.name != self.name: - return - - # Receipt requested - # TODO: We shouldn't answer if we're invisible! - contact = gajim.contacts.get_contact(self.name, obj.jid) - nick = obj.resource - gc_contact = gajim.contacts.get_gc_contact(self.name, obj.jid, nick) - if obj.receipt_request_tag and gajim.config.get_per('accounts', - self.name, 'answer_receipts') and ((contact and contact.sub \ - not in (u'to', u'none')) or gc_contact) and obj.mtype != 'error': - receipt = common.xmpp.Message(to=obj.fjid, typ='chat') - receipt.setID(obj.id_) - receipt.setTag('received', namespace='urn:xmpp:receipts', - attrs={'id': obj.id_}) - - if obj.thread_id: - receipt.setThread(obj.thread_id) - self.connection.send(receipt) - - # We got our message's receipt - if obj.receipt_received_tag and obj.session.control and \ - gajim.config.get_per('accounts', self.name, 'request_receipt'): - obj.session.control.conv_textview.hide_xep0184_warning(obj.id_) - - if obj.mtype == 'error': - self.dispatch_error_message(obj.stanza, obj.msgtxt, - obj.session, obj.fjid, obj.timestamp) - return True - elif obj.mtype == 'groupchat': - gajim.nec.push_incoming_event(GcMessageReceivedEvent(None, - conn=self, msg_obj=obj)) - return True - elif obj.invite_tag is not None: - gajim.nec.push_incoming_event(GcInvitationReceivedEvent(None, - conn=self, msg_obj=obj)) - return True - - # process and dispatch an error message - def dispatch_error_message(self, msg, msgtxt, session, frm, tim): - error_msg = msg.getErrorMsg() - - if not error_msg: - error_msg = msgtxt - msgtxt = None - - subject = msg.getSubject() - - if session.is_loggable(): - try: - gajim.logger.write('error', frm, error_msg, tim=tim, - subject=subject) - except exceptions.PysqliteOperationalError, e: - self.dispatch('DB_ERROR', (_('Disk Write Error'), 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.dispatch('DB_ERROR', (pritext, sectext)) - gajim.nec.push_incoming_event(MessageErrorEvent(None, conn=self, - fjid=frm, error_code=msg.getErrorCode(), error_msg=error_msg, - msg=msgtxt, time_=tim, session=session)) - def _dispatch_gc_msg_with_captcha(self, stanza, msg_obj): msg_obj.stanza = stanza gajim.nec.push_incoming_event(GcMessageReceivedEvent(None, diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index b1e4ea718..d4d549196 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -799,6 +799,7 @@ class ZeroconfPresenceReceivedEvent(nec.NetworkIncomingEvent): base_network_events = [] def generate(self): + self.jid, self.resource = gajim.get_room_and_nick_from_fjid(self.fjid) self.resource = 'local' self.prio = 0 self.keyID = None @@ -1064,6 +1065,11 @@ class ZeroconfMessageReceivedEvent(MessageReceivedEvent): self.fjid = unicode(self.fjid) self.jid, self.resource = gajim.get_room_and_nick_from_fjid(self.fjid) + def generate(self): + self.base_event = nec.NetworkIncomingEvent(None, conn=self.conn, + stanza=self.stanza) + return super(ZeroconfMessageReceivedEvent, self).generate() + class GcInvitationReceivedEvent(nec.NetworkIncomingEvent): name = 'gc-invitation-received' base_network_events = [] diff --git a/src/common/zeroconf/connection_handlers_zeroconf.py b/src/common/zeroconf/connection_handlers_zeroconf.py index 0dfaba3b3..b3568b364 100644 --- a/src/common/zeroconf/connection_handlers_zeroconf.py +++ b/src/common/zeroconf/connection_handlers_zeroconf.py @@ -36,6 +36,7 @@ from common.zeroconf import zeroconf from common.commands import ConnectionCommands from common.pep import ConnectionPEP from common.protocol.bytestream import ConnectionSocks5BytestreamZeroconf +from common.connection_handlers_events import ZeroconfMessageReceivedEvent import logging log = logging.getLogger('gajim.c.z.connection_handlers_zeroconf') @@ -91,82 +92,9 @@ connection_handlers.ConnectionHandlersBase, connection_handlers.ConnectionJingle Called when we receive a message """ log.debug('Zeroconf MessageCB') - - frm = msg.getFrom() - mtype = msg.getType() - thread_id = msg.getThread() - - if not mtype: - mtype = 'normal' - - if frm is None: - for key in self.connection.zeroconf.contacts: - if ip == self.connection.zeroconf.contacts[key][zeroconf.C_ADDRESS]: - frm = key - - frm = unicode(frm) - - session = self.get_or_create_session(frm, thread_id) - - if thread_id and not session.received_thread_id: - session.received_thread_id = True - - if msg.getTag('feature') and msg.getTag('feature').namespace == \ - common.xmpp.NS_FEATURE: - if gajim.HAVE_PYCRYPTO: - self._FeatureNegCB(con, msg, session) - return - - if msg.getTag('init') and msg.getTag('init').namespace == \ - common.xmpp.NS_ESESSION_INIT: - self._InitE2ECB(con, msg, session) - - encrypted = False - tim = msg.getTimestamp() - tim = helpers.datetime_tuple(tim) - tim = time.localtime(timegm(tim)) - - if msg.getTag('c', namespace = common.xmpp.NS_STANZA_CRYPTO): - encrypted = True - - try: - msg = session.decrypt_stanza(msg) - except Exception: - self.dispatch('FAILED_DECRYPT', (frm, tim, session)) - - - msgtxt = msg.getBody() - subject = msg.getSubject() # if not there, it's None - - # invitations - invite = None - encTag = msg.getTag('x', namespace = common.xmpp.NS_ENCRYPTED) - - if not encTag: - invite = msg.getTag('x', namespace = common.xmpp.NS_MUC_USER) - if invite and not invite.getTag('invite'): - invite = None - - if encTag and self.USE_GPG: - #decrypt - encmsg = encTag.getData() - - keyID = gajim.config.get_per('accounts', self.name, 'keyid') - if keyID: - decmsg = self.gpg.decrypt(encmsg, keyID) - # \x00 chars are not allowed in C (so in GTK) - msgtxt = decmsg.replace('\x00', '') - encrypted = True - - if mtype == 'error': - self.dispatch_error_msg(msg, msgtxt, session, frm, tim, subject) - else: - # XXX this shouldn't be hardcoded - if isinstance(session, ChatControlSession): - session.received(frm, msgtxt, tim, encrypted, msg) - else: - session.received(msg) - # END messageCB + gajim.nec.push_incoming_event(ZeroconfMessageReceivedEvent(None, + conn=self, stanza=msg, ip=ip)) + return def store_metacontacts(self, tags): """ diff --git a/src/common/zeroconf/connection_zeroconf.py b/src/common/zeroconf/connection_zeroconf.py index 4ec132bae..28457deeb 100644 --- a/src/common/zeroconf/connection_zeroconf.py +++ b/src/common/zeroconf/connection_zeroconf.py @@ -140,7 +140,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf): jid=key, nickname=self.roster.getName(key), sub='both', ask='no', groups=self.roster.getGroups(key))) gajim.nec.push_incoming_event(ZeroconfPresenceReceivedEvent( - None, conn=self, jid=key, show=self.roster.getStatus(key), + None, conn=self, fjid=key, show=self.roster.getStatus(key), status=self.roster.getMessage(key))) #XXX open chat windows don't get refreshed (full name), add that return self.call_resolve_timeout @@ -152,7 +152,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf): jid=jid, nickname=self.roster.getName(jid), sub='both', ask='no', groups=self.roster.getGroups(jid))) gajim.nec.push_incoming_event(ZeroconfPresenceReceivedEvent( - None, conn=self, jid=jid, show=self.roster.getStatus(jid), + None, conn=self, fjid=jid, show=self.roster.getStatus(jid), status=self.roster.getMessage(jid))) def _on_remove_service(self, jid): @@ -160,7 +160,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf): # 'NOTIFY' (account, (jid, status, status message, resource, priority, # keyID, timestamp, contact_nickname)) gajim.nec.push_incoming_event(ZeroconfPresenceReceivedEvent( - None, conn=self, jid=jid, show='offline', status='')) + None, conn=self, fjid=jid, show='offline', status='')) def _disconnectedReconnCB(self): """ @@ -229,7 +229,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf): jid=jid, nickname=self.roster.getName(jid), sub='both', ask='no', groups=self.roster.getGroups(jid))) gajim.nec.push_incoming_event(ZeroconfPresenceReceivedEvent( - None, conn=self, jid=jid, show=self.roster.getStatus(jid), + None, conn=self, fjid=jid, show=self.roster.getStatus(jid), status=self.roster.getMessage(jid))) self.connected = STATUS_LIST.index(show)