<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE xep SYSTEM 'xep.dtd' [ <!ENTITY % ents SYSTEM 'xep.ent'> %ents; ]> <?xml-stylesheet type='text/xsl' href='xep.xsl'?> <xep> <header> <title>Pubsub Subscription Storage</title> <abstract>This document defines an XMPP protocol extension for storing subscriptions to Pubsub nodes.</abstract> &LEGALNOTICE; <number>0173</number> <status>Deferred</status> <type>Historical</type> <sig>Standards</sig> <approver>Council</approver> <dependencies> <spec>XMPP Core</spec> <spec>XEP-0049</spec> <spec>XEP-0060</spec> </dependencies> <supersedes/> <supersededby/> <shortname>pubsubs</shortname> <author> <firstname>Magnus</firstname> <surname>Henoch</surname> <email>henoch@dtek.chalmers.se</email> <jid>legoscia@jabber.cd.chalmers.se</jid> </author> <revision> <version>0.1</version> <date>2006-02-09</date> <initials>psa</initials> <remark><p>Initial version; changed title to Pubsub Subscription Storage; changed namespace to storage:pubsubs for consistency with other storage XEPs.</p></remark> </revision> <revision> <version>0.0.4</version> <date>2005-12-11</date> <initials>mh</initials> <remark><p>Add resource attribute.</p></remark> </revision> <revision> <version>0.0.3</version> <date>2005-11-13</date> <initials>mh</initials> <remark><p>Add subscription attribute.</p></remark> </revision> <revision> <version>0.0.2</version> <date>2005-10-28</date> <initials>mh</initials> <remark><p>Fix typo and schema.</p></remark> </revision> <revision> <version>0.0.1</version> <date>2005-10-25</date> <initials>mh</initials> <remark><p>First draft.</p></remark> </revision> </header> <section1 topic='Introduction' anchor='intro'> <p>&xep0060; allows Jabber entities to subscribe to various kinds of information, but provides no way of remembering which nodes a user has subscribed to. Other protocols (e.g. &xep0080;, &xep0084;) allow information about a certain entity to be published to a Pubsub node. These protocols use &xep0030; to allow other entities to find the pubsub node used by a certain entity, but provide no way of performing the opposite mapping, from pubsub node to information source. This document attempts to fill that void, using &xep0049; for storing information about subscriptions.</p> </section1> <section1 topic='Requirements' anchor='reqs'> <p>This protocol enables Jabber clients to do the following:</p> <ul> <li>Remember which pubsub nodes the entity has subscribed to, and what kind of information is available at each node</li> <li>Update the mappings when subscriptions are added or removed</li> <li>Correlate incoming pubsub events to subscriptions</li> </ul> </section1> <section1 topic='Protocol' anchor='proto'> <p>The <subscriptions/> element qualified by the 'storage:pubsubs' namespace is the root element used in the jabber:iq:private transactions. It has zero or more <subscription/> child elements, each of which MUST possess the following attributes:</p> <ul> <li><em>jid</em> -- The JID of the pubsub service used</li> <li><em>node</em> -- The pubsub node at which the data is available</li> <li><em>subscription</em> -- The current subscription state, one of "none", "pending", "unconfigured" and "subscribed"</li> </ul> <p>Additionally, the <subscription/> element MAY possess these attributes:</p> <ul> <li><em>resource</em> -- The resource that is subscribed to this pubsub node. If the 'resource' attribute is absent, the bare JID is subscribed.</li> <li><em>user</em> -- The JID of the owner of this particular piece of data</li> <li><em>targetns</em> -- The namespace of the data in question</li> </ul> </section1> <section1 topic='Use Cases' anchor='usecases'> <section2 topic='Retrieving Existing Subscriptions' anchor='retrieving'> <p>In this example, the user already has a subscription to Juliet's geolocation, possibly established through another client.</p> <example caption='Client requests existing subscriptions'><![CDATA[ <iq type='get' id='retrieve1'> <query xmlns='jabber:iq:private'> <subscriptions xmlns='storage:pubsubs'/> </query> </iq> ]]></example> <example caption='Server returns existing subscriptions'><![CDATA[ <iq type='result' id='retrieve1'> <query xmlns='jabber:iq:private'> <subscriptions xmlns='storage:pubsubs'> <subscription user='juliet@capulet.com' jid='pubsub.capulet.com' node='juliet/geoloc' targetns='http://jabber.org/protocol/geoloc' subscription='subscribed'/> </subscriptions> </query> </iq> ]]></example> </section2> <section2 topic='Updating Subscriptions' anchor='updating'> <p>Due to the nature of XEP-0049, incremental updates are not possible; a client MUST send the entire <subscriptions/> node for each update. Before performing the update, the client SHOULD retrieve the stored subscriptions, and incorporate any changes.</p> <p>In this example, the user has just subscribed to Romeo's tune (see &xep0118;). Assuming that retrieving happened as in the previous use case, updating the subscriptions proceeds as follows:</p> <example caption='Client sends updated subscriptions'><![CDATA[ <iq type='set' id='update1'> <query xmlns='jabber:iq:private'> <subscriptions xmlns='storage:pubsubs'> <subscription user='juliet@capulet.com' jid='pubsub.capulet.com' node='juliet/geoloc' targetns='http://jabber.org/protocol/geoloc' subscription='subscribed'/> <subscription user='romeo@montague.net' jid='pubsub.montague.net' node='5017cdc9f4a3d1450445c9096064e459' targetns='http://jabber.org/protocol/tune' subscription='subscribed'/> </subscriptions> </query> </iq> ]]></example> <example caption='Server reports success'><![CDATA[ <iq type='result' id='update1'/> ]]></example> </section2> <section2 topic='Identifying Incoming Events' anchor='identifying'> <p>Having recorded the retrieved mappings, the client is now prepared to identify incoming pubsub events. Assume that the following event arrives:</p> <example caption='Client receives pubsub event'><![CDATA[ <message from='pubsub.montague.net' to='mercutio@shakespeare.lit'> <event xmlns='http://jabber.org/protocol/pubsub#event'> <items node='5017cdc9f4a3d1450445c9096064e459'> <item id='current'> <tune xmlns='http://jabber.org/protocol/tune'> <artist>Yes</artist> <title>Heart of the Sunrise</title> <source>Yessongs</source> <track>3</track> <length>686</length> </tune> </item> </items> </event> </message> ]]></example> <p>The client now knows that this information comes from romeo@montague.net.</p> </section2> </section1> <section1 topic='Security Considerations' anchor='security'> <p>Pubsub events offer an opportunity to spoof sender addresses e.g. through 'replyto' data (as specified by the &xep0033; protocol). This protocol attempts to close that hole. It does so by the following rules and assumptions:</p> <ul> <li>A client MUST add mappings (i.e. associations between a publisher's JID and a pubsub node) only from trustworthy sources, i.e. published disco items (see &xep0030;). This relies on disco information not being cracked or falsified.</li> <li>A client MUST retrieve mappings only from trustworthy sources, i.e. private XML storage. This assumes that no-one but the user is able to change such information.</li> </ul> </section1> <section1 topic='IANA Considerations' anchor='iana'> <p>This document requires no interaction with &IANA;.</p> </section1> <section1 topic='XMPP Registrar Considerations' anchor='registrar'> <p>No namespaces or parameters need to be registered with the ®ISTRAR; as a result of this document.</p> </section1> <section1 topic='XML Schema' anchor='schema'> <code><![CDATA[ <?xml version='1.0' encoding='UTF-8'?> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' targetNamespace='storage:pubsubs' xmlns='storage:pubsubs' elementFormDefault='qualified'> <xs:element name='subscriptions'> <xs:complexType> <xs:sequence> <xs:element ref='subscription' minOccurs='0' maxOccurs='unbounded'/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name='subscription'> <xs:complexType> <xs:attribute name='jid' type='xs:string' use='required'/> <xs:attribute name='node' type='xs:string' use='required'/> <xs:attribute name='subscription' use='required'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='none'/> <xs:enumeration value='pending'/> <xs:enumeration value='subscribed'/> <xs:enumeration value='unconfigured'/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name='resource' type='xs:string' use='optional'/> <xs:attribute name='user' type='xs:string' use='optional'/> <xs:attribute name='targetns' type='xs:string' use='optional'/> </xs:complexType> </xs:element> </xs:schema> ]]></code> </section1> </xep>