restore messages with Zeroconf

This commit is contained in:
Yann Leboulanger 2010-12-19 21:22:29 +01:00
parent 70f7ceb2a2
commit b5b04f2a3d
4 changed files with 116 additions and 182 deletions

View File

@ -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,

View File

@ -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 = []

View File

@ -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):
"""

View File

@ -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)