diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index b0a1ae75c..14d405dc5 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -1116,6 +1116,16 @@ ConnectionJingle, ConnectionIBBytestream): self._nec_ping_received) gajim.ged.register_event_handler('presence-received', ged.CORE, self._nec_presence_received) + gajim.ged.register_event_handler('subscribe-presence-received', + ged.CORE, self._nec_subscribe_presence_received) + gajim.ged.register_event_handler('subscribed-presence-received', + ged.CORE, self._nec_subscribed_presence_received) + gajim.ged.register_event_handler('subscribed-presence-received', + ged.POSTGUI, self._nec_subscribed_presence_received_end) + gajim.ged.register_event_handler('unsubscribed-presence-received', + ged.CORE, self._nec_unsubscribed_presence_received) + gajim.ged.register_event_handler('unsubscribed-presence-received', + ged.POSTGUI, self._nec_unsubscribed_presence_received_end) def build_http_auth_answer(self, iq_obj, answer): if not self.connection or self.connected < 2: @@ -1869,6 +1879,94 @@ ConnectionJingle, ConnectionIBBytestream): sess.terminate_e2e() self.delete_session(jid, sess.thread_id) + def _nec_subscribe_presence_received(self, obj): + account = obj.conn.name + if account != self.name: + return + if gajim.jid_is_transport(obj.fjid) and obj.fjid in \ + self.agent_registrations: + self.agent_registrations[obj.fjid]['sub_received'] = True + if not self.agent_registrations[obj.fjid]['roster_push']: + # We'll reply after roster push result + return True + if gajim.config.get_per('accounts', self.name, 'autoauth') or \ + gajim.jid_is_transport(obj.fjid) or obj.jid in self.jids_for_auto_auth \ + or obj.transport_auto_auth: + if self.connection: + p = xmpp.Presence(obj.fjid, 'subscribed') + p = self.add_sha(p) + self.connection.send(p) + if gajim.jid_is_transport(obj.fjid) or obj.transport_auto_auth: + #TODO!?!? + #self.show = 'offline' + #self.status = 'offline' + #emit NOTIFY + pass + if obj.transport_auto_auth: + self.automatically_added.append(obj.jid) + self.request_subscription(obj.jid, name=obj.user_nick) + return True + if not obj.status: + obj.status = _('I would like to add you to my roster.') + + def _nec_subscribed_presence_received(self, obj): + account = obj.conn.name + if account != self.name: + return + # BE CAREFUL: no con.updateRosterItem() in a callback + if obj.jid in self.automatically_added: + self.automatically_added.remove(obj.jid) + return True + # detect a subscription loop + if obj.jid not in self.subscribed_events: + self.subscribed_events[obj.jid] = [] + self.subscribed_events[obj.jid].append(time_time()) + block = False + if len(self.subscribed_events[obj.jid]) > 5: + if time_time() - self.subscribed_events[obj.jid][0] < 5: + block = True + self.subscribed_events[obj.jid] = \ + self.subscribed_events[obj.jid][1:] + if block: + gajim.config.set_per('account', self.name, 'dont_ack_subscription', + True) + return True + + def _nec_subscribed_presence_received_end(self, obj): + account = obj.conn.name + if account != self.name: + return + if not gajim.config.get_per('accounts', account, + 'dont_ack_subscription'): + self.ack_subscribed(obj.jid) + + def _nec_unsubscribed_presence_received(self, obj): + account = obj.conn.name + if account != self.name: + return + # detect a unsubscription loop + if obj.jid not in self.subscribed_events: + self.subscribed_events[obj.jid] = [] + self.subscribed_events[obj.jid].append(time_time()) + block = False + if len(self.subscribed_events[obj.jid]) > 5: + if time_time() - self.subscribed_events[obj.jid][0] < 5: + block = True + self.subscribed_events[obj.jid] = \ + self.subscribed_events[obj.jid][1:] + if block: + gajim.config.set_per('account', self.name, 'dont_ack_subscription', + True) + return True + + def _nec_unsubscribed_presence_received_end(self, obj): + account = obj.conn.name + if account != self.name: + return + if not gajim.config.get_per('accounts', account, + 'dont_ack_subscription'): + self.ack_unsubscribed(obj.jid) + def _StanzaArrivedCB(self, con, obj): self.last_io = gajim.idlequeue.current_time() diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index 9665162ee..53160a3f0 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -624,8 +624,8 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): except Exception: if self.iq_obj.getTag('error') and self.iq_obj.getTag('error').\ getTag('jid-malformed'): - # wrong jid, we probably tried to change our nick in a room to a non - # valid one + # wrong jid, we probably tried to change our nick in a room to a + # non valid one who = str(self.iq_obj.getFrom()) jid_stripped, resource = gajim.get_room_and_nick_from_fjid(who) self.conn.dispatch('GC_MSG', (jid_stripped, @@ -641,7 +641,7 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): # XEP-0172 User Nickname self.user_nick = self.iq_obj.getTagData('nick') or '' self.contact_nickname = None - transport_auto_auth = False + self.transport_auto_auth = False # XEP-0203 delay_tag = self.iq_obj.getTag('delay', namespace=xmpp.NS_DELAY2) if delay_tag: @@ -668,12 +668,12 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): agent = gajim.get_server_from_jid(self.jid) if self.conn.connection.getRoster().getItem(agent): # to be sure it's a transport contact - transport_auto_auth = True + self.transport_auto_auth = True if not self.is_gc and self.id_ and self.id_.startswith('gajim_muc_') \ and self.ptype == 'error': - # Error presences may not include sent stanza, so we don't detect it's - # a muc preence. So detect it by ID + # Error presences may not include sent stanza, so we don't detect + # it's a muc presence. So detect it by ID h = hmac.new(self.conn.secret_hmac, self.jid).hexdigest()[:6] if self.id_.split('_')[-1] == h: self.is_gc = True @@ -706,74 +706,17 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): return if self.ptype == 'subscribe': - log.debug('subscribe request from %s' % self.fjid) - if self.fjid.find('@') <= 0 and self.fjid in \ - self.conn.agent_registrations: - self.conn.agent_registrations[self.fjid]['sub_received'] = True - if not self.conn.agent_registrations[self.fjid]['roster_push']: - # We'll reply after roster push result - return - if gajim.config.get_per('accounts', self.conn.name, 'autoauth') or \ - self.fjid.find('@') <= 0 or self.jid in \ - self.conn.jids_for_auto_auth or transport_auto_auth: - if self.conn.connection: - p = xmpp.Presence(self.fjid, 'subscribed') - p = self.conn.add_sha(p) - self.conn.connection.send(p) - if self.fjid.find('@') <= 0 or transport_auto_auth: - self.show = 'offline' - self.status = 'offline' - return True - - if transport_auto_auth: - self.conn.automatically_added.append(self.jid) - self.conn.request_subscription(self.jid, - name=self.user_nick) - else: - if not self.status: - self.status = _('I would like to add you to my roster.') - self.conn.dispatch('SUBSCRIBE', (self.jid, self.status, - self.user_nick)) + gajim.nec.push_incoming_event(SubscribePresenceReceivedEvent(None, + conn=self.conn, iq_obj=self.iq_obj, presence_obj=self)) elif self.ptype == 'subscribed': - if self.jid in self.conn.automatically_added: - self.conn.automatically_added.remove(self.jid) - else: - # detect a subscription loop - if self.jid not in self.conn.subscribed_events: - self.conn.subscribed_events[self.jid] = [] - self.conn.subscribed_events[self.jid].append(time_time()) - block = False - if len(self.conn.subscribed_events[self.jid]) > 5: - if time_time() - self.subscribed_events[self.jid][0] < 5: - block = True - self.conn.subscribed_events[self.jid] = \ - self.conn.subscribed_events[self.jid][1:] - if block: - gajim.config.set_per('account', self.conn.name, - 'dont_ack_subscription', True) - else: - self.conn.dispatch('SUBSCRIBED', (self.jid, self.resource)) # BE CAREFUL: no con.updateRosterItem() in a callback - log.debug(_('we are now subscribed to %s') % self.jid) + gajim.nec.push_incoming_event(SubscribedPresenceReceivedEvent(None, + conn=self.conn, iq_obj=self.iq_obj, presence_obj=self)) elif self.ptype == 'unsubscribe': log.debug(_('unsubscribe request from %s') % self.jid) elif self.ptype == 'unsubscribed': - log.debug(_('we are now unsubscribed from %s') % self.jid) - # detect a unsubscription loop - if self.jid not in self.conn.subscribed_events: - self.conn.subscribed_events[self.jid] = [] - self.conn.subscribed_events[self.jid].append(time_time()) - block = False - if len(self.conn.subscribed_events[self.jid]) > 5: - if time_time() - self.conn.subscribed_events[self.jid][0] < 5: - block = True - self.conn.subscribed_events[self.jid] = \ - self.conn.subscribed_events[self.jid][1:] - if block: - gajim.config.set_per('account', self.conn.name, - 'dont_ack_subscription', True) - else: - self.conn.dispatch('UNSUBSCRIBED', self.jid) + gajim.nec.push_incoming_event(UnsubscribedPresenceReceivedEvent( + None, conn=self.conn, iq_obj=self.iq_obj, presence_obj=self)) elif self.ptype == 'error': errmsg = self.iq_obj.getError() errcode = self.iq_obj.getErrorCode() @@ -934,3 +877,32 @@ class GcPresenceReceivedEvent(nec.NetworkIncomingEvent): self.actor = self.iq_obj.getActor() self.new_nick = self.iq_obj.getNewNick() return True + +class SubscribePresenceReceivedEvent(nec.NetworkIncomingEvent): + name = 'subscribe-presence-received' + base_network_events = [] + + def generate(self): + self.jid = self.presence_obj.jid + self.fjid = self.presence_obj.fjid + self.status = self.presence_obj.status + self.transport_auto_auth = self.presence_obj.transport_auto_auth + self.user_nick = self.presence_obj.user_nick + return True + +class SubscribedPresenceReceivedEvent(nec.NetworkIncomingEvent): + name = 'subscribed-presence-received' + base_network_events = [] + + def generate(self): + self.jid = self.presence_obj.jid + self.resource = self.presence_obj.resource + return True + +class UnsubscribedPresenceReceivedEvent(nec.NetworkIncomingEvent): + name = 'unsubscribed-presence-received' + base_network_events = [] + + def generate(self): + self.jid = self.presence_obj.jid + return True diff --git a/src/gui_interface.py b/src/gui_interface.py index 19f5ec1ad..f3016363f 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -520,56 +520,48 @@ class Interface: array[4].roster_message(array[0], msg, array[3], account, msg_type='error') - def handle_event_subscribe(self, account, array): + def handle_event_subscribe_presence(self, obj): #('SUBSCRIBE', account, (jid, text, user_nick)) user_nick is JEP-0172 - if self.remote_ctrl: - self.remote_ctrl.raise_signal('Subscribe', (account, array)) - - jid = array[0] - text = array[1] - nick = array[2] + account = obj.conn.name if helpers.allow_popup_window(account) or not self.systray_enabled: - dialogs.SubscriptionRequestWindow(jid, text, account, nick) + dialogs.SubscriptionRequestWindow(obj.jid, obj.status, account, + obj.user_nick) return - self.add_event(account, jid, 'subscription_request', (text, nick)) + self.add_event(account, obj.jid, 'subscription_request', (obj.status, + obj.user_nick)) if helpers.allow_showing_notification(account): path = gtkgui_helpers.get_icon_path('gajim-subscription_request', 48) event_type = _('Subscription request') - notify.popup(event_type, jid, account, 'subscription_request', path, - event_type, jid) + notify.popup(event_type, obj.jid, account, 'subscription_request', + path, event_type, obj.jid) - def handle_event_subscribed(self, account, array): + def handle_event_subscribed_presence(self, obj): #('SUBSCRIBED', account, (jid, resource)) - jid = array[0] - if jid in gajim.contacts.get_jid_list(account): - c = gajim.contacts.get_first_contact_from_jid(account, jid) - c.resource = array[1] + account = obj.conn.name + if obj.jid in gajim.contacts.get_jid_list(account): + c = gajim.contacts.get_first_contact_from_jid(account, obj.jid) + c.resource = obj.resource self.roster.remove_contact_from_groups(c.jid, account, [_('Not in Roster'), _('Observers')], update=False) else: keyID = '' attached_keys = gajim.config.get_per('accounts', account, 'attached_gpg_keys').split() - if jid in attached_keys: - keyID = attached_keys[attached_keys.index(jid) + 1] - name = jid.split('@', 1)[0] + if obj.jid in attached_keys: + keyID = attached_keys[attached_keys.index(obj.jid) + 1] + name = obj.jid.split('@', 1)[0] name = name.split('%', 1)[0] - contact1 = gajim.contacts.create_contact(jid=jid, account=account, - name=name, groups=[], show='online', status='online', ask='to', - resource=array[1], keyID=keyID) + contact1 = gajim.contacts.create_contact(jid=obj.jid, + account=account, name=name, groups=[], show='online', + status='online', ask='to', resource=obj.resource, keyID=keyID) gajim.contacts.add_contact(account, contact1) - self.roster.add_contact(jid, account) + self.roster.add_contact(obj.jid, account) dialogs.InformationDialog(_('Authorization accepted'), _('The contact "%s" has authorized you to see his or her status.') - % jid) - if not gajim.config.get_per('accounts', account, - 'dont_ack_subscription'): - gajim.connections[account].ack_subscribed(jid) - if self.remote_ctrl: - self.remote_ctrl.raise_signal('Subscribed', (account, array)) + % obj.jid) def show_unsubscribed_dialog(self, account, contact): def on_yes(is_checked, list_): @@ -583,13 +575,10 @@ class Interface: # FIXME: Per RFC 3921, we can "deny" ack as well, but the GUI does # not show deny - def handle_event_unsubscribed(self, account, jid): + def handle_event_unsubscribed_presence(self, obj): #('UNSUBSCRIBED', account, jid) - gajim.connections[account].ack_unsubscribed(jid) - if self.remote_ctrl: - self.remote_ctrl.raise_signal('Unsubscribed', (account, jid)) - - contact = gajim.contacts.get_first_contact_from_jid(account, jid) + account = obj.conn.name + contact = gajim.contacts.get_first_contact_from_jid(account, obj.jid) if not contact: return @@ -597,13 +586,13 @@ class Interface: self.show_unsubscribed_dialog(account, contact) return - self.add_event(account, jid, 'unsubscribed', contact) + self.add_event(account, obj.jid, 'unsubscribed', contact) if helpers.allow_showing_notification(account): path = gtkgui_helpers.get_icon_path('gajim-unsubscribed', 48) event_type = _('Unsubscribed') - notify.popup(event_type, jid, account, 'unsubscribed', path, - event_type, jid) + notify.popup(event_type, obj.jid, account, 'unsubscribed', path, + event_type, obj.jid) def handle_event_agent_removed(self, account, agent): # remove transport's contacts from treeview @@ -1911,9 +1900,6 @@ class Interface: 'MSGERROR': [self.handle_event_msgerror], 'MSGSENT': [self.handle_event_msgsent], 'MSGNOTSENT': [self.handle_event_msgnotsent], - 'SUBSCRIBED': [self.handle_event_subscribed], - 'UNSUBSCRIBED': [self.handle_event_unsubscribed], - 'SUBSCRIBE': [self.handle_event_subscribe], 'AGENT_REMOVED': [self.handle_event_agent_removed], 'REGISTER_AGENT_INFO': [self.handle_event_register_agent_info], 'AGENT_INFO_ITEMS': [self.handle_event_agent_info_items], @@ -1985,6 +1971,12 @@ class Interface: 'roster-item-exchange-received': \ [self.handle_event_roster_item_exchange], 'stream-conflict-received': [self.handle_event_resource_conflict], + 'subscribe-presence-received': [ + self.handle_event_subscribe_presence], + 'subscribed-presence-received': [ + self.handle_event_subscribed_presence], + 'unsubscribed-presence-received': [ + self.handle_event_unsubscribed_presence], } def register_core_handlers(self): diff --git a/src/remote_control.py b/src/remote_control.py index e6d7a723d..d3b5e7011 100644 --- a/src/remote_control.py +++ b/src/remote_control.py @@ -117,6 +117,12 @@ class Remote: self.on_roster_info) gajim.ged.register_event_handler('presence-received', ged.POSTGUI, self.on_presence_received) + gajim.ged.register_event_handler('subscribe-presence-received', + ged.POSTGUI, self.on_subscribe_presence_received) + gajim.ged.register_event_handler('subscribed-presence-received', + ged.POSTGUI, self.on_subscribed_presence_received) + gajim.ged.register_event_handler('unsubscribed-presence-received', + ged.POSTGUI, self.on_unsubscribed_presence_received) def on_last_status_time(self, obj): self.raise_signal('LastStatusTime', (obj.conn.name, [ @@ -151,6 +157,17 @@ class Remote: obj.status, obj.resource, obj.prio, obj.keyID, obj.timestamp, obj.contact_nickname])) + def on_subscribe_presence_received(self, obj): + self.raise_signal('Subscribe', (obj.conn.name, [obj.jid, obj.status, + obj.user_nick])) + + def on_subscribed_presence_received(self, obj): + self.raise_signal('Subscribed', (obj.conn.name, [obj.jid, + obj.resource])) + + def on_unsubscribed_presence_received(self, obj): + self.raise_signal('Unsubscribed', (obj.conn.name, obj.jid)) + def raise_signal(self, signal, arg): if self.signal_object: try: