source: ralphm-patches/roster_item_sender.patch @ 58:4b02ff624ab2

Last change on this file since 58:4b02ff624ab2 was 58:4b02ff624ab2, checked in by Ralph Meijer <ralphm@…>, 9 years ago

Move roster patches to xmppim.py, add backwards compat and new pushReceived.

File size: 5.0 KB
  • wokkel/test/test_xmppim.py

    # HG changeset patch
    # Parent c69d15fefcece37b5eb00e8ce1db144d6ac98d22
    Record sender on received roster sets to support alternative roster sources.
    
     * `RosterItem` gains `sender` attribute that holds the JID of the sender
       entity from which the roster push was received.
     * `pushReceived` can raise `RosterPushIgnored` to return a
       `service-unavailable` stanza error for unwanted pushes.
    
    diff --git a/wokkel/test/test_xmppim.py b/wokkel/test/test_xmppim.py
    a b  
    931931        items = []
    932932
    933933        def pushReceived(item):
     934            self.assertIs(None, item.recipient)
     935            self.assertIs(None, item.sender)
    934936            items.append(item)
    935937
    936938        def cb(result):
     
    942944        d = self.handleRequest(xml)
    943945        d.addCallback(cb)
    944946        return d
     947
     948
     949    def test_pushReceivedOtherSource(self):
     950        """
     951        Roster pushes can be sent from other entities, too.
     952        """
     953        xml = """
     954          <iq type='set' to='this@example.org/Home' from='other@example.org'>
     955            <query xmlns='jabber:iq:roster'>
     956              <item jid='user@example.org'/>
     957            </query>
     958          </iq>
     959        """
     960
     961        items = []
     962
     963        def onRosterSet(item):
     964            items.append(item)
     965
     966        def cb(result):
     967            item = items[0]
     968            self.assertEquals(JID('this@example.org/Home'), item.recipient)
     969            self.assertEquals(JID('other@example.org'), item.sender)
     970
     971        self.service.onRosterSet = onRosterSet
     972
     973        d = self.handleRequest(xml)
     974        d.addCallback(cb)
     975        return d
     976
     977
     978    def test_pushReceivedIgnored(self):
     979        """
     980        Ignored roster pushes return a service unavailable error.
     981        """
     982        xml = """
     983          <iq type='set' to='this@example.org/Home' from='bad@example.org'>
     984            <query xmlns='jabber:iq:roster'>
     985              <item jid='user@example.org'/>
     986            </query>
     987          </iq>
     988        """
     989
     990        def pushReceived(item):
     991            """
     992            Explicitly ignore pushes from other entities.
     993
     994            This assumes the recipient address is the same as the user, which
     995            should hold for regular XMPP client connections.
     996            """
     997            if (item.sender and
     998                item.sender.userhost() != item.recipient.userhost()):
     999                raise xmppim.RosterPushIgnored()
     1000
     1001        def cb(result):
     1002            self.assertEquals('service-unavailable', result.condition)
     1003
     1004        self.service.pushReceived = pushReceived
     1005
     1006        d = self.handleRequest(xml)
     1007        self.assertFailure(d, error.StanzaError)
     1008        d.addCallback(cb)
     1009        return d
  • wokkel/xmppim.py

    diff --git a/wokkel/xmppim.py b/wokkel/xmppim.py
    a b  
    634634    @type approved: C{bool}
    635635    @ivar remove: Signals roster item removal.
    636636    @type remove: C{bool}
     637
     638    @ivar recipient: The JID of the recipient of this roster item.
     639    @type recipient: L{JID}
     640
     641    @ivar sender: The JID of the sender of this roster item.
     642    @type sender: L{JID}
    637643    """
    638644
    639645    __subscriptionStates = {(False, False): None,
     
    653659        self.approved = False
    654660        self.remove = False
    655661
     662        self.sender = None
     663        self.recipient = None
     664
    656665
    657666    def __getJID(self):
    658667        warnings.warn(
     
    743752
    744753
    745754
     755class RosterPushIgnored(Exception):
     756    """
     757    Raised when this entity doesn't want to accept/trust a roster push.
     758    """
     759
     760
     761
    746762class RosterClientProtocol(XMPPHandler, IQHandlerMixin):
    747763    """
    748764    Client side XMPP roster protocol.
     
    796812
    797813
    798814    def _onRosterSet(self, iq):
     815        def trapIgnored(failure):
     816            failure.trap(RosterPushIgnored)
     817            raise error.StanzaError('service-unavailable')
     818
     819        # Parse received roster item.
    799820        item = RosterItem.fromElement(iq.query.item)
    800821
     822        # Copy stanza addressing to roster item.
     823        request = Stanza.fromElement(iq)
     824        item.recipient = request.recipient
     825        item.sender = request.sender
     826
    801827        d = defer.maybeDeferred(self.pushReceived, item)
     828        d.addErrback(trapIgnored)
    802829        return d
    803830
    804831
     
    808835
    809836        Override this to handle roster pushes.
    810837
     838        RFC 6121 specifically allows entities other than a user's server to
     839        hold a roster for that user. However, how a client should deal with
     840        that is currently not yet specfied. For now, it is advisable to ignore
     841        roster pushes from other entities. I.e. when C{item.sender} is set but
     842        the sender's bare JID is different from the user's bare JID.
     843
     844        To avert presence leaks, a handler can raise L{RosterPushIgnored} when
     845        not accepting a roster push (directly or via Deferred). This will
     846        result in a L{'service-unavailable'} error being sent in return.
     847
    811848        For backwards compatibility, the default implementation calls
    812849        the deprecated C{onRosterSet} or C{onRosterRemove} if defined on
    813850        C{self}.
Note: See TracBrowser for help on using the repository browser.