Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
7301 lines (7131 sloc) 372 KB
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
<!ENTITY ITEM "&lt;item/&gt;">
<!ENTITY ITEMS "&lt;items/&gt;">
<!ENTITY PUBSUB "&lt;pubsub/&gt;">
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>Publish-Subscribe</title>
<abstract>This specification defines an XMPP protocol extension for generic publish-subscribe functionality. The protocol enables XMPP entities to create nodes (topics) at a pubsub service and publish information at those nodes; an event notification (with or without payload) is then broadcasted to all entities that have subscribed to the node. Pubsub therefore adheres to the classic Observer design pattern and can serve as the foundation for a wide variety of applications, including news feeds, content syndication, rich presence, geolocation, workflow systems, network management systems, and any other application that requires event notifications.</abstract>
&LEGALNOTICE;
<number>0060</number>
<status>Draft</status>
<type>Standards Track</type>
<sig>Standards</sig>
<dependencies>
<spec>XMPP Core</spec>
<spec>XEP-0004</spec>
<spec>XEP-0030</spec>
<spec>XEP-0059</spec>
<spec>XEP-0068</spec>
<spec>XEP-0082</spec>
<spec>XEP-0131</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>pubsub</shortname>
<schemaloc>
<ns>pubsub</ns>
<url>http://xmpp.org/schemas/pubsub.xsd</url>
</schemaloc>
<schemaloc>
<ns>pubsub#errors</ns>
<url>http://xmpp.org/schemas/pubsub-errors.xsd</url>
</schemaloc>
<schemaloc>
<ns>pubsub#event</ns>
<url>http://xmpp.org/schemas/pubsub-event.xsd</url>
</schemaloc>
<schemaloc>
<ns>pubsub#owner</ns>
<url>http://xmpp.org/schemas/pubsub-owner.xsd</url>
</schemaloc>
<discuss>pubsub</discuss>
&pgmillard;
&stpeter;
&ralphm;
<revision>
<version>1.15.8</version>
<date>2019-06-19</date>
<initials>edhelas</initials>
<remark><p>Add pubsub#access_model and pubsub#publish_model to examples</p></remark>
</revision>
<revision>
<version>1.15.7</version>
<date>2019-01-27</date>
<initials>egp</initials>
<remark>
<p>Add 'publisher' attribute to &lt;item/&gt; in the http://jabber.org/protocol/pubsub schema, forgotten in revision 1.13.</p>
</remark>
</revision>
<revision>
<version>1.15.6</version>
<date>2018-11-22</date>
<initials>jsc (Editor)</initials>
<remark>
<ul><li>Correct several "entity element(s)" to "&lt;subscription/&gt; element(s)" (mw)</li>
<li>Remove unused and never defined 'node' attribute in pubsub#event item schema. This had been added in version 1.8 of the JEP, but never used. (egp)</li></ul>
</remark>
</revision>
<revision>
<version>1.15.5</version>
<date>2018-11-03</date>
<initials>pep</initials>
<remark>Fix a bunch of typos, batch-style.</remark>
</revision>
<revision>
<version>1.15.4</version>
<date>2018-08-11</date>
<initials>egp</initials>
<remark>Add example where fewer than the number of requested items are returned.</remark>
</revision>
<revision>
<version>1.15.3</version>
<date>2018-08-18</date>
<initials>egp</initials>
<remark>
<p>Add a new sentence and example about what to do if there are fewer items than requested present in a node.</p>
</remark>
</revision>
<revision>
<version>1.15.2</version>
<date>2018-05-14</date>
<initials>egp</initials>
<remark>
<p>Fix a few things in the schema:</p>
<ul>
<li>Remove duplicated &lt;publish/&gt; element.</li>
<li>Make &lt;affiliations/&gt;’s node attribute optional.</li>
<li>Add a missing optional dataform in &lt;default/&gt;.</li>
</ul>
</remark>
</revision>
<revision>
<version>1.15.1</version>
<date>2018-02-02</date>
<initials>sc</initials>
<remark>
<p>Add missing "retrieve-default-sub" feature to the XML Schema</p>
</remark>
</revision>
<revision>
<version>1.15.0</version>
<date>2017-12-12</date>
<initials>dg</initials>
<remark>
<ul>
<li>Specify that unregistered publish-options are mapped 1:1 to node configurations</li>
<li>Get rid of per-item OVERRIDE</li>
<li>Get rid of METADATA publish-options</li>
<li>Remove registration for the obsolete pubsub#access_model publish-options</li>
</ul>
</remark>
</revision>
<revision>
<version>1.14</version>
<date>2017-11-29</date>
<initials>jt</initials>
<remark><p>Add pubsub#multi-items to features.</p></remark>
</revision>
<revision>
<version>1.13.8</version>
<date>2017-10-10</date>
<initials>fs (XEP Editor: jwi)</initials>
<remark><p>Add missing dependency on XEP-0059.</p></remark>
</revision>
<revision>
<version>1.13.7</version>
<date>2017-08-24</date>
<initials>egp</initials>
<remark><p>Fix examples using invalid XEP-0082 dates.</p></remark>
</revision>
<revision>
<version>1.13.6</version>
<date>2017-06-22</date>
<initials>dg</initials>
<remark><p>Clarify behaviour of publish-options. Fields must be registered</p></remark>
</revision>
<revision>
<version>1.13.5</version>
<date>2016-12-21</date>
<initials>psa (XEP Editor: ssw)</initials>
<remark><p>Add missing options to schema.</p></remark>
</revision>
<revision>
<version>1.13.4</version>
<date>2016-12-02</date>
<initials>psa</initials>
<remark><p>Make Multiple Simultaneous Modifications examples consistent with text.</p></remark>
</revision>
<revision>
<version>1.13.3</version>
<date>2016-12-08</date>
<initials>ss (XEP Editor: ssw)</initials>
<remark><p>Include publisher with any item retrieval.</p></remark>
</revision>
<revision>
<version>1.13.2</version>
<date>2016-10-11</date>
<initials>ss (XEP Editor: ssw)</initials>
<remark><p>Be more consistent with reply.</p></remark>
</revision>
<revision>
<version>1.13.1</version>
<date>2016-07-21</date>
<initials>ss</initials>
<remark>
<ul>
<li>Fix wording, replace Jabber with XMPP where applicable.</li>
</ul>
</remark>
</revision>
<revision>
<version>1.13</version>
<date>2010-07-12</date>
<initials>psa</initials>
<remark>
<ul>
<li>Pending further discussion: added but then removed change to allow notifications via IQ stanzas; removed but then retained batch publishing; removed but then retained SubIDs in subscription approvals.</li>
<li>Corrected a large number of reported errata.</li>
<li>Removed delete-any feature.</li>
<li>Added missing delete-items feature.</li>
<li>Added special value of "presence" for the pubsub#expire option to support temporary subscriptions.</li>
<li>Removed replyto and replyroom config options.</li>
<li>Removed multiple node discovery since it depended on the deprecated Service Discovery Publishing feature.</li>
<li>Defined "room" value for itemreply config option.</li>
<li>Added optional 'publisher' attribute to &lt;item/&gt; element.</li>
<li>Added optional &lt;redirect/&gt; child to &lt;delete/&gt; element.</li>
<li>Based redirects on URIs for consistency with RFC 6120 gone and redirect errors.</li>
<li>Clarified meaning of filtered notifications (they are based on NodeIDs, not payload namespaces).</li>
<li>Added pubsub-on-a-jid service discovery feature for explicit discovery that an IM and presence account also functions as a virtual pubsub service.</li>
<li>Added purge_offline node configuration option for purging the node when the relevant publisher goes offline, for use in certain extended presence applications.</li>
<li>Added item_expire node configuration option for automatically removing items after a certain number of seconds.</li>
<li>Added notification_type node configuration option for defining which value of the &lt;message/&gt; type attribute shall be used for notifications.</li>
<li>Added retrieve-default-sub feature for retrieving default subscription configuration from a node (as you can retrieve default node configuration from the service).</li>
<li>Clarified suggested rules for payload definitions.</li>
<li>Mentioned that singleton pattern can be enforced by setting max_items to 1.</li>
<li>Removed the notion of batch publishing because it makes information coherence and atom handling excessively difficult.</li>
<li>Added error handling for too-many-subscriptions to help prevent a certain denial of service attack.</li>
<li>Added process for retrieving default subscription configuration options for leaf nodes, by omitting the 'node' attribute on the &lt;default/&gt; element (also added the &lt;default/&gt; element to the schema for the http://jabber.org/protocol/pubsub namespace, since it was missing).</li>
<li>Removed informational mapping of node metadata to Dublin Core.</li>
</ul>
</remark>
</revision>
<revision>
<version>1.12</version>
<date>2008-09-03</date>
<initials>psa</initials>
<remark>
<ul>
<li>Specified that service should return ItemID on successful publish if no ItemID was provided in request.</li>
<li>Described the use of Result Set Management to return some but not all published items.</li>
<li>Defined pubsub#notify_sub config option so that owners can receive notifications of new subscriptions, unsubscribes, and other subscription changes.</li>
<li>Harmonized definition of +notify feature with implementation reality.</li>
<li>Moved text about collections to XEP-0248.</li>
</ul>
</remark>
</revision>
<revision>
<version>1.11</version>
<date>2008-03-05</date>
<initials>rm/psa</initials>
<remark><p>For collection nodes, changed name of node child element to associate and added disassociate child element to handle disassociation use case; corrected SHIM examples to conform to XEP-0131; modified lease expiry notification for consistency with other subscription-related notifications (i.e., not using SHIM header); renamed SHIM headers to Collection and SubID for consistency with HTTP and Email headers.</p></remark>
</revision>
<revision>
<version>1.10</version>
<date>2007-09-26</date>
<initials>psa</initials>
<remark>
<ul>
<li>In accordance with XMPP Council consensus, moved the auto-create, auto-subscribe, filtered-notifications, and last-published features from XEP-0163 to this specification</li>
<li>Clarified implications of auto-subscribe feature for handling of account owners, stable presence subscribers, and transient presence sharers</li>
<li>Updated filtered-notifications text and examples to track changes to XEP-0115</li>
<li>Added publish-options functionality</li>
<li>Added developer-friendly How It Works section</li>
<li>Defined member affiliation to properly implement whitelist feature</li>
<li>Split several long sections into smaller sub-sections.</li>
<li>Clarified that a pubsub service must generate an ItemID if the publisher does not provide one.</li>
<li>Specified recommended ItemID for singleton nodes.</li>
<li>Summarized triggers for sending notifications.</li>
</ul>
</remark>
</revision>
<revision>
<version>1.9</version>
<date>2006-09-13</date>
<initials>psa</initials>
<remark>
<ul>
<li>Replaced boolean send_item_subscribe node configuration option with more comprehensive send_last_published_item option per list discussion</li>
<li>Added deliver_notifications node configuration option to enable quiet nodes without notifications, if desired enabling pull-model item retrieval only.</li>
<li>Modified subscription and affiliation retrieval to return empty element if no results.</li>
</ul>
</remark>
</revision>
<revision>
<version>1.8</version>
<date>2006-06-27</date>
<initials>psa</initials>
<remark>
<ul>
<li>Defined five access models: open, presence, roster, authorize, and whitelist</li>
<li>Renamed pubsub#subscription_model feature to pubsub#access_model</li>
<li>Separated affiliations retrieval from subscriptions retrieval</li>
<li>Removed subscription information from affiliations management</li>
<li>Changed &lt;entity/&gt; element to &lt;subscription/&gt; element in response to subscription request</li>
<li>Clarified batch processing of item publication and item deletion</li>
<li>Added basic example to introduction</li>
<li>More fully specified node creation flows</li>
<li>More fully specified recommended behavior for caching last published item, including use of jabber:x:delay protocol</li>
<li>Specified that semantic meaning of NodeIDs must not be used to encapsulate hierarchy</li>
<li>More fully specified error conditions</li>
<li>Changed some feature-related conditions to &lt;unsupported/&gt; plus feature attribute</li>
<li>Changed some error conditions from &lt;not-authorized/&gt; to &lt;forbidden/&gt;</li>
<li>Harmonized error conditions for unsubscribe if entity is not subscribed (unexpected-request rather than not-found)</li>
<li>Further defined error conditions related to item publication</li>
<li>Specified structure of &lt;affiliations/&gt;, &lt;delete/&gt;, &lt;purge/&gt;, and &lt;subscriptions/&gt; elements qualified by pubsub#owner namespace</li>
<li>Changed retrieval of default node configuration options to use &lt;default/&gt; element, not &lt;configure/&gt; element</li>
<li>Allowed caching of last published item</li>
<li>Added pubsub#deliver subscription option</li>
<li>Added metadata fields for pubsub#owners and pubsub#contact</li>
<li>Changed element for retrieval of default node configuration options from &lt;configure/&gt; to &lt;default/&gt; to prevent ambiguity related to configuration of root collection node</li>
<li>Specified pubsub#node_type configuration field</li>
<li>Specified pubsub#collection SHIM header</li>
<li>Specified conformance with Resourceprep for nodes addressable as JIDs</li>
<li>Added pubsub#modify-affiliations feature</li>
<li>Added pubsub#digest_frequency field to subscribe_options FORM_TYPE</li>
<li>Added pubsub#roster_groups_allowed field to node_config FORM_TYPE</li>
<li>More clearly specified the requirements level (MUST, SHOULD, MAY) for each service discovery feature</li>
<li>Defined pubsub#include_body subscription option and the pubsub#body_xslt node configuration option to transform payload format into an XMPP message body, and clarified rules for inclusion of message bodies</li>
<li>Clarified nature of collections and association of a node to a collection</li>
<li>Specified that simultaneous subscriptions of type nodes and items are allowed to collection nodes</li>
<li>Added examples and further explanation of time-based and content-based subscriptions</li>
<li>Added Internationalization Considerations</li>
<li>Clarified terminology</li>
<li>Corrected and updated the schemas</li>
</ul>
</remark>
</revision>
<revision>
<version>1.7</version>
<date>2005-03-03</date>
<initials>psa/rm</initials>
<remark>
<ul>
<li>Reinstated pubsub#subscribe feature (deleted in error)</li>
<li>Added type attribute for the &lt;create/&gt; and &lt;configure/&gt; elements to differentiate between leaf nodes and collection nodes</li>
<li>In Section 8.1.7, changed affiliations retrieval support to SHOULD and added pubsub#retrieve-affiliations feature</li>
<li>In Section 8.1.10, removed two duplicate examples</li>
<li>In Section 8.1.12, clarified relationship between normal disco#info data and node metadata (which uses a service discovery extension)</li>
<li>In Section 8.2.4, specified that node purgation MUST result in one event notification, not a notification per item</li>
<li>In Section 8.1.8, further specified handling of SubIDs</li>
<li>Clarified nature of the pubsub#type field</li>
<li>Mentioned that the forbidden error should be returned in response to certain operations requested by an outcast</li>
<li>Corrected datatype of max_items attribute from xs:string to xs:positiveInteger</li>
<li>Corrected &lt;requesting-entity-not-subscribed/&gt; error to &lt;not-subscribed/&gt; since the subscribed JID need not be that of the requesting entity</li>
<li>Added service discovery features for more optional use cases: retracting items, purging nodes, deleting nodes</li>
<li>Updated relevant registries</li>
</ul>
</remark>
</revision>
<revision>
<version>1.6</version>
<date>2004-07-13</date>
<initials>pgm/psa</initials>
<remark><p>Added service discovery features for pubsub#metadata, and pubsub#retrieve-items. Added pubsub#subscription_depth configuration option. Specified pubsub-specific error condition elements qualified by pubsub#errors namespace.</p></remark>
</revision>
<revision>
<version>1.5</version>
<date>2004-07-07</date>
<initials>pgm/psa</initials>
<remark><p>Fixed typos. Added more details to the section on collections. Added paragraph to create node use case to allow the service to change the requested node-id to something which it creates. Added text about bouncing publish requests when the request does not match the event-type for that node. Added disco features for the jabber registrar. Changed affiliation verbiage to allow publishers to remove any item. Tweaked verbiage for create node, eliminated extra example. Fully defined XMPP Registrar submissions. Corrected schemas.</p></remark>
</revision>
<revision>
<version>1.4</version>
<date>2004-06-22</date>
<initials>pgm</initials>
<remark><p>Added subid syntax in a variety of places. Added more information about disco#info and disco#items support. Added more info about subscription options. Added collection information. Added implementation notes about subscription leases, and content-based pubsub services.</p></remark>
</revision>
<revision>
<version>1.3</version>
<date>2004-04-25</date>
<initials>psa</initials>
<remark><p>Editorial review; added one implementation note.</p></remark>
</revision>
<revision>
<version>1.2</version>
<date>2004-03-09</date>
<initials>psa</initials>
<remark><p>Added XMPP error handling.</p></remark>
</revision>
<revision>
<version>1.1</version>
<date>2004-01-14</date>
<initials>psa</initials>
<remark><p>Added XMPP Registrar Considerations subsection for Service Discovery category/type registration.</p></remark>
</revision>
<revision>
<version>1.0</version>
<date>2003-10-28</date>
<initials>psa</initials>
<remark><p>Per a vote of the Jabber Council, advanced status to Draft.</p></remark>
</revision>
<revision>
<version>0.16</version>
<date>2003-10-23</date>
<initials>pgm</initials>
<remark><p>Clarified JID addressing usage for nodes. Added specific MAY requirement for disco usage. Added sentence about implementations verifying that an entity has a subscription before getting the current items.</p></remark>
</revision>
<revision>
<version>0.15</version>
<date>2003-10-21</date>
<initials>pgm</initials>
<remark><p>Fixed invalid XML in examples for subscription deny/allow.</p></remark>
</revision>
<revision>
<version>0.14</version>
<date>2003-10-21</date>
<initials>pgm</initials>
<remark><p>Clarified restrictions on addressing nodes by JID. Added section on Approving and Denying Subscription Requests. Changed get-pending to use Ad-Hoc Commands. Changed semantics when sending in a form type='cancel' for pending subscriptions.</p></remark>
</revision>
<revision>
<version>0.13</version>
<date>2003-09-30</date>
<initials>pgm</initials>
<remark><p>Removed item as a possible child of subscribe and unsubscribe and pubsub in the schemas. Removed retract as a possible child of item in the pubsub#event schema. Added verbiage to requirements for addressing nodes either via JIDs or disco nodes.</p></remark>
</revision>
<revision>
<version>0.12</version>
<date>2003-08-13</date>
<initials>pgm/psa</initials>
<remark><p>Defined public vs. private nodes; described how changes to existing nodes might trigger meta-node events (e.g., configuration changes); changed &lt;x/&gt; to &lt;event/&gt; for #events namespace; added metadata about meta-nodes; fully defined XMPP Registrar considerations.</p></remark>
</revision>
<revision>
<version>0.11</version>
<date>2003-06-25</date>
<initials>pgm</initials>
<remark><p>Removed subscription notifications since they have inherent issues. Removed empty implementation note sub-section.</p></remark>
</revision>
<revision>
<version>0.10</version>
<date>2003-06-11</date>
<initials>pgm</initials>
<remark><p>Fixed error example when returning 501 from an items-get request. Added note about receiving subscription requests when an entity is already subscribed. Fixed some entity elements in various subscription examples. Many were missing the node attribute. Added subscription change notification verbiage and example. Added verbiage and example of subscription state notification being sent to the requesting entity. Added disco#items information for getting a list of item identifiers for a single node. Added verbiage for returning the current entity element when a curent subscriber attempts to subscribe again.</p></remark>
</revision>
<revision>
<version>0.9</version>
<date>2003-04-30</date>
<initials>pgm</initials>
<remark><p>Include JID attributes in the entity elements when receiving your affiliations. Changed error code 406 (which was wrong) to 404, which is correct. Changed many 405 errors to 401, and modified the error table to make it more implementable (rules are more concrete). Added subscribe-options element for indicating subscriptions may be configured.</p></remark>
</revision>
<revision>
<version>0.8</version>
<date>2003-04-03</date>
<initials>pgm</initials>
<remark><p>Clarified the affiliations table and the semantics around subscribing and unsubscribing. Added protocol to get all of your affiliations in the service. Added protocol for services informing subscribers that configurable subscription options are available. Added protocol for obtaining existing node configuration settings and for concatenating configuration and node creation requests into a single stanza. Added meta-node implementation notes and specified the interaction with the XMPP Registrar and the meta NodeIDs. Added authorization notes to subscription options.</p></remark>
</revision>
<revision>
<version>0.7</version>
<date>2003-02-14</date>
<initials>pgm</initials>
<remark><p>Clarified requirements around what affiliations must be supported. Moved requirements about specifying entities which can subscribe and publish out of the MUSTs to MAYs. Changed SHOULD to MAY when talking about allowing entities to create nodes. Added ability to send configuration requests in the same stanza as a creation request.</p></remark>
</revision>
<revision>
<version>0.6</version>
<date>2003-02-06</date>
<initials>pgm</initials>
<remark><p>Added more details and an example about publishing without NodeID. Added more implementation notes about NodeIDs and persistent storage.</p></remark>
</revision>
<revision>
<version>0.5</version>
<date>2003-01-22</date>
<initials>pgm</initials>
<remark><p>Fixed header for delete item example. Added examples showing subscribers being notified of deleted items. Added examples for notification of node deletion, and configuration for node deletion. Added Subscriber option semantics and examples. Added examples for 402 and 407 errors on subscribe and create respectively. Added clarification about ItemID handling to impl notes.</p></remark>
</revision>
<revision>
<version>0.4</version>
<date>2003-01-21</date>
<initials>pgm</initials>
<remark><p>Clarified in-band and out-of-band configuration requirement. Added Delete Item privilege for all affiliations to the table. Added Delete item protocol for publishers and owners. Added 401 error case for subscribing to an illegal jid. Changed subscription request form. Added defaults to configuration form, and clarified role of the XMPP Registrar for the features show. Added text explaining the max_items attribute. Changed &quot;last items&quot; to &quot;most recent items&quot;. Removed default configuration acceptance -- owners should just cancel. Added the notify_retract configuration option. Clarified error handling for affiliation modifications. </p></remark>
</revision>
<revision>
<version>0.3</version>
<date>2003-01-20</date>
<initials>pgm</initials>
<remark><p>Added subscription attribute for entities. Removed subscriber from the affiliations table. Clarified configuration details. Clarified JabberID usages. Added XMPP Registrar Considerations. Added link to XEP-0068 about the FORM_TYPE element in subscription request notifications. Fixed some typos in examples. Added unsupported configuration namespace to example. Added a default node configuration example. </p></remark>
</revision>
<revision>
<version>0.2</version>
<date>2003-01-02</date>
<initials>pgm</initials>
<remark><p>Added numerous implementation notes; added get-pending action with regard to subscriptions; added error table; changed purge and delete to use IQ type='set'.</p></remark>
</revision>
<revision>
<version>0.1</version>
<date>2002-11-19</date>
<initials>pgm</initials>
<remark><p>Initial version.</p></remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<section2 topic='Overview' anchor='intro-overview'>
<p>The XMPP publish-subscribe extension defined in this document provides a framework for a wide variety of applications, including news feeds, content syndication, extended presence, geolocation, avatar management, shared bookmarks, auction and trading systems, workflow systems, network management systems, NNTP gateways, profile management, and any other application that requires event notifications.</p>
<p>This technology uses the classic "publish-subscribe" or "observer" design pattern: a person or application publishes information, and an event notification (with or without payload) is broadcasted to all authorized subscribers. In general, the relationship between the publisher and subscriber is mediated by a service that receives publication requests, broadcasts event notifications to subscribers, and enables privileged entities to manage lists of people or applications that are authorized to publish or subscribe. The focal point for publication and subscription is a "node" to which publishers send data and from which subscribers receive event notifications. Nodes can also maintain a history of events and provide other services that supplement the pure pubsub model.</p>
<p>This document defines a generic protocol that all pubsub applications can use. Compliant implementations are not required to implement all of the features defined here (see the <link url='#features'>Feature Summary</link>.) Other specifications may define "subsets" or "profiles" of publish-subscribe for use in specialized contexts, but such profiles are out of scope for this document.</p>
</section2>
<section2 topic='How It Works' anchor='intro-howitworks'>
<p>Although this specification is large because it defines many side use cases and possible error flows, the basic idea is simple:</p>
<ol>
<li>An entity publishes information to a node at a publish-subscribe service.</li>
<li>The pubsub service pushes an event notification to all entities that are authorized to learn about the published information.</li>
</ol>
<p>Perhaps the most popular application of pubsub-like functionality is content syndication, which has become familiar from the RSS and Atom (&rfc4287;) feeds associated with weblogs, news sites, and other frequently-updated information available on the Internet. Consider the example of a weblog published by &lt;hamlet@denmark.lit&gt;. When Hamlet writes a new weblog entry, his blogging software publishes the entry to a pubsub node hosted at &lt;pubsub.shakespeare.lit&gt;:</p>
<example caption='Publisher Publishes a New Weblog Entry'><![CDATA[
<iq type='set'
from='hamlet@denmark.lit/blogbot'
to='pubsub.shakespeare.lit'
id='pub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='princely_musings'>
<item>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</publish>
</pubsub>
</iq>
]]></example>
<p>So that is the "pub" part of pubsub.</p>
<p>Now the pubsub service notifies all the subscribers about the new blog entry:</p>
<example caption='Service Notifies Subscribers'><![CDATA[
<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
[ ... ENTRY ... ]
</item>
</items>
</event>
</message>
<message from='pubsub.shakespeare.lit' to='bernardo@denmark.lit' id='bar'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
[ ... ENTRY ... ]
</item>
</items>
</event>
</message>
<message from='pubsub.shakespeare.lit' to='horatio@denmark.lit' id='baz'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
[ ... ENTRY ... ]
</item>
</items>
</event>
</message>
<message from='pubsub.shakespeare.lit' to='bard@shakespeare.lit' id='fez'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
[ ... ENTRY ... ]
</item>
</items>
</event>
</message>
]]></example>
<p>Here is an even simpler example: a transient node that sends only event notifications without a payload:</p>
<example caption='A Transient Notification'><![CDATA[
<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='elsinore/doorbell'/>
</event>
</message>
]]></example>
<p>Naturally, the entities involved may need to complete other use cases in order to enable full pubsub functionality -- for example, the publisher may need to create the node (see <link url='#owner-create'>Create a Node</link>) and subscribers may need to sign up for event notifications (see <link url='#subscriber-subscribe'>Subscribe to a Node</link>). These use cases are fully described in the remainder of this document. (For information about which features are required and which are recommended or optional, consult the <link url='#features'>Feature Summary</link>.)</p>
</section2>
</section1>
<section1 topic='Glossary' anchor='glossary'>
<p>The following terms are used throughout this document to refer to elements, objects, or actions that occur in the context of a pubsub service. (Note: Some of these terms are specified in greater detail within the body of this document.)</p>
<dl>
<di><dt>Authorize Access Model</dt><dd>A node access model under which an entity can subscribe only through having a subscription request approved by a node owner (subscription requests are accepted but only provisionally) and only subscribers may retrieve items.</dd></di>
<di><dt>Address</dt><dd>(1) A JID as defined in &xmppcore;, or (2) the combination of a JID and a &xep0030; node.</dd></di>
<di><dt>Collection Node</dt><dd>A type of node that contains nodes and/or other collections but no published items. Collections make it possible to represent more sophisticated relationships among nodes. Collection nodes are defined in &xep0248;.</dd></di>
<di><dt>Entity</dt><dd>A JID-addressable XMPP entity (client, service, application, etc.).</dd></di>
<di><dt>Event</dt><dd>A change in the state of a node.</dd></di>
<di><dt>Instant Node</dt><dd>A node whose NodeID is automatically generated by a pubsub service.</dd></di>
<di><dt>Item</dt><dd>An XML fragment which is published to a node, thereby generating an event.</dd></di>
<di><dt>ItemID</dt><dd>A unique identifier for an item in the context of a specific node.</dd></di>
<di><dt>Leaf Node</dt><dd>A type of node that contains published items only. It is NOT a container for other nodes.</dd></di>
<di><dt>Node</dt><dd>A virtual location to which information can be published and from which event notifications and/or payloads can be received (in other pubsub systems, this may be labelled a "topic").</dd></di>
<di><dt>NodeID</dt><dd>The unique identifier for a node within the context of a pubsub service. The NodeID is either supplied by the node creator or generated by the pubsub service (if the node creator requests an Instant Node). The NodeID MAY have semantic meaning (e.g., in some systems or in pubsub profiles such as PEP the NodeID might be an XML namespace for the associated payload), but such meaning is OPTIONAL. If a document defines a given NodeID as unique within the realm of XMPP pubsub systems, it MUST specify the XML namespace of the associated payload.</dd></di>
<di><dt>Notification</dt><dd>A message sent to a subscriber informing them of an event.</dd></di>
<di><dt>Outcast</dt><dd>An entity that is disallowed from subscribing or publishing to a node.</dd></di>
<di><dt>Owner</dt><dd>The manager of a node, of which there may be more than one; often but not necessarily the node creator.</dd></di>
<di><dt>Open Access Model</dt><dd>A node access model under which any entity may subscribe and retrieve items without approval.</dd></di>
<di><dt>Payload</dt><dd>The XML data that is contained within the &lt;item/&gt; element of a publication request or an event notification. A given payload is defined by an XML namespace and associated schema. A document that defines a payload format SHOULD specify whether the payload can be used only for a NodeID whose value is the same as the XML namespace, or whether the payload can be used for any NodeID. Such a document also SHOULD specify whether it is suggested that node at which such payloads are published are best configured as <link url='#impl-singleton'>Singleton Nodes</link>.</dd></di>
<di><dt>Personal Eventing</dt><dd>A simplified subset of Publish-Subscribe for use in the context of instant messaging and presence applications, whereby each IM user's JID is a virtual pubsub service; for details, see &xep0163;.</dd></di>
<di><dt>Presence Access Model</dt><dd>A node access model under which any entity that is subscribed to the owner's presence with a subscription of type "from" or "both" (see &rfc3921;) may subscribe to the node and retrieve items from the node; this access model applies mainly to instant messaging systems.</dd></di>
<di><dt>Publisher</dt><dd>An entity that is allowed to publish items to a node and that is automatically subscribed to the node.</dd></di>
<di><dt>Publish-Only</dt><dd>An entity that is allowed to publish items to a node but that is not allowed to receive notifications. (This affiliation is useful in the context of nodes that do not have an open access model when automated entities need to generate notifications on behalf of the owner.)</dd></di>
<di><dt>Pubsub Service</dt><dd>An XMPP server or component that adheres to the protocol defined herein.</dd></di>
<di><dt>Roster Access Model</dt><dd>A node access model under which any entity that is subscribed to the owner's presence and in the specified roster group(s) may subscribe to the node and retrieve items from the node; this access model applies mainly to instant messaging systems.</dd></di>
<di><dt>Subscriber</dt><dd>An entity that is subscribed to a node.</dd></di>
<di><dt>Whitelist Access Model</dt><dd>A node access model under which an entity may subscribe and retrieve items only if explicitly allowed to do so by the node owner (subscription requests from unauthorized entities are rejected).</dd></di>
</dl>
</section1>
<!-- =================== REQS ======================== -->
<section1 topic='Requirements' anchor='reqs'>
<p>Requirements for a pubsub service can be driven by end-user needs as well as the needs of other components and services which can use the service. First, a pubsub service implemented using XMPP MUST provide the basic features that implement a pure publish-subscribe pattern:</p>
<!-- ================== MUSTS =================== -->
<ul>
<li>An entity MUST be able to publish events to a service such that all subscribers to a node receive notification of the event. See <link url='#publisher-publish'>Publish an Item to a Node</link>.</li>
<li>An entity MUST be able to subscribe to a node (or be informed that subscription is not allowed). See <link url='#subscriber-subscribe'>Subscribe to a Node</link>.</li>
<li>An entity MUST be allowed to be affiliated with a node. Allowable affiliations are member, none, outcast, owner, publish-only, and publisher. Implementations MUST support affiliations of none and owner, and MAY support affiliations of member, outcast, publisher, and publish-only. See <link url='#affiliations'>Affiliations</link>.</li>
<li>An entity MUST be allowed to query the pubsub service (or a specific node) to determine what optional features of this specification the service (or node) implements. This query MUST use the Service Discovery (disco#info) protocol. See <link url='#entity-info'>Discover Node Information</link>.</li>
</ul>
<!-- =================== MAYS and SHOULDS =================== -->
<p>Some of the possible uses of an XMPP-based pubsub service will require other features, but these features are OPTIONAL and therefore not mandatory for compliance with this specification. However, if these features are implemented, they MUST adhere to the protocol described herein in to be compliant. These features include:</p>
<ul>
<li>A service MAY cache the last item published to a node (even if the "persistent-items" option is set to false); if it does default "cache-last-item" to true, it SHOULD send the last published item (or notification thereof) to subscribed entities based on configuration of the "send_last_published_item" field.</li>
<li>A node owner SHOULD be able to specify who may subscribe to a node.</li>
<li>A node owner SHOULD be able to specify who may publish to a node.</li>
<li>A node MAY be configured to deliver the published payload inside the event notification.</li>
<li>A node MAY be configured to persist published items to some persistent storage mechanism.</li>
<li>A node MAY be configured to persist only a limited number of items.</li>
<li>A service MAY support collections as described in <cite>XEP-0248</cite>.</li>
<li>A service or node MAY support extended service discovery information (metadata).</li>
</ul>
</section1>
<section1 topic='Preliminaries' anchor='preliminaries'>
<section2 topic='Affiliations' anchor='affiliations'>
<p>To manage permissions, the protocol defined herein uses a hierarchy of affiliations, similiar to those introduced in &xep0045;.</p>
<p>All affiliations MUST be based on a bare JID &BAREJID; instead of a full JID &FULLJID;.</p>
<p>Support for the "owner" and "none" affiliations is REQUIRED. Support for all other affiliations is RECOMMENDED. For each non-required affiliation supported by an implementation, it SHOULD return a service discovery feature of "name-affiliation" where "name" is the name of the affiliation, such as "member", "outcast", or "publisher" (see the <link url='#features'>Feature Summary</link>). Particular kinds of pubsub services MAY enforce additional requirements (e.g., requiring support for a given non-required affiliation or for all affiliations).</p>
<table caption='Affiliations and their Privileges'>
<tr>
<th>Affiliation</th>
<th>Subscribe</th>
<th>Retrieve Items</th>
<th>Publish Items</th>
<th>Delete Single Item</th>
<th>Purge Node</th>
<th>Configure Node</th>
<th>Delete Node</th>
</tr>
<tr>
<td>Owner</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Publisher</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes *</td>
<td>Yes *</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Publish-Only</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>Yes *</td>
<td>No *</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Member</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>None</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Outcast</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
</table>
<p>* Note: A service MAY allow any publisher to delete / purge any item once it has been published to that node instead of allowing only the original publisher to remove it. This behavior is NOT RECOMMENDED for the publish-only affiliation, which SHOULD be allowed to delete only items that the publish-only entity has published.</p>
<p>The ways in which an entity changes its affiliation with a node are well-defined. Typically, action by an owner is required to make an affiliation state transition. Affiliation changes and their triggering actions are specified in the following table.</p>
<table caption='Affiliation State Chart'>
<tr>
<th>&#160;</th>
<th>Outcast</th>
<th>None</th>
<th>Member</th>
<th>Publisher</th>
<th>Owner</th>
</tr>
<tr>
<td>Outcast</td>
<td>--</td>
<td>Owner removes ban</td>
<td>Owner adds entity to member list</td>
<td>Owner adds entity to publisher list</td>
<td>Owner adds entity to owner list</td>
</tr>
<tr>
<td>None</td>
<td>Owner bans entity</td>
<td>--</td>
<td>Owner adds entity to member list</td>
<td>Owner adds entity to publisher list</td>
<td>Owner adds entity to owner list</td>
</tr>
<tr>
<td>Member</td>
<td>Owner bans entity</td>
<td>Owner removes entity from member list</td>
<td>--</td>
<td>Owner adds entity to publisher list</td>
<td>Owner adds entity to owner list</td>
</tr>
<tr>
<td>Publisher</td>
<td>Owner bans entity</td>
<td>Owner removes entity from publisher list</td>
<td>n/a</td>
<td>--</td>
<td>Owner adds entity to owner list</td>
</tr>
<tr>
<td>Owner</td>
<td>n/a</td>
<td>Owner resigns</td>
<td>n/a</td>
<td>n/a</td>
<td>--</td>
</tr>
</table>
</section2>
<section2 topic='Subscription States' anchor='substates'>
<p>Subscriptions to a node may exist in several states.</p>
<table caption='Subscription States'>
<tr>
<th>Subscription State</th>
<th>Description</th>
</tr>
<tr>
<td>None</td>
<td>The node MUST NOT send event notifications or payloads to the Entity.</td>
</tr>
<tr>
<td>Pending</td>
<td>An entity has requested to subscribe to a node and the request has not yet been approved by a node owner. The node MUST NOT send event notifications or payloads to the entity while it is in this state.</td>
</tr>
<tr>
<td>Unconfigured</td>
<td>An entity has subscribed but its subscription options have not yet been configured. The node MAY send event notifications or payloads to the entity while it is in this state. The service MAY timeout unconfigured subscriptions.</td>
</tr>
<tr>
<td>Subscribed</td>
<td>An entity is subscribed to a node. The node MUST send all event notifications (and, if configured, payloads) to the entity while it is in this state (subject to subscriber configuration and content filtering).</td>
</tr>
</table>
</section2>
<section2 topic='Event Types' anchor='events'>
<p>The requirements for the publish-subscribe protocol imply that there are two major dimensions along which we can measure events: persistent vs. transient, and pure event notification vs. inclusion of payload. An implementation SHOULD enable an owner to configure a node along both of these dimensions.</p>
<p>No matter whether a node is configured for persistent or transient events, a service MAY cache the last item published to the node, in which case it SHOULD send that item to subscribers based on configuration of the "send_last_published_item" option (see the <link url='#impl-caching'>Item Caching</link> section of this document); if the service supports the "http://jabber.org/protocol/pubsub#last-published" feature then the value of this option MUST default to "on_sub_and_presence" (though the service SHOULD allow the node owner to override the default).</p>
<p class='box'>Note: The "on_sub_and_presence" setting relates to the <em>subscriber's</em> presence, not the publisher's presence.</p>
<p>A pubsub service MUST validate publish requests against the configuration of the node along both of these dimensions (see the <link url='#publisher-publish'>Publish An Item to a Node</link> section of this document for the relevant error conditions).</p>
<p>The node configuration and desired event type determine whether an item must be provided by the publisher, whether the item includes a payload in the publish request or event notification, and whether an item ID is provided by the publisher or generated by the pubsub service. We can summarize the relevant rules as follows:</p>
<table caption='Items, Payloads, and Item IDs'>
<tr><th>&#160;</th><th>Notification-Only Node *</th><th>Payload-Included Node *</th></tr>
<tr>
<td><strong>Persistent Node **</strong></td>
<td>Publish request MUST include an &ITEM; element, which MAY be empty or MAY contain a payload; even if publish request contains a payload, pubsub service MUST NOT include the payload in event notifications; if publish request did not include item ID, pubsub service MUST generate item ID</td>
<td>Publish request MUST include an &ITEM; element, which SHOULD contain a payload; if publish request included a payload, event notifications MUST include the payload; if publish request did not include item ID, pubsub service MUST generate item ID</td>
</tr>
<tr>
<td><strong>Transient Node **</strong></td>
<td>Publish request MUST NOT include an &ITEM; element; payload is not included in publish request or event notifications, although event notifications MUST include an empty &ITEMS; element; item ID is neither provided in publish request nor generated by pubsub service</td>
<td>Publish request MUST include an &ITEM; element, which SHOULD contain a payload; if publish request included a payload, event notifications MUST include the payload; pubsub service MAY generate an item ID</td>
</tr>
</table>
<p>* Note: Whether the node is notification-only or includes payloads is determined by the "pubsub#deliver_payloads" configuration field.</p>
<p>** Note: Whether the node is persistent or transient is determined by the "pubsub#persist_items" configuration field.</p>
</section2>
<section2 topic='Node Types' anchor='nodetypes'>
<p>There are two types of nodes:</p>
<table caption='Node Types'>
<tr>
<th>Node Type</th>
<th>Description</th>
</tr>
<tr>
<td>Leaf</td>
<td>A node that contains published items only. It is NOT a container for other nodes. This is the most common node type.</td>
</tr>
<tr>
<td>Collection</td>
<td>A node that contains nodes and/or other collections but no published items. Collections make it possible to represent more sophisticated relationships among nodes. For details, refer to <cite>XEP-0248</cite>.</td>
</tr>
</table>
</section2>
<section2 topic='Node Access Models' anchor='accessmodels'>
<p>In order to make node creation simpler for clients, we define the following node access models (in order of openness):</p>
<table caption='Node Access Models'>
<tr>
<th>Access Model</th>
<th>Description</th>
</tr>
<tr>
<td>Open</td>
<td>Any entity may subscribe to the node (i.e., without the necessity for subscription approval) and any entity may retrieve items from the node (i.e., without being subscribed); this SHOULD be the default access model for generic pubsub services.</td>
</tr>
<tr>
<td>Presence</td>
<td>Any entity with a subscription of type "from" or "both" may subscribe to the node and retrieve items from the node; this access model applies mainly to instant messaging systems (see <cite>RFC 3921</cite>).</td>
</tr>
<tr>
<td>Roster</td>
<td>Any entity in the specified roster group(s) may subscribe to the node and retrieve items from the node; this access model applies mainly to instant messaging systems (see <cite>RFC 3921</cite>).</td>
</tr>
<tr>
<td>Authorize</td>
<td>The node owner must approve all subscription requests, and only subscribers may retrieve items from the node.</td>
</tr>
<tr>
<td>Whitelist</td>
<td>An entity may subscribe or retrieve items only if on a whitelist managed by the node owner. The node owner MUST automatically be on the whitelist. In order to add entities to the whitelist, the node owner SHOULD use the protocol specified in the <link url='#owner-affiliations'>Manage Affiliated Entities</link> section of this document, specifically by setting the affiliation to "member".</td>
</tr>
</table>
<p>A generic publish-subscribe implementation SHOULD support all of the defined access models, although specialized publish-subscribe implementations MAY support only a subset of the access models. Which access models are provided in a particular deployment is a matter of service provisioning (e.g., some restricted deployments may wish to lock down permissions so that only the "authorize" and "whitelist" access models are provided, or even only the "whitelist" access model).</p>
<p>A node creator or owner can override the default access model by specifying an appropriate value for the 'pubsub#access_model' configuration field (see the <link url='#owner-create'>Create a Node With Default Configuration</link> and <link url='#owner-configure'>Configure a Node</link> sections of this document).</p>
</section2>
<section2 topic='Addressing' anchor='addressing'>
<p>If a pubsub node is addressable, it MUST be addressable either (1) as a JID or (2) as the combination of a JID and a node. <note>These nodes are equivalent to those used in <cite>XEP-0030: Service Discovery</cite>.</note></p>
<section3 topic='JID' anchor='addressing-jid'>
<p>If a pubsub node is addressable as a JID, the NodeID MUST be the resource identifier, and MUST NOT be specified by the "user" portion (node identifier) of the JID (e.g. "domain.tld/NodeID" and "user@domain.tld/NodeID" are allowed; "NodeID@domain.tld" is not allowed <note>This rule does not apply to the root collection node, if any.</note>). JID addressing SHOULD be used when interacting with a pubsub node using a protocol that does not support the node attribute. For example, when a service makes it possible for entities to subscribe to nodes via presence, it would address nodes as JIDs. If a pubsub node is addressable as a JID, the pubsub service MUST ensure that the NodeID conforms to the Resourceprep profile of Stringprep as described in <cite>RFC 3920</cite>.</p>
<p>Consider the following example, in which the pubsub service is located at the hostname pubsub.shakespeare.lit.</p>
<example caption='Node addressed as domain.tld/NodeID'><![CDATA[
<iq to='pubsub.shakespeare.lit/news announcements'>
...
</iq>
]]></example>
<p>Now consider the following example, in which the pubsub service is located at pubsub@shakespeare.lit.</p>
<example caption='Node addressed as user@domain.tld/NodeID'><![CDATA[
<iq to='pubsub@shakespeare.lit/news announcements'>
...
</iq>
]]></example>
</section3>
<section3 topic='JID+NodeID' anchor='addressing-jidnode'>
<p>If a pubsub node is addressable as a JID plus node, the NodeID MUST be the value of both the Service Discovery 'node' attribute and the pubsub 'node' attribute; i.e., for discovery purposes, a pubsub node is equivalent to a Service Discovery node. If a pubsub node is addressable as a JID plus node, the pubsub service SHOULD ensure that the NodeID conforms to the Resourceprep profile of Stringprep as described in <cite>RFC 3920</cite>.</p>
<p>Consider the following example, in which the (virtual) pubsub service is located at hamlet@denmark.lit.</p>
<example caption='Node addressed as JID+NodeID'><![CDATA[
<iq to='hamlet@denmark.lit'>
<query node='princely_musings'/>
</iq>
]]></example>
</section3>
</section2>
</section1>
<section1 topic='Entity Use Cases' anchor='entity'>
<p>This section defines the use cases for and protocols to be used by any entity that wishes to interact with a publish-subscribe service, mainly focused on Service Discovery use cases.</p>
<section2 topic='Discover Features' anchor='entity-features'>
<p>A service MUST respond to service discovery information requests qualified by the 'http://jabber.org/protocol/disco#info' namespace. The "disco#info" result returned by a pubsub service MUST indicate the identity of the service and indicate which pubsub features are supported.</p>
<example caption='Entity Queries Pubsub Service Regarding Supported Features'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='feature1'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>
<example caption='Pubsub Service Returns Set of Supported Features'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='feature1'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity category='pubsub' type='service'/>
<feature var='http://jabber.org/protocol/pubsub'/>
</query>
</iq>
]]></example>
<p>The possible pubsub features are noted throughout this document and have been registered as described in the <link url='#registrar'>XMPP Registrar Considerations</link> section of this document. For information regarding which features are required, recommended, and optional, see the <link url='#features'>Feature Summary</link> section of this document.</p>
</section2>
<section2 topic='Discover Nodes' anchor='entity-nodes'>
<p>If a service implements a hierarchy of nodes (by means of <link url='#collections'>Collection Nodes</link>), it MUST also enable entities to discover the nodes in that hierarchy by means of the <strong>Service Discovery</strong> protocol, subject to the recommendations in <cite>XEP-0030</cite> regarding large result sets (for which &xep0055; or some other protocol SHOULD be used). The following examples show the use of service discovery in discovering the nodes available at a hierarchical pubsub service.</p>
<p>Note: Node hierarchies and collection nodes are OPTIONAL. For details, refer to the <link url='#impl-semantics'>NodeID Semantics</link> and <link url='#collections'>Collection Nodes</link> sections of this document.</p>
<p>In the first example, an entity sends a service discovery items ("disco#items") request to the root node (i.e., the service itself), which is a <link url='#collections'>Collection Node</link>:</p>
<example caption='Entity asks service for all first-level nodes'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='nodes1'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
]]></example>
<example caption='Service returns all first-level nodes'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='nodes1'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item jid='pubsub.shakespeare.lit'
node='blogs'
name='Weblog updates'/>
<item jid='pubsub.shakespeare.lit'
node='news'
name='News and announcements'/>
</query>
</iq>
]]></example>
<p>In the second example, an entity sends a disco#items request to one of the first-level nodes, which is also a collection node:</p>
<example caption='Entity requests second-level nodes'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='nodes2'>
<query xmlns='http://jabber.org/protocol/disco#items'
node='blogs'/>
</iq>
]]></example>
<example caption='Service returns second-level nodes'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='nodes2'>
<query xmlns='http://jabber.org/protocol/disco#items'
node='blogs'>
<item jid='pubsub.shakespeare.lit'
node='princely_musings'/>
<item jid='pubsub.shakespeare.lit'
node='kingly_ravings'/>
<item jid='pubsub.shakespeare.lit'
node='starcrossed_stories'/>
<item jid='pubsub.shakespeare.lit'
node='moorish_meanderings'/>
</query>
</iq>
]]></example>
<p>If a node is a leaf node rather than a collection node and items have been published to the node, the service MAY return one &ITEM; element for each published item as described in the <link url='#entity-discoveritems'>Discover Items for a Node</link> section of this document, however such items MUST NOT include a 'node' attribute (since they are published items, not nodes).</p>
</section2>
<section2 topic='Discover Node Information' anchor='entity-info'>
<p>A pubsub service MUST allow entities to query individual nodes for the information associated with that node. The Service Discovery protocol MUST be used to discover this information. The "disco#info" result MUST include an identity with a category of "pubsub" and a type of either "leaf" or "collection".</p>
<p>Note: If a node has an identity type of "leaf", then it MUST NOT contain other nodes or collections (only items); if a node has an identity type of "collection", then it MUST NOT contain items (only other nodes or collections).</p>
<example caption='Entity queries collection node for information'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='info2'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='blogs'/>
</iq>
]]></example>
<example caption='Service responds with identity of pubsub/collection'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='meta1'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='blogs'>
<identity category='pubsub' type='collection'/>
</query>
</iq>
]]></example>
<example caption='Entity queries leaf node for information'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='info1'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='princely_musings'/>
</iq>
]]></example>
<example caption='Service responds with identity of pubsub/leaf'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='info1'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='princely_musings'>
...
<identity category='pubsub' type='leaf'/>
...
</query>
</iq>
]]></example>
</section2>
<section2 topic='Discover Node Metadata' anchor='entity-metadata'>
<p>The "disco#info" result MAY include detailed metadata about the node, encapsulated in the &xep0004; format as described in &xep0128;, where the data form context is specified by including a FORM_TYPE of "http://jabber.org/protocol/pubsub#metadata" in accordance with &xep0068;. If metadata is provided, it SHOULD include values for all configured options as well as "automatic" information such as the node creation date, a list of publishers, and the like.</p>
<example caption='Entity queries a node for information'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='meta1'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='princely_musings'/>
</iq>
]]></example>
<example caption='Service responds with information and metadata'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='meta1'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='princely_musings'>
<identity category='pubsub' type='leaf'/>
<feature var='http://jabber.org/protocol/pubsub'/>
<x xmlns='jabber:x:data' type='result'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#metadata</value>
</field>
<field var='pubsub#type' label='Payload type' type='text-single'>
<value>http://www.w3.org/2005/Atom</value>
</field>
<field var='pubsub#creator' label='Node creator' type='jid-single'>
<value>hamlet@denmark.lit</value>
</field>
<field var='pubsub#creation_date' label='Creation date' type='text-single'>
<value>2003-07-29T22:56:10Z</value>
</field>
<field var='pubsub#title' label='A short name for the node' type='text-single'>
<value>Princely Musings (Atom)</value>
</field>
<field var='pubsub#description' label='A description of the node' type='text-single'>
<value>Updates for Hamlet&apos;s Princely Musings weblog.</value>
</field>
<field var='pubsub#language' label='Default language' type='list-single'>
<value>en</value>
</field>
<field var='pubsub#contact' label='People to contact with questions' type='jid-multi'>
<value>bard@shakespeare.lit</value>
</field>
<field var='pubsub#access_model' label='Access model' type='list-single'>
<value>open</value>
</field>
<field var='pubsub#publish_model' label='Publish model' type='list-single'>
<value>publishers</value>
</field>
<field var='pubsub#max_items' label='Max # of items to persist' type='text-single'>
<value>120</value>
</field>
<field var='pubsub#owner' label='Node owners' type='jid-multi'>
<value>hamlet@denmark.lit</value>
</field>
<field var='pubsub#publisher' label='Publishers to this node' type='jid-multi'>
<value>hamlet@denmark.lit</value>
</field>
<field var='pubsub#num_subscribers' label='Number of subscribers to this node' type='text-single'>
<value>1066</value>
</field>
</x>
</query>
</iq>
]]></example>
<p>Note: Node metadata can be set in many ways. Some of it is based on node configuration (e.g., the owner's JID) whereas some of it may be dynamic (e.g., the number of subscribers). Any static information to be provided in the node metadata SHOULD be provided as fields in the node configuration form.</p>
<p>Note: The pubsub#language field SHOULD be list-single so that the pubsub service can present an appropriate list of languages and language codes.</p>
</section2>
<section2 topic='Discover Items for a Node' anchor='entity-discoveritems'>
<p>To discover the published items which exist on the service for a specific node, an entity MAY send a "disco#items" request to the node itself, and the service MAY return each item as a Service Discovery &ITEM; element. The 'name' attribute of each Service Discovery item MUST contain its ItemID and the item MUST NOT possess a 'node' attribute. This ItemID MAY then be used to retrieve the item using the protocol defined in the <link url='#subscriber-retrieve'>Retrieve Items from a Node</link> section of this document.</p>
<example caption='Entity requests all of the items for a node'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='items1'>
<query xmlns='http://jabber.org/protocol/disco#items'
node='princely_musings'/>
</iq>
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<query xmlns='http://jabber.org/protocol/disco#items'
node='princely_musings'>
<item jid='pubsub.shakespeare.lit' name='368866411b877c30064a5f62b917cffe'/>
<item jid='pubsub.shakespeare.lit' name='3300659945416e274474e469a1f0154c'/>
<item jid='pubsub.shakespeare.lit' name='4e30f35051b7b8b42abe083742187228'/>
<item jid='pubsub.shakespeare.lit' name='ae890ac52d0df67ed7cfdf51b644e901'/>
</query>
</iq>
]]></example>
</section2>
<section2 topic='Retrieve Subscriptions' anchor='entity-subscriptions'>
<p>An entity may want to query the service to retrieve its subscriptions for all nodes at the service. Support for this feature ("retrieve-subscriptions") is RECOMMENDED.</p>
<p>In order to make the request, the requesting entity MUST send an IQ-get whose &PUBSUB; child contains an empty &lt;subscriptions/&gt; element with no attributes.</p>
<example caption='Entity requests all current subscriptions'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='subscriptions1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscriptions/>
</pubsub>
</iq>
]]></example>
<p>If the service returns a list of subscriptions, it MUST return all subscriptions for all JIDs that match the bare JID &BAREJID; portion of the 'from' attribute on the request.</p>
<p>For each subscription, a &lt;subscription/&gt; element is returned specifying the NodeID, the JID that is affiliated (which MAY include a resource, depending on how the entity subscribed), and the current subscription state. If subscription identifiers are supported by the service, the 'subid' attribute MUST be present as well.</p>
<example caption='Service returns all current subscriptions'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit'
id='subscriptions1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscriptions>
<subscription node='node1' jid='francisco@denmark.lit' subscription='subscribed'/>
<subscription node='node2' jid='francisco@denmark.lit' subscription='subscribed'/>
<subscription node='node5' jid='francisco@denmark.lit' subscription='unconfigured'/>
<subscription node='node6' jid='francisco@denmark.lit' subscription='subscribed' subid='123-abc'/>
<subscription node='node6' jid='francisco@denmark.lit' subscription='subscribed' subid='004-yyy'/>
</subscriptions>
</pubsub>
</iq>
]]></example>
<p>If the requesting entity has no subscriptions, the pubsub service MUST return an empty &lt;subscriptions/&gt; element.</p>
<example caption='No subscriptions'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='subscriptions1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscriptions/>
</pubsub>
</iq>
]]></example>
<p>If the service does not support subscriptions retrieval, the service MUST respond with a &feature; error, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "retrieve-subscriptions".</p>
<example caption='Subscriptions retrieval not supported'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='subscriptions1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
feature='retrieve-subscriptions'/>
</error>
</iq>
]]></example>
<p>An entity MAY also request all of its subscriptions at a specific node (e.g., if it has subscriptions with multiple SubIDs) by including a 'node' attribute on the &lt;subscriptions/&gt; element.</p>
<example caption='Entity requests current subscriptions from a specific node'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='subscriptions2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscriptions node='princely_musings'/>
</pubsub>
</iq>
]]></example>
<p>The service would then return only the entity's subscriptions to that specific node; this acts as a filter on the entity's subscriptions.</p>
<example caption='Service returns all current subscriptions to a specific node'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit'
id='subscriptions2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscriptions node='node6'>
<subscription node='node6' jid='francisco@denmark.lit' subscription='subscribed' subid='123-abc'/>
<subscription node='node6' jid='francisco@denmark.lit' subscription='subscribed' subid='004-yyy'/>
</subscriptions>
</pubsub>
</iq>
]]></example>
</section2>
<section2 topic='Retrieve Affiliations' anchor='entity-affiliations'>
<p>An entity may want to query the service to retrieve its affiliations for all nodes at the service, or query a specific node for its affiliation with that node. Support for this feature ("retrieve-affiliations") is RECOMMENDED.</p>
<p>In order to make the request of the service, the requesting entity includes an empty &lt;affiliations/&gt; element with no attributes.</p>
<example caption='Entity requests all current affiliations'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='affil1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<affiliations/>
</pubsub>
</iq>
]]></example>
<p>If the service returns a list of affiliations, it MUST return all affiliations for all JIDs that match the bare JID &BAREJID; portion of the 'from' attribute on the request.</p>
<p>For each affiliation, an &lt;affiliation/&gt; element is returned containing the NodeID and the affiliation state (owner, publisher, publish-only, member, or outcast).</p>
<example caption='Service replies with all current affiliations'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit'
id='affil1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<affiliations>
<affiliation node='node1' affiliation='owner'/>
<affiliation node='node2' affiliation='publisher'/>
<affiliation node='node5' affiliation='outcast'/>
<affiliation node='node6' affiliation='owner'/>
</affiliations>
</pubsub>
</iq>
]]></example>
<p>If the requesting entity has no affiliations, the pubsub service MUST return an empty &lt;affiliations/&gt; element.</p>
<example caption='No affiliations'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='affil1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<affiliations/>
</pubsub>
</iq>
]]></example>
<p>If the service does not support affiliations retrieval, the service MUST respond with a &feature; error, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "retrieve-affiliations".</p>
<example caption='Affiliations retrieval not supported'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='affil1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
feature='retrieve-affiliations'/>
</error>
</iq>
]]></example>
<p>In order to make an affiliations request of a specific node, the requesting entity includes an empty &lt;affiliations/&gt; element with a 'node' attribute.</p>
<example caption='Entity requests affiliation at a specific node'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='affil2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<affiliations node='node6'/>
</pubsub>
</iq>
]]></example>
<example caption='Service replies with current affiliation'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit'
id='affil2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<affiliations>
<affiliation node='node6' affiliation='owner'/>
</affiliations>
</pubsub>
</iq>
]]></example>
</section2>
</section1>
<section1 topic='Subscriber Use Cases' anchor='subscriber'>
<p>This section defines the use cases for and protocols to be used by potential and actual subscribers. (Note: The <link url='#impl'>Implementation Notes</link> section of this document describes many important factors and business rules which a pubsub service MUST observe. In addition, the examples throughout assume the existence of a separate pubsub component and include any relevant 'from' addresses as stamped by a server or network edge.)</p>
<section2 topic='Subscribe to a Node' anchor='subscriber-subscribe'>
<section3 topic='Request' anchor='subscriber-subscribe-request'>
<p>When an XMPP entity wishes to subscribe to a node, it sends a subscription request to the pubsub service. The subscription request is an IQ-set where the &lt;pubsub/&gt; element contains one and only one &lt;subscribe/&gt; element. The &lt;subscribe/&gt; element SHOULD possess a 'node' attribute specifying the node to which the entity wishes to subscribe. The &lt;subscribe/&gt; element MUST also possess a 'jid' attribute specifying the exact XMPP address to be used as the subscribed JID -- often a bare JID &BAREJID; or full JID &FULLJID;.</p>
<p>Here is an example of a subscription request.</p>
<example caption='Entity subscribes to a node'><![CDATA[
<iq type='set'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='sub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscribe
node='princely_musings'
jid='francisco@denmark.lit'/>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Success Case' anchor='subscriber-subscribe-success'>
<p>If the subscription request is successfully processed, the server MUST inform the requesting entity that it is now subscribed (which MAY include a service-generated SubID).</p>
<example caption='Service replies with success'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscription
node='princely_musings'
jid='francisco@denmark.lit'
subid='ba49252aaa4f5d320c24d3766f0bdcade78c78d3'
subscription='subscribed'/>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Error Cases' anchor='subscriber-subscribe-error'>
<p>There are several reasons why the subscription request might fail:</p>
<ol>
<li>The bare JID portions of the JIDs do not match.</li>
<li>The node has an access model of "presence" and the requesting entity is not subscribed to the owner's presence.</li>
<li>The node has an access model of "roster" and the requesting entity is not in one of the authorized roster groups.</li>
<li>The node has an access model of "whitelist" and the requesting entity is not on the whitelist.</li>
<li>The service requires payment for subscriptions to the node.</li>
<li>The requesting entity is anonymous and the service does not allow anonymous entities to subscribe.</li>
<li>The requesting entity has a pending subscription.</li>
<li>The requesting entity is blocked from subscribing (e.g., because having an affiliation of outcast).</li>
<li>The requesting entity has attempted to establish too many subscriptions.</li>
<li>The node does not support subscriptions.</li>
<li>The node has moved.</li>
<li>The node does not exist.</li>
</ol>
<p>These error cases are described more fully in the following sections.</p>
<section4 topic='JIDs Do Not Match' anchor='subscriber-subscribe-error-nomatch'>
<p>If the specified JID is a bare JID or full JID, the service MUST at a minimum check the bare JID portion against the bare JID portion of the 'from' attribute on the received IQ request to make sure that the requesting entity has the same identity as the JID which is being requested to be added to the subscriber list.</p>
<p>If the bare JID portions of the JIDs do not match as described above and the requesting entity does not have some kind of admin or proxy privilege as defined by the implementation, the service MUST return a &badrequest; error, which SHOULD also include a pubsub-specific error condition of &lt;invalid-jid/&gt;.</p>
<example caption='JIDs do not match'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<invalid-jid xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
<p>Note: An implementation MAY enable the service administrator to configure a list of entities that are excluded from this check; those entities may be considered "trusted proxies" that are allowed to subscribe on behalf of other entities. In the same way, implementations MAY enable blacklisting of entities that are not allowed to perform specific operations (such as subscribing or creating nodes).</p>
</section4>
<section4 topic='Presence Subscription Required' anchor='subscriber-subscribe-error-presence'>
<p>For nodes with an access model of "presence", if the requesting entity is not subscribed to the owner's presence then the pubsub service MUST respond with a &notauthorized; error, which SHOULD also include a pubsub-specific error condition of &lt;presence-subscription-required/&gt;.</p>
<example caption='Entity is not authorized to create a subscription (presence subscription required)'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='auth'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<presence-subscription-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Not in Roster Group' anchor='subscriber-subscribe-error-rostergroup'>
<p>For nodes with an access model of "roster", if the requesting entity is not in one of the authorized roster groups then the pubsub service MUST respond with a &notauthorized; error, which SHOULD also include a pubsub-specific error condition of &lt;not-in-roster-group/&gt;.</p>
<example caption='Entity is not authorized to create a subscription (not in roster group)'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='auth'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<not-in-roster-group xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Not on Whitelist' anchor='subscriber-subscribe-error-whitelist'>
<p>For nodes with a node access model of "whitelist", if the requesting entity is not on the whitelist then the service MUST return a &notallowed; error, specifying a pubsub-specific error condition of &lt;closed-node/&gt;.</p>
<example caption='Node has whitelist access model'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<closed-node xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Payment Required' anchor='subscriber-subscribe-error-payment'>
<p>Commercial deployments may wish to link subscribers to a database of paying customers. If the subscriber needs to provide payment in order to subscribe to the node (e.g., if the subscriber is not in the customer database or the customer's account is not paid up), the service SHOULD return a &payment; error to the subscriber.</p>
<example caption='Payment is required for a subscription'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='auth'>
<payment-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Anonymous Subscriptions Not Allowed' anchor='subscriber-subscribe-error-anonymous'>
<p>Some XMPP servers may allow authentication using SASL ANONYMOUS; however, because the resulting entity is unstable (the assigned JID may not be owned by the same principal in a persistent manner), a service MAY prevent anonymous entities from subscribing to nodes and SHOULD use service discovery to determine if an entity has an identity of "account/anonymous". If a requesting entity is anonymous but the service does not allow anonymous entities to subscribe, the service SHOULD return a &forbidden; error to the subscriber.</p>
<example caption='Requesting entity is anonymous'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='anonymous@denmark.lit/foo'
id='sub1'>
<error type='cancel'>
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Subscription Pending' anchor='subscriber-subscribe-error-pending'>
<p>If the requesting entity has a pending subscription, the service MUST return a &notauthorized; error to the subscriber, specifying a pubsub-specific error condition of &lt;pending-subscription/&gt;.</p>
<example caption='Requesting entity has pending subscription'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='auth'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<pending-subscription xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Blocked' anchor='subscriber-subscribe-error-blocked'>
<p>If the requesting entity is blocked from subscribing (e.g., because having an affiliation of outcast), the service MUST return a &forbidden; error to the subscriber.</p>
<example caption='Requesting entity is blocked'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='auth'>
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Too Many Subscriptions' anchor='subscriber-subscribe-error-toomany'>
<p>If the requesting entity has attempted to establish too many subscriptions (where the definition of "too many" is a matter of local service policy), the service MUST return a &policy; error to the subscriber, specifying a pubsub-specific error condition of &lt;too-many-subscriptions/&gt;.</p>
<example caption='Requesting entity has exceeded limit on number of subscriptions'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='wait'>
<policy-violation xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<too-many-subscriptions xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
<p>The service can match on bare JID or full JID in determining which subscribing entities match for the purpose of determining if an entity has requested too many subscriptions.</p>
</section4>
<section4 topic='Subscriptions Not Supported' anchor='subscriber-subscribe-error-unsupported'>
<p>If the node does not allow entities to subscribe, the service SHOULD return a &feature; error to the subscriber, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "subscribe".</p>
<example caption='Subscribing not supported'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
feature='subscribe'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Node Has Moved' anchor='subscriber-subscribe-error-redirect'>
<p>If the node has, the service SHOULD return a &gone; error (if the node has moved permanently) or a &redirect; error (if the node has moved temporarily).</p>
<example caption='Node has moved'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='modify'>
<gone xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>
xmpp:pubsub.shakespeare.lit?;node=some-other-node
</gone>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Node Does Not Exist' anchor='subscriber-subscribe-error-node'>
<p>If the node does not exist, the service SHOULD return an &notfound; error to the subscriber.</p>
<example caption='Node does not exist'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='cancel'>
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
</section3>
<section3 topic='Approval Required' anchor='subscriber-subscribe-approval'>
<p>For nodes with an access model of "authorize", subscription requests MUST be approved by one of the node owners unless service policy allows entities with affiliations other than "none" to auto-subscribe (e.g., members and publishers might be allowed to auto-subscribe); therefore the pubsub service sends a message to the node owner(s) requesting authorization (see the <link url='#owner-subreq'>Manage Subscription Requests</link> section of this document). Because the subscription request may or may not be approved, the service MUST return a pending notification to the subscriber.</p>
<example caption='Service replies with pending'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscription
node='princely_musings'
jid='francisco@denmark.lit'
subscription='pending'/>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Configuration Required' anchor='subscriber-subscribe-configure'>
<p>If the entity must configure its subscription options (see the <link url='#subscriber-configure'>Configure Subscription Options</link> section of this document) before receiving event notifications, the service MUST so inform the entity. It SHOULD do so by returning an IQ-result to the requesting entity with a notation that configuration of subscription options is required.</p>
<example caption='Service replies with success and indicates that subscription configuration is required'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscription
node='princely_musings'
jid='francisco@denmark.lit'
subscription='unconfigured'>
<subscribe-options>
<required/>
</subscribe-options>
</subscription>
</pubsub>
</iq>
]]></example>
<p>Note: The node shall include the &lt;required/&gt; child element only if the subscriber must configure the subscription before receiving any event notifications. A service MAY time out subscription requests if configuration is required and a configuration request is not submitted within a reasonable amount of time (which shall be determined by the service or node configuration).</p>
<p>Alternatively, if the service is unable to create the subscription without simultaneous configuration, the service MAY return a &notacceptable; error, specifying a pubsub-specific error condition of &lt;configuration-required/&gt;.</p>
<example caption='Service returns error specifying that subscription configuration is required'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscribe
node='princely_musings'
jid='francisco@denmark.lit'/>
<options node='princely_musings' jid='francisco@denmark.lit'>
<x xmlns='jabber:x:data' type='submit'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#subscribe_options</value>
</field>
<field var='pubsub#deliver'><value>1</value></field>
<field var='pubsub#digest'><value>0</value></field>
<field var='pubsub#include_body'><value>false</value></field>
<field var='pubsub#show-values'>
<value>chat</value>
<value>online</value>
<value>away</value>
</field>
</x>
</options>
</pubsub>
<error type='modify'>
<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<configuration-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
<p>If the &lt;required/&gt; element is not included and no error is returned, the subscription takes effect immediately and the entity may configure the subscription at any time (the service MAY indicate that subscription options are supported by including an empty &lt;subscribe-options/&gt; element in the IQ-result, as shown in the following example).</p>
<example caption='Service replies with success and indicates that subscription options are supported but not required'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscription
node='princely_musings'
jid='francisco@denmark.lit'
subscription='unconfigured'>
<subscribe-options/>
</subscription>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Multiple Subscriptions' anchor='subscriber-subscribe-multi'>
<p>An entity may wish to subscribe using different subscription options, which it can do by subscribing multiple times to the same node. Support for this feature ("multi-subscribe") is OPTIONAL.</p>
<p>If multiple subscriptions for the same JID are allowed, the service MUST use the 'subid' attribute to differentiate between subscriptions for the same entity (therefore the SubID MUST be unique for each node+JID combination and the SubID MUST be present on the &lt;subscription/&gt; element any time it is sent to the subscriber). It is NOT RECOMMENDED for clients to generate SubIDs, since collisions might result; therefore a service SHOULD generate the SubID on behalf of the subscriber and MAY overwrite SubIDs if they are provided by subscribers. If the service does not allow multiple subscriptions for the same entity and it receives an additional subscription request, the service MUST return the current subscription state (as if the subscription was just approved).</p>
<p>When the pubsub service generates event notifications, it SHOULD send only one event notification to an entity that has multiple subscriptions, rather than one event notification for each subscription. By "entity" here is meant the JID specified for the subscription, whether bare JID or full JID; however, if the same bare JID has multiple subscriptions but those subscriptions are for different full JIDs (e.g., one subscription for user@domain.tld./foo and another subscription for user@domain.tld/bar), the service MUST treat those as separate JIDs for the purpose of generating event notifications.</p>
</section3>
<section3 topic='Receiving the Last Published Item' anchor='subscriber-subscribe-last'>
<p>When a subscription request is successfully processed, the service MAY send the last published item to the new subscriber. The message containing this item SHOULD be stamped with extended information qualified by the 'urn:xmpp:delay' namespace (see &xep0203;) to indicate it is sent with delayed delivery. (Note that in this example the event notification is sent to the bare JID since that is the subscribed JID.)</p>
<example caption='Service sends last published item'><![CDATA[
<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</items>
</event>
<delay xmlns='urn:xmpp:delay' stamp='2003-12-13T23:58:37Z'/>
</message>
]]></example>
<p>If the service sends the last published item by default for all nodes (subject to overriding by node configuration), it MUST return a feature of "http://jabber.org/protocol/pubsub#last-published" in its responsess to disco#info requests.</p>
</section3>
</section2>
<section2 topic='Unsubscribe from a Node' anchor='subscriber-unsubscribe'>
<section3 topic='Request' anchor='subscriber-unsubscribe-request'>
<p>To unsubscribe from a node, the subscriber sends an IQ-set whose &PUBSUB; child contains an &lt;unsubscribe/&gt; element that specifies the node and the subscribed JID.</p>
<example caption='Entity unsubscribes from a node'><![CDATA[
<iq type='set'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='unsub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<unsubscribe
node='princely_musings'
jid='francisco@denmark.lit'/>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Success Case' anchor='subscriber-unsubscribe-success'>
<p>If the request can be successfully processed, the service MUST return an IQ result and MAY include a &PUBSUB; child element with the updated &lt;subscription/&gt; element for that node. If subscription identifiers are supported by the service, the 'subid' attribute MUST be present as well.</p>
<example caption='Service replies with success'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='unsub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscription
node='princely_musings'
jid='francisco@denmark.lit'
subscription='none'
subid='ba49252aaa4f5d320c24d3766f0bdcade78c78d3'/>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Error Cases' anchor='subscriber-unsubscribe-error'>
<p>There are several reasons why the unsubscribe request might fail:</p>
<ol>
<li>The requesting entity has multiple subscriptions to the node but does not specify a subscription ID.</li>
<li>The request does not specify an existing subscriber.</li>
<li>The requesting entity does not have sufficient privileges to unsubscribe the specified JID.</li>
<li>The node does not exist.</li>
<li>The request specifies a subscription ID that is not valid or current.</li>
</ol>
<p>These error cases are described more fully in the following sections.</p>
<section4 topic='No Subscription ID' anchor='subscriber-unsubscribe-error-nosubid'>
<p>If the requesting entity has multiple subscriptions to the node but does not specify a subscription ID, the service MUST return a &badrequest; error, which SHOULD also include a pubsub-specific error condition of &lt;subid-required/&gt;.</p>
<example caption='Entity did not specify SubID'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='unsub1'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<subid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='No Such Subscriber' anchor='subscriber-unsubscribe-error-nosub'>
<p>If the value of the 'jid' attribute does not specify an existing subscriber, the pubsub service MUST return an error stanza, which SHOULD be &unexpected; and which SHOULD also include a pubsub-specific error condition of &lt;not-subscribed/&gt;.</p>
<example caption='Requesting entity is not a subscriber'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='unsub1'>
<error type='cancel'>
<unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<not-subscribed xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Insufficient Privileges' anchor='subscriber-unsubscribe-error-forbidden'>
<p>If the requesting entity is prohibited from unsubscribing the specified JID, the service MUST return a &forbidden; error. The service MUST validate that the entity making the request is authorized to unsubscribe the entity. If the subscriber's JID is of the form &FULLJID;, a service MUST perform this check by comparing the &BAREJID; part of the two JIDs to ensure that they match. If the bare JID portions of the JIDs do not match and the requesting entity is not authorized to unsubscribe the JID (e.g., because it is not a service-wide admin or authorized proxy), the service MUST return a &forbidden; error.</p>
<example caption='Requesting entity is prohibited from unsubscribing entity'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='unsub1'>
<error type='auth'>
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Node Does Not Exist' anchor='subscriber-unsubscribe-error-node'>
<p>If the node does not exist, the pubsub service MUST return an &notfound; error.</p>
<example caption='Node does not exist'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='unsub1'>
<error type='cancel'>
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Bad Subscription ID' anchor='subscriber-unsubscribe-error-badsubid'>
<p>If a subscription identifier is associated with the subscription, the unsubscribe request MUST include an appropriate 'subid' attribute. If the unsubscribe request includes a SubID but SubIDs are not supported for the node (or the subscriber did not subscribe using a SubID in the first place), the service SHOULD ignore the SubID and simply unsubscribe the entity. If the subscriber originally subscribed with a SubID but the unsubscribe request includes a SubID that is not valid or current for the subscriber, the service MUST return a &notacceptable; error, which SHOULD also include a pubsub-specific error condition of &lt;invalid-subid/&gt;.</p>
<example caption='Invalid subscription identifier'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='unsub1'>
<error type='modify'>
<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<invalid-subid xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
</section3>
</section2>
<section2 topic='Configure Subscription Options' anchor='subscriber-configure'>
<p>An implementation MAY allow subscribers to configure subscription options. Implementations SHOULD use the <cite>Data Forms</cite> protocol to accomplish this configuration (however, an out-of-band mechanism such as a web interface could be offered as well).</p>
<section3 topic='Advertising Support' anchor='subscriber-configure-support'>
<p>If a service supports subscription options it MUST advertise that fact in its response to a "disco#info" query by including a feature whose 'var' attribute is "pubsub#subscription-options".</p>
<example caption='Pubsub service indicates support for subscription options'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='feature1'>
<query xmlns='http://jabber.org/protocol/disco#info'>
...
<feature var='http://jabber.org/protocol/pubsub#subscription-options'/>
...
</query>
</iq>
]]></example>
</section3>
<section3 topic='Request' anchor='subscriber-configure-request'>
<p>A subscriber requests the subscription options by including an &lt;options/&gt; element inside an IQ-get stanza.</p>
<example caption='Subscriber requests subscription options form'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='options1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<options node='princely_musings' jid='francisco@denmark.lit'/>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Success Case' anchor='subscriber-configure-success'>
<p>If the request can be successfully processed, the service MUST respond with the options.</p>
<example caption='Service responds with the options form'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='options1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<options node='princely_musings' jid='francisco@denmark.lit'>
<x xmlns='jabber:x:data' type='form'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#subscribe_options</value>
</field>
<field var='pubsub#deliver' type='boolean'
label='Enable delivery?'>
<value>1</value>
</field>
<field var='pubsub#digest' type='boolean'
label='Receive digest notifications (approx. one per day)?'>
<value>0</value>
</field>
<field var='pubsub#include_body' type='boolean'
label='Receive message body in addition to payload?'>
<value>false</value>
</field>
<field
var='pubsub#show-values'
type='list-multi'
label='Select the presence types which are
allowed to receive event notifications'>
<option label='Want to Chat'><value>chat</value></option>
<option label='Available'><value>online</value></option>
<option label='Away'><value>away</value></option>
<option label='Extended Away'><value>xa</value></option>
<option label='Do Not Disturb'><value>dnd</value></option>
<value>chat</value>
<value>online</value>
</field>
</x>
</options>
</pubsub>
</iq>
]]></example>
<p>Note: The foregoing example shows some (but by no means all) of the possible configuration options that MAY be provided. If an implementation provides these options using the <strong>Data Forms</strong> protocol, it MUST use the field variables that are registered with the XMPP Registrar in association with the 'http://jabber.org/protocol/pubsub' namespace (a preliminary representation of those field variables is shown above and in the <link url='#registrar-formtypes-subscribe'>pubsub#subscribe_options FORM_TYPE</link> section of this document, but MUST NOT be construed as canonical since the XMPP Registrar may standardize additional fields at a later date without changes to this document).</p>
<p>Note: Many of the relevant data form fields are of type "boolean" and MUST be handled accordingly. &BOOLEANNOTE;</p>
</section3>
<section3 topic='Error Cases' anchor='subscriber-configure-error'>
<p>There are several reasons why the options request might fail:</p>
<ol>
<li>The requesting entity does not have sufficient privileges to modify subscription options for the specified JID.</li>
<li>The requesting entity (or specified subscriber) is not subscribed.</li>
<li>The request does not specify both the NodeID and the subscriber's JID.</li>
<li>The request does not specify a subscription ID but one is required.</li>
<li>The request specifies a subscription ID that is not valid or current.</li>
<li>Subscription options are not supported.</li>
<li>The node does not exist.</li>
</ol>
<p>These error cases are described more fully in the following sections.</p>
<section4 topic='Insufficient Privileges' anchor='subscriber-configure-error-forbidden'>
<p>When requesting subscription options, the subscriber MUST specify the JID that is subscribed to the node and SHOULD specify a node (if no node is specified, i.e. via node="", the service MUST assume that the requesting entity wishes to request subscription options for its subscription to the root collection node; refer to <cite>XEP-0248</cite> for details).</p>
<p>The service MUST validate that the entity making the request is authorized to set the subscription options for the subscribed entity. If the subscriber's JID is of the form &FULLJID;, a service MUST perform this check by comparing the &BAREJID; part of the two JIDs to ensure that they match. If the bare JID portions of the JIDs do not match and the requesting entity is not authorized to modify subscription options for the JID (e.g., because it is not a service-wide admin or authorized proxy), the service MUST return a &forbidden; error.</p>
<example caption='Requesting entity does not have sufficient privileges to modify subscription options'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='auth'>
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='No Such Subscriber' anchor='subscriber-configure-error-nosub'>
<p>If the requesting entity (or specified subscriber, if different) is not subscribed, the service MUST return an &unexpected; error, which SHOULD also include a pubsub-specific error condition of &lt;not-subscribed/&gt;.</p>
<example caption='No such subscriber'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='options1'>
<error type='modify'>
<unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<not-subscribed xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Subscriber JID Required' anchor='subscriber-configure-error-jid'>
<p>If the subscriber does not specify a subscriber JID, the service MUST return a &badrequest; error, which SHOULD also include a pubsub-specific error condition of &lt;jid-required/&gt;.</p>
<example caption='Subscriber JID not specified'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='options1'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<jid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Subscription ID Required' anchor='subscriber-configure-error-subid'>
<p>If a subscription identifier is associated with the subscription, the 'subid' attribute MUST be present on the request in order for the service to differentiate subscriptions for the same entity. If the 'subid' is required but not provided, the service MUST return a &badrequest; error, which SHOULD also include a pubsub-specific error condition of &lt;subid-required/&gt;.</p>
<example caption='SubID required'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<subid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Invalid Subscription ID' anchor='subscriber-configure-error-badsubid'>
<p>If a subscription identifier is associated with the subscription but the request includes a SubID that is not valid or current for the subscriber, the service MUST return a &notacceptable; error, which SHOULD also include a pubsub-specific error condition of &lt;invalid-subid/&gt;.</p>
<example caption='Invalid subscription identifier'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='unsub1'>
<error type='modify'>
<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<invalid-subid xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Subscription Options Not Supported' anchor='subscriber-configure-error-options'>
<p>If the node or service does not support subscription options, the service MUST respond with a &feature; error, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "subscription-options".</p>
<example caption='Subscription options not supported'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='options1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
feature='subscription-options'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Node Does Not Exist' anchor='subscriber-configure-error-node'>
<p>If the node does not exist, the pubsub service MUST return an &notfound; error.</p>
<example caption='Node does not exist'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='options1'>
<error type='cancel'>
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
</section3>
<section3 topic='Form Submission' anchor='subscriber-configure-submit'>
<p>After receiving the configuration form, the requesting entity SHOULD submit the form in order to update the entity's subscription options for that node.</p>
<example caption='Subscriber submits completed options form'><![CDATA[
<iq type='set'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='options2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<options node='princely_musings' jid='francisco@denmark.lit'>
<x xmlns='jabber:x:data' type='submit'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#subscribe_options</value>
</field>
<field var='pubsub#deliver'><value>1</value></field>
<field var='pubsub#digest'><value>0</value></field>
<field var='pubsub#include_body'><value>false</value></field>
<field var='pubsub#show-values'>
<value>chat</value>
<value>online</value>
<value>away</value>
</field>
</x>
</options>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Form Processing' anchor='subscriber-configure-process'>
<section4 topic='Success' anchor='subscriber-configure-process-success'>
<p>If the service can successfully process the submission, it MUST respond with success.</p>
<example caption='Service responds with success'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='options2'/>
]]></example>
</section4>
<section4 topic='Failure' anchor='subscriber-configure-process-failure'>
<p>If the subscriber attempts to set an invalid group of options, the service MUST respond with a &badrequest; error.</p>
<example caption='Service responds with Bad Request for invalid options'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='options2'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<invalid-options xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
<p>The other errors already mentioned for getting subscription options also apply to setting subscription options.</p>
</section4>
</section3>
<section3 topic='Subscribe and Configure' anchor='subscriber-configure-subandconfig'>
<p>As noted, if a service supports subscription options, an entity MAY subscribe and provide the subscription options in the same stanza.</p>
<p>Note: The &lt;options/&gt; element MUST follow the &lt;subscribe/&gt; element and MUST NOT possess a 'node' attribute or 'jid' attribute, since the value of the &lt;subscribe/&gt; element's 'node' attribute specifies the desired NodeID and the value of the &lt;subscribe/&gt; element's 'jid' attribute specifies the subscriber's JID; if any of these rules are violated, the service MUST return a &badrequest; error.</p>
<example caption='Entity subscribes to node and sets configuration options'><![CDATA[
<iq type='set'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='sub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscribe node='princely_musings' jid='francisco@denmark.lit'/>
<options>
<x xmlns='jabber:x:data' type='submit'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#subscribe_options</value>
</field>
<field var='pubsub#deliver'><value>1</value></field>
<field var='pubsub#digest'><value>0</value></field>
<field var='pubsub#include_body'><value>false</value></field>
<field var='pubsub#show-values'>
<value>chat</value>
<value>online</value>
<value>away</value>
</field>
</x>
</options>
</pubsub>
</iq>
]]></example>
<p>When the service informs the client of success, it SHOULD include a data form of type "result" informing the client of the resulting configuration options.</p>
<example caption='Service replies with success (including configuration options)'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='sub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscription
node='princely_musings'
jid='francisco@denmark.lit'
subid='ba49252aaa4f5d320c24d3766f0bdcade78c78d3'
subscription='subscribed'/>
<options>
<x xmlns='jabber:x:data' type='result'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#subscribe_options</value>
</field>
<field var='pubsub#deliver'><value>1</value></field>
<field var='pubsub#digest'><value>0</value></field>
<field var='pubsub#include_body'><value>false</value></field>
<field var='pubsub#show-values'>
<value>chat</value>
<value>online</value>
<value>away</value>
</field>
</x>
</options>
</pubsub>
</iq>
]]></example>
</section3>
</section2>
<section2 topic='Request Default Subscription Configuration Options' anchor='subscribe-default'>
<p>An entity might want to request information about the default subscription configuration. Support for this feature is OPTIONAL.</p>
<section3 topic='Request' anchor='subscriber-default-request'>
<p>To get the default subscription options for a node, the entity MUST send an empty &lt;default/&gt; element to the node; in response, the node SHOULD return the default subscription options.</p>
<example caption='Entity requests default subscription configuration options'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='def1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<default node='princely_musings'/>
</pubsub>
</iq>
]]></example>
<p>Note: Here the namespace is 'http://jabber.org/protocol/pubsub' (not 'http://jabber.org/protocol/pubsub#owner' as for retrieval of the default node configuration options).</p>
<p>The service itself MAY also have default subscription configuration options. To get the default subscription configuration options all (leaf) nodes at a service, the entity MUST send an empty &lt;default/&gt; element but not specifiy a node; in response, the service SHOULD return the default subscription options.</p>
<example caption='Entity requests default subscription configuration options'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='def2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<default/>
</pubsub>
</iq>
]]></example>
<p>The process for retrieving the default subscription configuration options for collection nodes is described in <cite>XEP-0248</cite>.</p>
</section3>
<section3 topic='Success Case' anchor='subscriber-default-success'>
<p>If no error occurs, the node MUST return the default subscription configuration options.</p>
<example caption='Service responds with default subscription configuration options'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='def1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<default node='princely_musings'>
<x xmlns='jabber:x:data' type='result'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#subscribe_options</value>
</field>
<field var='pubsub#deliver'><value>1</value></field>
<field var='pubsub#digest'><value>0</value></field>
<field var='pubsub#include_body'><value>false</value></field>
<field var='pubsub#show-values'>
<value>chat</value>
<value>online</value>
<value>away</value>
</field>
</x>
</default>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Error Cases' anchor='subscriber-default-error'>
<p>There are several reasons why the default subscription configuration options request might fail:</p>
<ol>
<li>The service does not support subscription configuration.</li>
<li>The service does not support retrieval of default subscription configuration.</li>
</ol>
<p>These error cases are described more fully in the following sections.</p>
<section4 topic='Node Configuration Not Supported' anchor='subscriber-default-error-noconfig'>
<p>If the node does not support subscription configuration, it MUST return a &feature; error, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "subscription-options".</p>
<example caption='Service does not support subscription configuration'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='def1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
feature='subscription-options'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Default Subscription Configuration Retrieval Not Supported' anchor='subscriber-default-error-notsupported'>
<p>If the node does not support retrieval of default subscription configuration options, it MUST return a &feature; error, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "retrieve-default-sub".</p>
<example caption='Service does not support retrieval of default subscription configuration options'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='def1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
feature='retrieve-default-sub'/>
</error>
</iq>
]]></example>
</section4>
</section3>
</section2>
<section2 topic='Retrieve Items from a Node' anchor='subscriber-retrieve'>
<p>Implementations of pubsub that choose to persist items MAY allow entities to request existing items from a node (e.g., an entity may wish to do this after successfully subscribing in order to receive all the items in the publishing history for the node).</p>
<section3 topic='Permissions' anchor='subscriber-retrieve-perms'>
<p>The service MUST conform to the node's access model in determining whether to return items to the entity that requests them. Specifically:</p>
<ul>
<li><p>If the access model is "open", the service SHOULD allow any entity (whether or not it is subscribed) to retrieve items.</p></li>
<li><p>If the access model is "presence", the service SHOULD allow any entity that is subscribed to the owner's presence to retrieve items.</p></li>
<li><p>If the access model is "roster", the service SHOULD allow any entity that is subscribed to the owner's presence and contained in the relevant roster group(s) to retrieve items.</p></li>
<li><p>If the access model is "authorize" or "whitelist", the service MUST allow only subscribed entities to retrieve items.</p></li>
</ul>
<p>The only exception foreseen to the SHOULD requirements for the foregoing access models is the enforcement of local privacy and security policies as specified more fully in the <link url='#security'>Security Considerations</link> section of this document. (In addition, a service MUST always allow the node owner to retrieve items from a node and SHOULD always allow a publisher to do so.)</p>
</section3>
<section3 topic='Requesting All Items' anchor='subscriber-retrieve-requestall'>
<p>The subscriber may request all items by specifying only the Node ID without restrictions.</p>
<example caption='Subscriber requests all items'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='items1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings'/>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Returning All Items' anchor='subscriber-retrieve-returnall'>
<p>The service then SHOULD return all available items at the node, although it MAY truncate the result set if a large number of items has been published (see next section) and naturally it cannot return items that have been deleted, expired, etc.</p>
<example caption='Service returns all items'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings'>
<item id='368866411b877c30064a5f62b917cffe'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>The Uses of This World</title>
<summary>
O, that this too too solid flesh would melt
Thaw and resolve itself into a dew!
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32396</id>
<published>2003-12-12T17:47:23Z</published>
<updated>2003-12-12T17:47:23Z</updated>
</entry>
</item>
<item id='3300659945416e274474e469a1f0154c'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Ghostly Encounters</title>
<summary>
O all you host of heaven! O earth! what else?
And shall I couple hell? O, fie! Hold, hold, my heart;
And you, my sinews, grow not instant old,
But bear me stiffly up. Remember thee!
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32396</id>
<published>2003-12-12T23:21:34Z</published>
<updated>2003-12-12T23:21:34Z</updated>
</entry>
</item>
<item id='4e30f35051b7b8b42abe083742187228'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Alone</title>
<summary>
Now I am alone.
O, what a rogue and peasant slave am I!
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32396</id>
<published>2003-12-13T11:09:53Z</published>
<updated>2003-12-13T11:09:53Z</updated>
</entry>
</item>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</items>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Returning Some Items' anchor='subscriber-retrieve-returnsome'>
<p>A node may have a large number of items associated with it, in which case it may be problematic to return all of the items in response to an items request. In this case, the service SHOULD return some of the items and note that the list of items has been truncated by including a &xep0059; notation.</p>
<example caption='Service returns some items via result set management'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings'>
<item id='368866411b877c30064a5f62b917cffe'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>The Uses of This World</title>
<summary>
O, that this too too solid flesh would melt
Thaw and resolve itself into a dew!
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32396</id>
<published>2003-12-12T17:47:23Z</published>
<updated>2003-12-12T17:47:23Z</updated>
</entry>
</item>
<item id='3300659945416e274474e469a1f0154c'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Ghostly Encounters</title>
<summary>
O all you host of heaven! O earth! what else?
And shall I couple hell? O, fie! Hold, hold, my heart;
And you, my sinews, grow not instant old,
But bear me stiffly up. Remember thee!
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32396</id>
<published>2003-12-12T23:21:34Z</published>
<updated>2003-12-12T23:21:34Z</updated>
</entry>
</item>
<item id='4e30f35051b7b8b42abe083742187228'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Alone</title>
<summary>
Now I am alone.
O, what a rogue and peasant slave am I!
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32396</id>
<published>2003-12-13T11:09:53Z</published>
<updated>2003-12-13T11:09:53Z</updated>
</entry>
</item>
</items>
<set xmlns='http://jabber.org/protocol/rsm'>
<first index='0'>368866411b877c30064a5f62b917cffe</first>
<last>4e30f35051b7b8b42abe083742187228</last>
<count>19</count>
</set>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Returning the Last Published Item' anchor='subscriber-retrieve-returnlast'>
<p>Even if the service or node does not support persistent items, it MAY return the last published item.</p>
<example caption='Service returns last published item'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</items>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Returning Notifications Only' anchor='subscriber-retrieve-returnnotify'>
<p>A service MAY return event notifications without payloads (e.g., to conserve bandwidth). If so, the client MAY request a specific item (using the ItemID) in order to retrieve the payload. When an entity requests items by ItemID, implementations MUST allow multiple items to be specified in the request.</p>
<example caption='Subscriber requests specific items by ItemID'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='items3'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings'>
<item id='368866411b877c30064a5f62b917cffe'/>
<item id='4e30f35051b7b8b42abe083742187228'/>
</items>
</pubsub>
</iq>
]]></example>
<example caption='Service sends requested item(s)'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
id='items3'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings'>
<item id='368866411b877c30064a5f62b917cffe'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>The Uses of This World</title>
<summary>
O, that this too too solid flesh would melt
Thaw and resolve itself into a dew!
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32396</id>
<published>2003-12-12T17:47:23Z</published>
<updated>2003-12-12T17:47:23Z</updated>
</entry>
</item>
<item id='4e30f35051b7b8b42abe083742187228'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Alone</title>
<summary>
Now I am alone.
O, what a rogue and peasant slave am I!
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32396</id>
<published>2003-12-13T11:09:53Z</published>
<updated>2003-12-13T11:09:53Z</updated>
</entry>
</item>
</items>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Requesting the Most Recent Items' anchor='subscriber-retrieve-requestrecent'>
<p>A service MAY allow entities to request the most recent N items by using the 'max_items' attribute. When max_items is used, implementations SHOULD return the N most recent (as opposed to the N oldest) items. (Note: A future version of this specification may recommend the use of <cite>XEP-0059</cite> instead of the 'max_items' attribute.)</p>
<example caption='Subscriber requests two most recent items'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='items2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings' max_items='2'/>
</pubsub>
</iq>
]]></example>
<example caption='Service returns two most recent items'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings'>
<item id='4e30f35051b7b8b42abe083742187228'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Alone</title>
<summary>
Now I am alone.
O, what a rogue and peasant slave am I!
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32396</id>
<published>2003-12-13T11:09:53Z</published>
<updated>2003-12-13T11:09:53Z</updated>
</entry>
</item>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</items>
</pubsub>
</iq>
]]></example>
<p>If there are fewer items in the node than requested, the service should return all of them.</p>
<example caption='Service returns no items if it has none'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings'/>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Requesting a Particular Item' anchor='subscriber-retrieve-requestone'>
<p>The subscriber can request a particular item by specifying the Node ID and the appropriate ItemID.</p>
<example caption='Subscriber requests a particular item'><![CDATA[
<iq type='get'
from='francisco@denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='items3'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'/>
</items>
</pubsub>
</iq>
]]></example>
<p>The service would then return that specific item, if available.</p>
</section3>
<section3 topic='Error Cases' anchor='subscriber-retrieve-error'>
<p>There are several reasons why the items retrieval request might fail:</p>
<ol>
<li>The requesting entity has multiple subscriptions to the node but does not specify a subscription ID.</li>
<li>The requesting entity is subscribed but specifies an invalid subscription ID.</li>
<li>The node does not return items to unsubscribed entities and the requesting entity is not subscribed.</li>
<li>The service or node does not support persistent items and does not return the last published item.</li>
<li>The service or node does not support item retrieval.</li>
<li>The node has an access model of "presence" and the requesting entity is not subscribed to the owner's presence.</li>
<li>The node has an access model of "roster" and the requesting entity is not in one of the authorized roster groups.</li>
<li>The node has an access model of "whitelist" and the requesting entity is not on the whitelist.</li>
<li>The service or node requires payment for item retrieval.</li>
<li>The requesting entity is blocked from retrieving items from the node (e.g., because having an affiliation of outcast).</li>
<li>The node does not exist.</li>
</ol>
<p>These error cases are described more fully in the following sections.</p>
<section4 topic='Subscription ID Required' anchor='subscriber-retrieve-error-subid'>
<p>If the requesting entity has multiple subscriptions to the node but does not specify a subscription ID, the service MUST return a &badrequest; error to the subscriber, which SHOULD also include a pubsub-specific error condition of &lt;subid-required/&gt;.</p>
<example caption='Entity did not specify SubID'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<subid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Invalid Subscription ID' anchor='subscriber-retrieve-error-badsubid'>
<p>If the requesting entity is subscribed but specifies an invalid subscription ID, the service MUST return a &notacceptable; error to the subscriber, which SHOULD also include a pubsub-specific error condition of &lt;invalid-subid/&gt;.</p>
<example caption='Entity specified invalid SubID'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<error type='modify'>
<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<invalid-subid xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Entity Not Subscribed' anchor='subscriber-retrieve-error-notsubscribed'>
<p>If the node does not return items to unsubscribed entities and the requesting entity is not subscribed (which includes having a pending subscription), the service MUST return a &notauthorized; error to the subscriber, which SHOULD also include a pubsub-specific error condition of &lt;not-subscribed/&gt;.</p>
<example caption='Entity is not subscribed'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<error type='auth'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<not-subscribed xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Persistent Items Not Supported' anchor='subscriber-retrieve-error-persistent'>
<p>If the service or node does not support persistent items and does not return the last published item, the service MUST return a &feature; error to the subscriber, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "persistent-items".</p>
<example caption='Persistent items not supported'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
feature='persistent-items'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Item Retrieval Not Supported' anchor='subscriber-retrieve-error-notsupported'>
<p>If the service or node does not support item retrieval (e.g., because the node is a collection node as described in <cite>XEP-0248</cite>), the service MUST return a &feature; error to the subscriber, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "retrieve-items".</p>
<example caption='Item retrieval not supported'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
feature='retrieve-items'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Presence Subscription Required' anchor='subscriber-retrieve-error-presence'>
<p>For nodes with an access model of "presence", if the requesting entity is not subscribed to the owner's presence then the pubsub service MUST respond with a &notauthorized; error, which SHOULD also include a pubsub-specific error condition of &lt;presence-subscription-required/&gt;.</p>
<example caption='Entity is not authorized to retrieve items (presence subscription required)'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<error type='auth'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<presence-subscription-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Not in Roster Group' anchor='subscriber-retrieve-error-rostergroup'>
<p>For nodes with an access model of "roster", if the requesting entity is not in one of the authorized roster groups then the pubsub service MUST respond with a &notauthorized; error, which SHOULD also include a pubsub-specific error condition of &lt;not-in-roster-group/&gt;.</p>
<example caption='Entity is not authorized to retrieve items (not in roster group)'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<error type='auth'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<not-in-roster-group xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Not on Whitelist' anchor='subscriber-retrieve-error-whitelist'>
<p>For nodes with a node access model of "whitelist", if the requesting entity is not on the whitelist then the service MUST return a &notallowed; error, specifying a pubsub-specific error condition of &lt;closed-node/&gt;.</p>
<example caption='Node has whitelist access model'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<closed-node xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Payment Required' anchor='subscriber-retrieve-error-payment'>
<p>Commercial deployments may wish to link subscribers to a database of paying customers. If the subscriber needs to provide payment in order to retrieve items from the node (e.g., if the subscriber is not in the customer database or the customer's account is not paid up), the service SHOULD return a &payment; error to the subscriber.</p>
<example caption='Payment is required to retrieve items'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<error type='auth'>
<payment-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Blocked' anchor='subscriber-retrieve-error-blocked'>
<p>If the requesting entity is blocked from retrieving items (e.g., because having an affiliation of outcast), the service MUST return a &forbidden; error to the subscriber.</p>
<example caption='Requesting entity is blocked'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<error type='auth'>
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Node Does Not Exist' anchor='subscriber-retrieve-error-node'>
<p>If the node does not exist, the service SHOULD return an &notfound; error to the subscriber.</p>
<example caption='Node does not exist'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<error type='cancel'>
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='No Such Item(s)' anchor='subscriber-retrieve-error-items'>
<p>If there are no items at the node or the requested items do not exist, the service SHOULD return an IQ stanza of type "result" with an empty &lt;items/&gt; element.</p>
<example caption='No such item(s)'><![CDATA[
<iq from='pubsub.shakespeare.lit'
id='items1'
to='francisco@denmark.lit/barracks'
type='result'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings'/>
</pubsub>
</iq>
]]></example>
</section4>
</section3>
</section2>
</section1>
<section1 topic='Publisher Use Cases' anchor='publisher'>
<section2 topic='Publish an Item to a Node' anchor='publisher-publish'>
<section3 topic='Request' anchor='publisher-publish-request'>
<p>Any entity that is allowed to publish items to a node (i.e., a publisher or an owner) may do so at any time by sending an IQ-set to the service containing a pubsub element with a &lt;publish/&gt; child.</p>
<p>The syntax is as follows:</p>
<ul>
<li>The &lt;publish/&gt; element MUST possess a 'node' attribute, specifying the NodeID of the node.</li>
<li>Depending on the node configuration, the &lt;publish/&gt; element MAY contain no &ITEM; elements or one &ITEM; element. <note>The inclusion of more than one &ITEM; element is no longer allowed, given the removal of batch publishing from version 1.13 of this specification.</note> <note>It is not necessary for a publication request to include a payload or even an &ITEM; element in order to trigger an event notification. For example, the result of publishing to a transient, notification-only node will be an event notification that does not include even an &ITEM; element. However, for the sake of convenience we refer to the act of publication as "publishing an item" (rather than, say, "triggering an event notification") even though a publication request will not always contain an &ITEM; element.</note></li>
<li>The &lt;item/&gt; element provided by the publisher MAY possess an 'id' attribute, specifying a unique ItemID for the item. If an ItemID is not provided in the publish request, the pubsub service MUST generate one and MUST ensure that it is unique for that node.</li>
</ul>
<p>An example follows.</p>
<example caption='Publisher publishes an item with an ItemID'><![CDATA[
<iq type='set'
from='hamlet@denmark.lit/blogbot'
to='pubsub.shakespeare.lit'
id='publish1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='princely_musings'>
<item id='bnd81g37d61f49fgn581'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</publish>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Success Case' anchor='publisher-publish-success'>
<p>If the pubsub service can successfully process the request, it MUST inform the publisher of success. If the publish request did not include an ItemID, the IQ-result SHOULD include an empty &ITEM; element that specifies the ItemID of the published item.</p>
<example caption='Service replies with success'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/blogbot'
id='publish1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'/>
</publish>
</pubsub>
</iq>
]]></example>
<p>Note: If the publisher previously published an item with the same ItemID, successfully processing the request means that the service MUST overwrite the old item with the new item and then proceed as follows.</p>
<p>The pubsub service MUST then send one event notification to each entity that meets the criteria for receiving an event notification (typically to each approved subscriber, although there are other contexts in which an entity may receive an event notification as summarized under <link url='#impl-notify'>Notification Triggers</link>). Each &MESSAGE; stanza generated by a pubsub service SHOULD possess an 'id' attribute with a unique value so that the service can properly track any notification-related errors that may occur (see the <link url='#impl-bounce'>Handling Notification-Related Errors</link> section of this document). Depending on the node configuration, the event notification either will or will not contain the payload, as shown below.</p>
<p>Note: In order to facilitate authorization for item removal as described in the <link url='#publisher-delete'>Delete an Item from a Node</link> section of this document, implementations that support persistent items SHOULD store the item (if the node is so configured) and maintain a record of the publisher.</p>
<p>Note: If the service or node is configured so that there is a maximum number of items cached at the node and the maximum is reached when an item is published, the service MUST delete one of the existing items. It is RECOMMENDED for the service to follow the "first in, first out" rule and delete the oldest item. Depending on node configuration, deletion of an existing item MAY result in sending of a delete notification to the subscribers.</p>
<section4 topic='Notification With Payload' anchor='publisher-publish-success-withpayload'>
<p>If the node is configured to include payloads, the subscribers will receive payloads with the event notifications.</p>
<example caption='Subscribers receive event notifications with payloads'><![CDATA[
<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</items>
</event>
</message>
<message from='pubsub.shakespeare.lit' to='bernardo@denmark.lit' id='bar'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</items>
</event>
</message>
<message from='pubsub.shakespeare.lit' to='horatio@denmark.lit' id='baz'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</items>
</event>
</message>
<message from='pubsub.shakespeare.lit' to='bard@shakespeare.lit' id='fez'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</items>
</event>
</message>
]]></example>
</section4>
<section4 topic='Notification Without Payload' anchor='publisher-publish-success-withoutpayload'>
<p>If the node is configured to not include payloads, the subscribers will receive event notifications only. (If payloads are not included, subscribers may request the published item via the protocol defined in the <link url='#subscriber-retrieve'>Retrieve Items from a Node</link> section of this document.)</p>
<example caption='Subscribers receive event notifications only'><![CDATA[
<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'/>
</items>
</event>
</message>
<message from='pubsub.shakespeare.lit' to='bernardo@denmark.lit' id='bar'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'/>
</items>
</event>
</message>
<message from='pubsub.shakespeare.lit' to='horatio@denmark.lit' id='baz'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'/>
</items>
</event>
</message>
<message from='pubsub.shakespeare.lit' to='bard@shakespeare.lit' id='fez'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'/>
</items>
</event>
</message>
]]></example>
</section4>
<section4 topic='Item Publisher' anchor='publisher-publish-success-publisher'>
<p>If configured to do so, the service can include the publisher of the item when it generates event notifications.</p>
<example caption='Service Notifies Subscribers'><![CDATA[
<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'
publisher='hamlet@denmark.lit'>
[ ... ENTRY ... ]
</item>
</items>
</event>
</message>
]]></example>
<p>If so, the service MUST also include the publisher with every other form of item retrieval.</p>
<example caption='Service returns items'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='francisco@denmark.lit/barracks'
id='items1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'
publisher='hamlet@denmark.lit'>
[ ... ENTRY ... ]
</item>
[ ... MORE ITEMS ... ]
</items>
</pubsub>
</iq>
]]></example>
<p>The value of the 'publisher' attribute MUST be generated by the service, not accepted by the service in the published item, since allowing the publisher to assert its JID would open the possibility of spoofing.</p>
<p>The JID stamped by the service can be either (1) the full JID &LOCALFULL; of the publisher as taken the 'from' attribute of the IQ-set used to publish the item or (2) the bare JID &LOCALBARE; of the publisher as derived from a formal affiliation in the explicit list of whitelisted publishers.</p>
</section4>
<section4 topic='Inclusion of Subscription ID' anchor='publisher-publish-success-subid'>
<p>If a single entity is subscribed to a node multiple times, the service SHOULD notate the event notification so that the entity can determine which subscription identifier(s) generated this event. If these notations are included, they MUST use the &xep0131; format and SHOULD be included after the event notification information (i.e., as the last child of the &MESSAGE; stanza).</p>
<example caption='Subscriber receives notated event notification'><![CDATA[
<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'/>
</items>
</event>
<headers xmlns='http://jabber.org/protocol/shim'>
<header name='SubID'>123-abc</header>
<header name='SubID'>004-yyy</header>
</headers>
</message>
]]></example>
</section4>
</section3>
<section3 topic='Error Cases' anchor='publisher-publish-error'>
<p>There are several reasons why the publish request might fail:</p>
<ol>
<li>The requesting entity does not have sufficient privileges to publish.</li>
<li>The node does not support item publication.</li>
<li>The node does not exist.</li>
<li>The payload size exceeds a service-defined limit.</li>
<li>The item contains more than one payload element or the namespace of the root payload element does not match the configured namespace for the node.</li>
<li>The request does not match the node configuration.</li>
</ol>
<p>These error cases are described more fully in the following sections.</p>
<p>Note: If a publisher publishes an item with an Item ID and the ItemID matches that of an existing item, the pubsub service MUST NOT fail the publication but instead MUST overwrite the existing item and generate a new event notification (i.e., re-publication is equivalent to modification).</p>
<section4 topic='Insufficient Privileges' anchor='publisher-publish-error-forbidden'>
<p>If the requesting entity does not have sufficient privileges to publish, the service MUST return a &forbidden; error.</p>
<example caption='Entity does not have sufficient privileges to publish to node'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
id='publish1'>
<error type='auth'>
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Item Publication Not Supported' anchor='publisher-publish-error-notsupported'>
<p>If the node does not support item publication (e.g., because it is a collection node as described in <cite>XEP-0248</cite>), the service MUST return a &feature; error, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "publish".</p>
<example caption='Node does not support item publication'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='publish1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
feature='publish'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Node Does Not Exist' anchor='publisher-publish-error-node'>
<p>If the requesting entity attempts to publish an item to a node that does not exist and the service does not support the "auto-create" feature (see <link url='#publisher-publish-autocreate'>Automatic Node Creation</link>), the service MUST return an &notfound; error.</p>
<example caption='Entity attempts to publish to a non-existent node'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='publish1'>
<error type='cancel'>
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Payload Too Big' anchor='publisher-publish-error-bigpayload'>
<p>If the payload size exceeds a service-defined limit, the service MUST return a &notacceptable; error, which SHOULD also include a pubsub-specific error condition of &lt;payload-too-big/&gt;.</p>
<example caption='Entity attempts to publish very large payload'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='publish1'>
<error type='modify'>
<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<payload-too-big xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Bad Payload' anchor='publisher-publish-error-badpayload'>
<p>If the &ITEM; element contains more than one payload element or the namespace of the root payload element does not match the configured namespace for the node, the service MUST bounce the request with a &badrequest; error, which SHOULD also include a pubsub-specific error condition of &lt;invalid-payload/&gt;.</p>
<example caption='Entity attempts to publish item with multiple payload elements or namespace does not match'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='publish1'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<invalid-payload xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Request Does Not Match Configuration' anchor='publisher-publish-error-badrequest'>
<p>If the request does not conform to the configured <link url='#events'>event type</link> for the node, the service MAY bounce the request with a &badrequest; error, which SHOULD also include a pubsub-specific error condition. The following rules apply:</p>
<ul>
<li>If the event type is persistent (either event notification or payload) and the publisher does not specify an ItemID, the service MUST generate the ItemID and MUST NOT bounce the publication request.</li>
<li>If the event type is persistent (either event notification or payload) and the publisher does not include an item, the service MUST bounce the publication request with a &badrequest; error and a pubsub-specific error condition of &lt;item-required/&gt;.</li>
<li>If the event type is payload (either persistent or transient) and the publisher does not include a payload, the service SHOULD bounce the publication request with a &badrequest; error and a pubsub-specific error condition of &lt;payload-required/&gt;.</li>
<li>If the event type is notification + transient and the publisher provides an item, the service MUST bounce the publication request with a &badrequest; error and a pubsub-specific error condition of &lt;item-forbidden/&gt;.</li>
</ul>
<p>Examples of these errors are shown below.</p>
<example caption='Publisher attempts to publish to persistent node with no item'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='publish1'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<item-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
<example caption='Publisher attempts to publish to payload node with no payload'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='publish1'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<payload-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
<example caption='Publisher attempts to publish to transient notification node with item'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='publish1'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<item-forbidden xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
</section3>
<section3 topic='Automatic Node Creation' anchor='publisher-publish-autocreate'>
<p>A pubsub service MAY automatically create a node when it receives a publish request sent to a node that does not exist (instead of returning an &notfound; error). When doing so, the service SHOULD apply the default node configuration. If a service supports this functionality, it MUST advertise that fact by including a feature of "http://jabber.org/protocol/pubsub#auto-create" in its disco#info responses.</p>
</section3>
<section3 topic='Publishing Options' anchor='publisher-publish-options'>
<p>A pubsub service MAY support the ability to specify options along with a publish request (if so, it MUST advertise support for the "http://jabber.org/protocol/pubsub#publish-options" feature). Here is an example:</p>
<example caption='Publishing with options'><![CDATA[
<iq type='set'
from='hamlet@denmark.lit/blogbot'
to='pubsub.shakespeare.lit'
id='pub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'>
<entry xmlns='http://www.w3.org/2005/Atom'>
<title>Soliloquy</title>
<summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
</summary>
<link rel='alternate' type='text/html'
href='http://denmark.lit/2003/12/13/atom03'/>
<id>tag:denmark.lit,2003:entry-32397</id>
<published>2003-12-13T18:30:02Z</published>
<updated>2003-12-13T18:30:02Z</updated>
</entry>
</item>
</publish>
<publish-options>
<x xmlns='jabber:x:data' type='submit'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#publish-options</value>
</field>
<field var='pubsub#access_model'>
<value>presence</value>
</field>
</x>
</publish-options>
</pubsub>
</iq>
]]></example>
<p>The &lt;publish-options/&gt; element MUST contain a data form (see <cite>XEP-0004</cite>), whose FORM_TYPE MUST be "http://jabber.org/protocol/pubsub#publish-options" (see <cite>XEP-0068</cite>).</p>
<p>Each form field denotes a precondition to publishing the request. A pub-sub service advertising support for publishing options MUST check each precondition field against the node configuration of the same name, and it MUST reject the publication upon encountering unknown fields.</p>
<p>Preconditions MUST be processed as follows:</p>
<ol>
<li>If the node exists and the precondition is not met, then the publish MUST fail with a &conflict; error condition and a pubsub-specific condition of &lt;precondition-not-met/&gt;.</li>
<li>If the node exists and the precondition is met, then the publish succeeds.</li>
<li>If the node does not exist and the service supports the "auto-create" feature, then the service shall auto-create the node with default configuration in all respects except those specified in the preconditions, and the publish succeeds.</li>
<li>If the node does not exist and the service does not support the "auto-create" feature, then the publish shall fail.</li>
</ol>
</section3>
</section2>
<section2 topic='Delete an Item from a Node' anchor='publisher-delete'>
<p>A publisher might want to delete an item once it has been published to a node that supports persistent items. Support for this feature ("delete-items") is RECOMMENDED.</p>
<section3 topic='Request' anchor='publisher-delete-request'>
<p>To delete an item, the publisher sends a retract request as shown in the following examples. The &lt;retract/&gt; element MUST possess a 'node' attribute, MAY possess a 'notify' attribute, and MUST contain one &ITEM; element; the &ITEM; element MUST be empty and MUST possess an 'id' attribute.</p>
<example caption='Entity deletes an item from a node'><![CDATA[
<iq type='set'
from='hamlet@denmark.lit/elsinore'
to='pubsub.shakespeare.lit'
id='retract1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<retract node='princely_musings'>
<item id='ae890ac52d0df67ed7cfdf51b644e901'/>
</retract>
</pubsub>
</iq>
]]></example>
</section3>
<section3 topic='Success Case' anchor='publisher-delete-success'>
<p>If no error occurs, the service MUST delete the item.</p>
<example caption='Service replies with success'><![CDATA[
<iq type='result'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='retract1'/>
]]></example>
<section4 topic='Delete And Notify' anchor='publisher-delete-success-notify'>
<p>If no error occurs and the &lt;retract/&gt; element included a 'notify' attribute with a value of "true" or "1" &BOOLEANNOTE;, then the service MUST delete the item and MUST notify all subscribers as shown below. The syntax is identical to event notifications except that instead of an &ITEM; element, the &ITEMS; element includes a &lt;retract/&gt; element.</p>
<example caption='Subscribers are notified of deletion'><![CDATA[
<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<retract id='ae890ac52d0df67ed7cfdf51b644e901'/>
</items>
</event>
</message>
<message from='pubsub.shakespeare.lit' to='bernardo@denmark.lit' id='bar'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<retract id='ae890ac52d0df67ed7cfdf51b644e901'/>
</items>
</event>
</message>
]]></example>
</section4>
<section4 topic='Inclusion of Subscription ID' anchor='publisher-delete-success-subid'>
<p>If a single entity is subscribed to the node multiple times, the service SHOULD notate the item deletion so that the entity can determine which subscription identifier(s) generated this event. As above, if these notations are included, they MUST use the <cite>Stanza Headers and Internet Metadata (SHIM)</cite> protocol and SHOULD be included after the notification data (i.e., as the last child of the &MESSAGE; stanza).</p>
<example caption='Subscriber receives notated event notification'><![CDATA[
<message from='pubsub.shakespeare.lit' to='bernardo@denmark.lit' id='bar'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='princely_musings'>
<retract id='ae890ac52d0df67ed7cfdf51b644e901'/>
</items>
</event>
<headers xmlns='http://jabber.org/protocol/shim'>
<header name='SubID'>123-abc</header>
<header name='SubID'>004-yyy</header>
</headers>
</message>
]]></example>
</section4>
</section3>
<section3 topic='Error Cases' anchor='publisher-delete-error'>
<p>There are several reasons why the item retraction request might fail:</p>
<ol>
<li>The publisher does not have sufficient privileges to delete the requested item.</li>
<li>The node or item does not exist.</li>
<li>The request does not specify a node.</li>
<li>The request does not include an &ITEM; element or the &ITEM; element does not specify an ItemID.</li>
<li>The node does not support persistent items.</li>
<li>The service does not support the deletion of items.</li>
</ol>
<p>These error cases are described more fully in the following sections.</p>
<section4 topic='Insufficient Privileges' anchor='publisher-delete-error-forbidden'>
<p>If the requesting entity does not have sufficient privileges to delete the item, the service MUST return a &forbidden; error.</p>
<example caption='Requesting entity does not have sufficient privileges'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='retract1'>
<error type='auth'>
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Node Does Not Exist' anchor='publisher-delete-error-node'>
<p>If the node or item does not exist, the service MUST return an &notfound; error.</p>
<example caption='Non-existent node or item'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='retract1'>
<error type='cancel'>
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='NodeID Required' anchor='publisher-delete-error-nodeid'>
<p>If the request does not specify a node, the service MUST return a &badrequest; error, which SHOULD also include a pubsub-specific error condition of &lt;nodeid-required/&gt;.</p>
<example caption='Request does not specify a node'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='retract1'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<nodeid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Item or ItemID Required' anchor='publisher-delete-error-itemid'>
<p>If the request does not include an &ITEM; element or the &ITEM; element does not specify an ItemID, the service MUST return a &badrequest; error, which SHOULD also include a pubsub-specific error condition of &lt;item-required/&gt;.</p>
<example caption='Request does not specify an item'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='retract1'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<item-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Persistent Items Not Supported' anchor='publisher-delete-error-persistent'>
<p>If the node does not support persistent items (e.g., because it is a collection node or a transient node that does not deliver payloads), the service MUST return a &feature; error, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "persistent-items".</p>
<example caption='Node does not support persistent items'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'
id='retract1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
feature='persistent-items'/>
</error>
</iq>
]]></example>
</section4>
<section4 topic='Item Deletion Not Supported' anchor='publisher-delete-error-notsupported'>
<p>If the service does not support item deletion, it MUST return a &feature; error, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "delete-items".</p>
<example caption='Service does not support item deletion'><![CDATA[
<iq type='error'
from='pubsub.shakespeare.lit'
to='hamlet@denmark.lit/elsinore'