From 5095bc6598e6090104ef4c5b2f5bc90f81bf5031 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Thu, 28 Nov 2013 21:24:17 +0100 Subject: [PATCH] support direct invitation (XEP-0249). Fixes #7581 --- src/common/connection.py | 17 +++++-- src/common/connection_handlers_events.py | 57 +++++++++++++++++------- src/common/contacts.py | 1 + src/common/gajim.py | 2 +- src/roster_window.py | 2 +- 5 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/common/connection.py b/src/common/connection.py index d07bed3ec..6119a32e1 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -1383,8 +1383,7 @@ class Connection(CommonConnection, ConnectionHandlers): errnum = con.Connection.ssl_errnum except AttributeError: errnum = [] # we don't have an errnum - i = 0 - for er in errnum: + for i, er in enumerate(errnum): if er > 0 and str(er) not in gajim.config.get_per('accounts', self.name, 'ignore_ssl_errors').split(): text = _('The authenticity of the %s certificate could be ' @@ -1399,7 +1398,6 @@ class Connection(CommonConnection, ConnectionHandlers): fingerprint=con.Connection.ssl_fingerprint_sha1[i], certificate=con.Connection.ssl_certificate[i])) return True - i += 1 if len(con.Connection.ssl_fingerprint_sha1): saved_fingerprint = gajim.config.get_per('accounts', self.name, 'ssl_fingerprint_sha1') @@ -2846,6 +2844,19 @@ class Connection(CommonConnection, ConnectionHandlers): """ Send invitation """ + contact = gajim.contacts.get_contact_from_full_jid(self.name, to) + if contact and contact.supports(nbxmpp.NS_CONFERENCE): + # send direct invite + message=nbxmpp.Message(to=to) + attrs = {'jid': room} + if reason: + attrs['reason'] = reason + if continue_tag: + attrs['continue'] = 'true' + c = message.addChild(name='x', attrs=attrs, + namespace=nbxmpp.NS_CONFERENCE) + self.connection.send(message) + return message=nbxmpp.Message(to=room) c = message.addChild(name='x', namespace=nbxmpp.NS_MUC_USER) c = c.addChild(name='invite', attrs={'to': to}) diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index b9ecf6808..16c4e1be7 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -1077,10 +1077,15 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.invite_tag = None self.decline_tag = None if not self.enc_tag: + # Direct invitation? self.invite_tag = self.stanza.getTag('x', - namespace=nbxmpp.NS_MUC_USER) - if self.invite_tag and not self.invite_tag.getTag('invite'): - self.invite_tag = None + namespace=nbxmpp.NS_CONFERENCE) + # Mediated invitation? + if not self.invite_tag: + self.invite_tag = self.stanza.getTag('x', + namespace=nbxmpp.NS_MUC_USER) + if self.invite_tag and not self.invite_tag.getTag('invite'): + self.invite_tag = None self.decline_tag = self.stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER) @@ -1193,25 +1198,47 @@ class GcInvitationReceivedEvent(nec.NetworkIncomingEvent): base_network_events = [] def generate(self): - self.room_jid = self.msg_obj.fjid + invite_tag = self.msg_obj.invite_tag + if invite_tag.getNamespace() == nbxmpp.NS_CONFERENCE: + # direct invitation + try: + self.room_jid = helpers.parse_jid(invite_tag.getAttr('jid')) + except helpers.InvalidFormat: + log.warn('Invalid JID: %s, ignoring it' % invite_tag.getAttr( + 'jid')) + return + self.jid_from = self.msg_obj.fjid + self.reason = invite_tag.getAttr('reason') + self.password = invite_tag.getAttr('password') + self.is_continued = False + if invite_tag.getAttr('continue') == 'true': + self.is_continued = True + else + self.room_jid = self.msg_obj.fjid + item = self.msg_obj.invite_tag.getTag('invite') + try: + self.jid_from = helpers.parse_jid(item.getAttr('from')) + except helpers.InvalidFormat: + log.warning('Invalid JID: %s, ignoring it' % item.getAttr( + 'from')) + return - item = self.msg_obj.invite_tag.getTag('invite') - try: - self.jid_from = helpers.parse_jid(item.getAttr('from')) - except helpers.InvalidFormat: - log.warning('Invalid JID: %s, ignoring it' % item.getAttr('from')) + self.reason = item.getTagData('reason') + self.password = invite_tag.getTagData('password') + + self.is_continued = False + if item.getTag('continue'): + self.is_continued = True + + if self.room_jid in gajim.gc_connected[self.conn.name] and \ + gajim.gc_connected[self.conn.name][self.room_jid]: + # We are already in groupchat. Ignore invitation return jid = gajim.get_jid_without_resource(self.jid_from) if gajim.config.get_per('accounts', self.conn.name, 'ignore_unknown_contacts') and not gajim.contacts.get_contacts( self.conn.name, jid): return - self.reason = item.getTagData('reason') - self.password = self.msg_obj.invite_tag.getTagData('password') - - self.is_continued = False - if item.getTag('continue'): - self.is_continued = True return True diff --git a/src/common/contacts.py b/src/common/contacts.py index d51d449f9..dc5d841a1 100644 --- a/src/common/contacts.py +++ b/src/common/contacts.py @@ -488,6 +488,7 @@ class Contacts(): for c in self._contacts[jid]: if c.resource == resource: return c + return self._contacts[jid][0] def iter_contacts(self): for jid in list(self._contacts.keys()): diff --git a/src/common/gajim.py b/src/common/gajim.py index 0b83479d9..f71eb3240 100644 --- a/src/common/gajim.py +++ b/src/common/gajim.py @@ -212,7 +212,7 @@ gajim_common_features = [nbxmpp.NS_BYTESTREAM, nbxmpp.NS_SI, nbxmpp.NS_FILE, nbxmpp.NS_SSN, nbxmpp.NS_MOOD, nbxmpp.NS_ACTIVITY, nbxmpp.NS_NICK, nbxmpp.NS_ROSTERX, nbxmpp.NS_SECLABEL, nbxmpp.NS_HASHES, nbxmpp.NS_HASHES_MD5, nbxmpp.NS_HASHES_SHA1, nbxmpp.NS_HASHES_SHA256, - nbxmpp.NS_HASHES_SHA512, nbxmpp.NS_CORRECT] + nbxmpp.NS_HASHES_SHA512, nbxmpp.NS_CORRECT, nbxmpp.NS_CONFERENCE] # Optional features gajim supports per account gajim_optional_features = {} diff --git a/src/roster_window.py b/src/roster_window.py index 61ef13772..4bf166e76 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -3335,7 +3335,7 @@ class RosterWindow: break def on_invite_to_room(self, widget, list_, room_jid, room_account, - resource=None): + resource=None): """ Resource parameter MUST NOT be used if more than one contact in list """