JEP-0060: Publish-Subscribe

This document defines a publish-subscribe protocol for use on Jabber/XMPP networks.


NOTICE: The protocol defined herein is a Draft Standard of the Jabber Software Foundation. Implementations are encouraged and the protocol is appropriate for deployment in production systems, but some changes to the protocol are possible before it becomes a Final Standard.


JEP Information

Status: Draft
Type: Standards Track
Number: 0060
Version: 1.8
Last Updated: 2006-06-27
JIG: Standards JIG
Approving Body: Jabber Council
Dependencies: XMPP Core, JEP-0004, JEP-0030, JEP-0068, JEP-0082, JEP-0131
Supersedes: None
Superseded By: None
Short Name: pubsub
XML Schema for pubsub namespace: <http://jabber.org/protocol/pubsub/pubsub.xsd>
XML Schema for pubsub#errors namespace: <http://jabber.org/protocol/pubsub/errors.xsd>
XML Schema for pubsub#event namespace: <http://jabber.org/protocol/pubsub/event.xsd>
XML Schema for pubsub#owner namespace: <http://jabber.org/protocol/pubsub/owner.xsd>
Wiki Page: <http://wiki.jabber.org/index.php/Publish-Subscribe (JEP-0060)>

Author Information

Peter Millard

See Author Note

Peter Saint-Andre

Email: stpeter@jabber.org
JID: stpeter@jabber.org

Ralph Meijer

Email: ralphm@ik.nu
JID: ralphm@ik.nu

Legal Notice

This Jabber Enhancement Proposal is copyright 1999 - 2006 by the Jabber Software Foundation (JSF) and is in full conformance with the JSF's Intellectual Property Rights Policy <http://www.jabber.org/jsf/ipr-policy.shtml>. This material may be distributed only subject to the terms and conditions set forth in the Creative Commons Attribution License (<http://creativecommons.org/licenses/by/2.5/>).

Discussion Venue

The preferred venue for discussion of this document is the Standards-JIG discussion list: <http://mail.jabber.org/mailman/listinfo/standards-jig>.

Relation to XMPP

The Extensible Messaging and Presence Protocol (XMPP) is defined in the XMPP Core (RFC 3920) and XMPP IM (RFC 3921) specifications contributed by the Jabber Software Foundation to the Internet Standards Process, which is managed by the Internet Engineering Task Force in accordance with RFC 2026. Any protocol defined in this JEP has been developed outside the Internet Standards Process and is to be understood as an extension to XMPP rather than as an evolution, development, or modification of XMPP itself.

Conformance Terms

The following keywords as used in this document are to be interpreted as described in RFC 2119: "MUST", "SHALL", "REQUIRED"; "MUST NOT", "SHALL NOT"; "SHOULD", "RECOMMENDED"; "SHOULD NOT", "NOT RECOMMENDED"; "MAY", "OPTIONAL".


Table of Contents

1. Introduction
1.1. Overview
1.2. Motivating Example
2. Glossary
3. Requirements
4. Preliminaries
4.1. Affiliations
4.2. Subscription States
4.3. Event Types
4.4. Node Types
4.5. Node Access Models
4.6. Addressing
4.6.1. JID
4.6.2. JID+NodeID
5. Entity Use Cases
5.1. Discover Features
5.2. Discover Nodes
5.3. Discover Node Information
5.4. Discover Node Meta-Data
5.5. Discover Items for a Node
5.6. Retrieve Subscriptions
5.7. Retrieve Affiliations
6. Subscriber Use Cases
6.1. Subscribe to a Node
6.2. Unsubscribe from a Node
6.3. Configure Subscription Options
6.4. Retrieve Items from a Node
7. Publisher Use Cases
7.1. Publish an Item to a Node
7.2. Delete an Item from a Node
8. Owner Use Cases
8.1. Create a Node
8.1.1. General Considerations
8.1.2. Create a Node With Default Configuration
8.1.3. Create and Configure a Node
8.2. Configure a Node
8.3. Request Default Configuration Options
8.4. Delete a Node
8.5. Purge All Node Items
8.6. Manage Subscription Requests
8.6.1. Request All Pending Subscription Requests
8.7. Manage Subscriptions
8.8. Manage Affiliations
9. Collection Nodes
9.1. Subscribe to a Collection Node
9.2. Root Collection Node
9.3. Create a New Collection Node
9.4. Create a Node Associated with a Collection
9.5. Associate an Existing Node with a Collection
9.6. Disassociate a Node from a Collection
9.7. Generating Publish Notifications for Collections
10. Feature Summary
11. Error Conditions
12. Implementation Notes
12.1. Intended Recipients for Notifications
12.2. Handling Notification-Related Errors
12.3. Presence-Based Delivery of Events
12.4. Not Routing Events to Offline Storage
12.5. Including a Message Body
12.6. Node ID and Item ID Uniqueness
12.7. Item Caching
12.8. Batch Processing
12.9. Auto-Subscribing Owners and Publishers
12.10. Authorizing Subscription Requests (Pending Subscribers)
12.11. Notification of Subscription State Changes
12.12. NodeID Semantics
12.13. Multiple Node Discovery
12.14. Inclusion of SHIM Headers
12.15. Associating Events and Payloads with the Generating Entity
12.16. Chaining
12.17. Time-Based Subscriptions (Leases)
12.18. Content-Based Pubsub Systems
13. Internationalization Considerations
13.1. Field Labels
14. Security Considerations
15. IANA Considerations
16. Jabber Registrar Considerations
16.1. Protocol Namespaces
16.2. Service Discovery Category/Type
16.3. Service Discovery Features
16.4. Field Standardization
16.4.1. pubsub#subscribe_authorization FORM_TYPE
16.4.2. pubsub#subscribe_options FORM_TYPE
16.4.3. pubsub#node_config FORM_TYPE
16.4.4. pubsub#meta-data FORM_TYPE
16.5. SHIM Headers
16.6. URI Query Types
17. XML Schemas
17.1. http://jabber.org/protocol/pubsub
17.2. http://jabber.org/protocol/pubsub#errors
17.3. http://jabber.org/protocol/pubsub#event
17.4. http://jabber.org/protocol/pubsub#owner
18. Acknowledgements
19. Author Note
Notes
Revision History


1. Introduction

1.1 Overview

As Jabber/XMPP technologies have matured, the need for a generic publish-subscribe ("pubsub") mechanism has arisen in a number of problem spaces. These include (but are not limited to): news feeds and content syndication, extended presence, avatar management, shared bookmarks, auction and trading systems, online catalogs, workflow systems, network management systems, NNTP gateways, profile management, and event notification.

In all of these domains, it is desirable for data communication to follow the classic "publish-subscribe" or "observer" design pattern: a person or application publishes information, and an event notification or the data itself 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 and/or the data itself to subscribers, and enables privileged entities to manage lists of people or applications that are authorized to publish or subscribe. In most pubsub services, the focal point for publication and subscription is a "topic" or "node" to which publishers send data and from which subscribers receive notifications and/or data. Additionally, some nodes may also maintain a history of events and provide other services that supplement the pure pubsub model.

This document defines a single, cohesive, generic protocol which all forms of pubsub can utilize. While compliant implementations are not required to implement all of the features defined herein, this document addresses most usages that may be requested of a pubsub service. Other specifications may define subsets of publish-subscribe for use in specialized contexts, but such profiles are out of scope for this document.

1.2 Motivating Example

In order to motivate the discussion, we provide a simple, introductory example of a pubsub protocol flow.

Perhaps the most popular application of pubsub-like functionality is content syndication, which has become familiar from the RSS and Atom (RFC 4287 [1]) feeds associated with weblogs, news sites, and other frequently-updated information available on the Internet. Consider the example of a weblog published by one of the Shakespearean characters typical of Jabber/XMPP protocol documentation. When this character authors a new weblog entry, his blogging software publishes the entry to a pubsub node hosted at a pubsub service:

Example 1. Publisher Publishes a New Weblog Entry

<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>
  </pubsub>
</iq>
    

Example 2. Service Notifies Subscribers

<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='marcellus@denmark.lit' id='fez'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        ... ENTRY ...
      </item>
    </items>
  </event>
</message>

.
.
.
    

Naturally, many other protocol flows may be required in order to enable publication of items to a node (e.g., the publisher first needs to create the node and subscribers need to sign up for notifications). These protocol flows are fully described in the remainder of this document.

An even simpler example is that of a transient node that sends only notifications, which is the pure pubsub model:

Example 3. A Transient Notification

<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='elsinore/doorbell'/>
  </event>
</message>
    

2. Glossary

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.)

Table 1: Publish-Subscribe Terms

Authorize Access Model 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.
Address (1) A JID as defined in XMPP Core [2], or (2) the combination of a JID and a Service Discovery [3] node.
Collection Node A type of node that contains nodes and/or other collections but no published items. Collections make it possible to represent hierarchial node structures.
Entity A JID-addressable Jabber entity (client, service, application, etc.).
Event A change in the state of a node.
Instant Node A node whose NodeID is automatically generated by a pubsub service.
Item An XML fragment which is published to a node, thereby generating an event.
ItemID A unique identifier for an item in the context of a specific node.
Leaf Node A type of node that contains published items only. It is NOT a container for other nodes.
Node 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").
NodeID 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, but such meaning is OPTIONAL.
Notification A message sent to a subscriber informing them of an event.
Outcast An entity that is disallowed from subscribing or publishing to a node.
Owner The manager of a node, of which there may be more than one; often but not necessarily the node creator.
Payload The full data associated with an event rather than just the event notification itself.
Open Access Model A node access model under which any entity may subscribe and retrieve items without approval.
Personal Eventing 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 Personal Eventing via Pubsub [4].
Presence Access Model 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 RFC 3921 [5]) may subscribe to the node and retrieve items from the node; this access model applies mainly to instant messaging systems.
Publisher An entity that is allowed to publish items to a node.
Pubsub Service An XMPP server or component that adheres to the protocol defined herein.
Roster Access Model 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.
Subscriber An entity that is subscribed to a node.
Whitelist Access Model A node access model under which an entity can subscribe only through being added by a node owner (subscription requests are rejected) and only subscribers may retrieve items.

3. Requirements

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 Jabber MUST provide the basic features which implement a pure publish-subscribe pattern:

Some of the possible uses of a Jabber-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:

4. Preliminaries

4.1 Affiliations

To manage permissions, the protocol defined herein uses a hierarchy of affiliations, similiar to those introduced in Multi-User Chat [6].

Support for the "owner" and "none" affiliations is REQUIRED. Support for all other affiliations is RECOMMENDED. Particular kinds of pubsub services MAY enforce additional requirements.

Table 2: Affiliations and their Privileges

Affiliation Subscribe Publish Items Purge Items Configure Node Delete Node Delete Item
Owner Yes Yes Yes Yes Yes Yes
Publisher Yes Yes No No No Yes/No *
None Yes No No No No No
Outcast No No No No No No

* Note: A service MAY allow any publisher to delete any item once it has been published to that node instead of allowing only the original publisher to remove it (this is disoverable via the "pubsub#delete-any" feature).

The ways in which an entity changes its affiliation with a node are well-defined. Typically, an owner action is required to make an affiliation state transition. Affiliation changes and their triggering actions are specified in the following table.

Table 3: Affiliation State Chart

--> Outcast None Publisher Owner
Outcast -- Owner removes ban Owner adds entity to publisher list Owner adds entity to owner list
None Owner bans entity -- Owner adds entity to publisher list Owner adds entity to owner list
Publisher Owner bans entity Owner removes entity from publisher list -- Owner adds entity to owner list
Owner n/a Owner resigns n/a --

4.2 Subscription States

Subscriptions to a node may exist in several states.

Table 4: Subscription States

Subscription State Description
None The node MUST NOT send event notifications or payloads to the Entity.
Pending 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.
Unconfigured 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.
Subscribed 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.

4.3 Event Types

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 notification vs. inclusion of payload. An implementation SHOULD enable an owner to configure a node along both of these dimensions.

No matter whether a node is configured for persistent or transient events, a service MAY cache the last item published to the node and send that item to new subscribers (see the Item Caching section of this document).

A pubsub service MUST validate publish requests against the configuration of the node along both of these dimensions (see the Publish An Item to a Node section of this document for the relevant error conditions).

Whether an item must be provided by the publisher, and whether an item ID is provided by the publisher or generated by the pubsub service, depends on the type of event being published. We can summarize the relevant rules as follows:

Table 5: Event Types, Items, and Item IDs

--> Notification Payload
Persistent Publisher MUST include an <item/> element, which MAY be empty or contain a payload; if item ID is not provided by publisher, it MUST be generated by pubsub service Publisher MUST include an <item/> element that contains the payload; if item ID is not provided by publisher, it MUST be generated by pubsub service
Transient Publisher MUST NOT include an <item/> element (therefore item ID is neither provided nor generated) but the notification will include an empty <items/> element Publisher MUST include an <item/> element that contains the payload, but the item ID is OPTIONAL

4.4 Node Types

There are two types of nodes:

Table 6: Node Types

Node Type Description
Leaf A node that contains published items only. It is NOT a container for other nodes. This is the most common node type.
Collection A node that contains nodes and/or other collections but no published items. Collections make it possible to represent hierarchial node structures.

4.5 Node Access Models

In order to make node creation simpler for clients, we define the following node access models (in order of openness):

Table 7: Node Access Models

Access Model Description
Open 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.
Presence 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 RFC 3921).
Roster 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 RFC 3921).
Authorize The node owner must approve all subscription requests, and only subscribers may retrieve items from the node.
Whitelist An entity may be subscribed only through being added to a whitelist by the node owner (unsolicited subscription requests are rejected), and only subscribers may retrieve items from the node. In effect, the default affiliation is outcast. 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 Manage Affiliated Entities section of this document.

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).

In order for a node creator or owner to specify the access model (see the Create a Node With Default Configuration and Configure a Node sections of this document), the 'pubsub#access_model' configuration field is used.

4.6 Addressing

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. [7]

4.6.1 JID

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). 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 RFC 3920.

Consider the following example, in which the pubsub service is located at the hostname pubsub.shakespeare.lit.

Example 4. Node addressed as domain.tld/NodeID

<iq to='pubsub.shakespeare.lit/news announcements'>
  ...
</iq>
      

Now consider the following example, in which the pubsub service is located at pubsub@shakespeare.lit.

Example 5. Node addressed as user@domain.tld/NodeID

<iq to='pubsub@shakespeare.lit/news announcements'>
  ...
</iq>
      

4.6.2 JID+NodeID

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 RFC 3920.

Consider the following example, in which the (virtual) pubsub service is located at hamlet@denmark.lit.

Example 6. Node addressed as JID+NodeID

<iq to='hamlet@denmark.lit'>
  <query node='princely_musings'/>
</iq>
      

5. Entity Use Cases

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.

5.1 Discover Features

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.

Example 7. Entity Queries Pubsub Service Regarding Supported Features

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='feature1'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
    

Example 8. Pubsub Service Returns Set of Supported Features

<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>
    

The possible pubsub features are noted throughout this document and have been registered as described in the Jabber Registrar Considerations section of this document. For information regarding which features are required, recommended, and optional, see the Feature Summary section of this document.

5.2 Discover Nodes

If a service implements a hierarchy of nodes (by means of Collection Nodes), it MUST also enable entities to discover the nodes in that hierarchy by means of the Service Discovery protocol, subject to the recommendations in JEP-0030 regarding large result sets (for which Jabber Search [8] 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.

Note: Node hierarchies and collection nodes are OPTIONAL. For details, refer to the NodeID Semantics and Collection Nodes sections of this document.

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 Collection Node:

Example 9. Entity requests all first-level nodes

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='nodes1'>
  <query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
    

Example 10. Service returns all first-level nodes

<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>
    

In the second example, an entity sends a disco#items request to one of the first-level nodes, which is also a collection node:

Example 11. Entity requests second-level nodes

<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 12. Service returns second-level nodes

<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>
    

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 Discover Items for a Node section of this document, however such items MUST NOT include a 'node' attribute (since they are published items, not nodes).

5.3 Discover Node Information

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".

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).

Example 13. Entity queries collection node for information

<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 14. Service responds with identity of pubsub/collection

<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 15. Entity queries leaf node for information

<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 16. Service responds with identity of pubsub/collection

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='info1'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    ...
    <identity category='pubsub' type='leaf'/>
    ...
  </query>
</iq>
    

5.4 Discover Node Meta-Data

The "disco#info" result MAY include detailed meta-data about the node, encapsulated in the Data Forms [9] format as described in Service Discovery Extensions [10], where the data form context is specified by including a FORM_TYPE of "http://jabber.org/protocol/pubsub#meta-data" in accordance with Field Standardization for Data Forms [11]. If meta-data 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.

Example 17. Entity queries a node for information

<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 18. Service responds with information and meta-data

<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#meta-data</value>
      </field>
      <field var='pubsub#type' label='Payload type'>
        <value>http://www.w3.org/2005/Atom</value>
      </field>
      <field var='pubsub#creator' label='Node creator'>
        <value>hamlet@denmark.lit</value>
      </field>
      <field var='pubsub#creation_date' label='Creation date'>
        <value>2003-07-29T22:56Z</value>
      </field>
      <field var='pubsub#title' label='A short name for the node'>
        <value>Princely Musings (Atom)</value>
      </field>
      <field var='pubsub#description' label='A description of the node'>
        <value>Updates for Hamlet&apos;s Princely Musings weblog.</value>
      </field>
      <field var='pubsub#language' label='Default language'>
        <value>en</value>
      </field>
      <field var='pubsub#contact' label='People to contact with questions'>
        <value>bard@shakespeare.lit</value>
      </field>
      <field var='pubsub#owner' label='Node owners'>
        <value>hamlet@denmark.lit</value>
      </field>
      <field var='pubsub#publisher' label='Publishers to this node'>
        <value>hamlet@denmark.lit</value>
      </field>
      <field var='pubsub#num_subscribers' label='Number of subscribers to this node'>
        <value>1066</value>
      </field>
    </x>
  </query>
</iq>
    

Note: Node meta-data 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 meta-data SHOULD be provided as fields in the node configuration form.

Much of the meta-data provided about a node maps directly to selected Dublin Core Metadata Initiative (DCMI) [12] meta-data attributes; specifically:

Table 8: Dublin Core Meta-Data Mapping

Pubsub Field Dublin Core Meta-Data Attribute
pubsub#creation_date Date [13]
pubsub#creator Creator
pubsub#description Description
pubsub#language Language
pubsub#publisher Publisher
pubsub#title Title
pubsub#type Type [14]

5.5 Discover Items for a Node

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 Retrieve Items from a Node section of this document.

Example 19. Entity requests all of the items for a node

<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>
    

5.6 Retrieve Subscriptions

A service SHOULD allow an entity to query the service to retrieve its subscriptions for all nodes at the service. In order to make the request, the requesting entity MUST send an IQ-get whose <pubsub/> child contains an empty <subscriptions/> element with no attributes.

Example 20. Entity requests all current subscriptions

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='subscriptions1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscriptions/>
  </pubsub>
</iq>
    

If the service returns a list of subscriptions, it MUST return all subscriptions for all JIDs that match the bare JID (<node@domain.tld>) portion of the 'from' attribute on the request.

For each subscription, a <subscription/> 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.

Example 21. Service returns all current subscriptions

<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='pending'/>
    </subscriptions>
  </pubsub>
</iq>
    

There are several reasons why the subscriptions retrieval request might fail:

  1. The requesting entity has no subscriptions.
  2. Subscriptions retrieval is not supported.

These error cases are described more fully below.

If the requesting entity has no subscriptions, the pubsub service MUST return an <item-not-found/> error.

Example 22. No subscriptions

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='subscriptions1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscriptions/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the service does not support subscriptions retrieval, the service MUST respond with a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "retrieve-subscriptions".

Example 23. Subscriptions retrieval not supported

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='subscriptions1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscriptions/>
  </pubsub>
  <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>
    

5.7 Retrieve Affiliations

A service SHOULD allow an entity to query the service to retrieve its affiliations for all nodes at the service. In order to make the request, the requesting entity includes an empty <affiliations/> element with no attributes.

Example 24. Entity requests all current affiliations

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='affil1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <affiliations/>
  </pubsub>
</iq>
    

If the service returns a list of affiliations, it MUST return all affiliations for all JIDs that match the bare JID (<node@domain.tld>) portion of the 'from' attribute on the request.

For each affiliation, an <affiliation/> element is returned containing the NodeID and the affiliation state (owner, publisher, or outcast).

Example 25. Service replies with all current affiliations

<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>
    

There are several reasons why the affiliations retrieval request might fail:

  1. The requesting entity has no affiliations.
  2. Affiliations retrieval is not supported.

These error cases are described more fully below.

If the requesting entity has no affiliations, the pubsub service MUST return an <item-not-found/> error.

Example 26. No affiliations

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='affil1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <affiliations/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the service does not support affiliations retrieval, the service MUST respond with a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "retrieve-affiliations".

Example 27. Affiliations retrieval not supported

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='affil1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <affiliations/>
  </pubsub>
  <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>
    

6. Subscriber Use Cases

This section defines the use cases for and protocols to be used by potential and actual subscribers. (Note: The Implementation Notes 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.)

6.1 Subscribe to a Node

When a Jabber 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 <pubsub/> element contains one and only one <subscribe/> element. The <subscribe/> element MUST possess a 'node' attribute specifying the node to which the entity wishes to subscribe. The <subscribe/> element MUST also possess a 'jid' attribute specifying the exact XMPP address to be used as the subscribed JID -- often a bare JID (<node@domain.tld>) or full JID (<node@domain.tld/resource>), although JIDs of the form <domain.tld> or <domain.tld/resource> may subscribe as well.

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. However, some implementations 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).

A service MAY allow entities to subscribe multiple times to the same node. This enables an entity to subscribe using different subscription options. 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 entity 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).

Here is an example of a subscription request.

Example 28. Entity subscribes to a node

<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>
    

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).

Example 29. Service replies with success

<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>
    

The service MAY also send the last published item to the new subscriber. The message containing this item SHOULD be stamped with extended information qualified by the 'jabber:x:delay' namespace (see Delayed Delivery [15]) to indicate it is are sent with delayed delivery. (Note that in this example the message notification is sent to the bare JID since that is the subscribed JID.)

Example 30. Service sends last published item

<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>
  <x xmlns='jabber:x:delay' stamp='20031213T23:58:37'/>
</message>
    

There are several reasons why the subscription request might fail:

  1. The bare JID portions of the JIDs do not match.
  2. The node has an access model of "presence" and the requesting entity is not subscribed to the owner's presence.
  3. The node has an access model of "roster" and the requesting entity is not in one of the authorized roster groups.
  4. The node has an access model of "whitelist" and the requesting entity is not on the whitelist.
  5. The service requires payment for subscriptions to the node.
  6. The requesting entity is anonymous and the service does not allow anonymous entities to subscribe.
  7. The requesting entity has a pending subscription.
  8. The requesting entity is blocked from subscribing (e.g., because having an affiliation of outcast).
  9. The node does not support subscriptions.
  10. The node does not exist.

These error cases are described more fully below.

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 <bad-request/> error, which SHOULD also include a pubsub-specific error condition of <invalid-jid/>.

Example 31. JIDs do not match

<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='bernardo@denmark.lit'/>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-jid xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

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 <not-authorized/> error, which SHOULD also include a pubsub-specific error condition of <presence-subscription-required/>.

Example 32. Entity is not authorized to create a subscription (presence subscription required)

<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'/>
  </pubsub>
  <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>
    

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 <not-authorized/> error, which SHOULD also include a pubsub-specific error condition of <not-in-roster-group/>.

Example 33. Entity is not authorized to create a subscription (not in roster group)

<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'/>
  </pubsub>
  <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>
    

For nodes with a node access model of "whitelist", if the requesting entity is not on the whitelist then the service MUST return a <not-allowed/> error, which SHOULD include a pubsub-specific error condition of <closed-node/>.

Example 34. Node has whitelist access model

<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'/>
  </pubsub>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <closed-node xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

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-required/> error to the subscriber.

Example 35. Payment is required for a subscription

<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'/>
  </pubsub>
  <error type='auth'>
    <payment-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

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.

Example 36. Requesting entity is anonymous

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='anonymous@denmark.lit/foo'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='anonymous@denmark.lit'/>
  </pubsub>
  <error type='cancel'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the requesting entity has a pending subscription, the service MUST return a <not-authorized/> error to the subscriber, which SHOULD include a pubsub-specific error condition of <not-subscribed/>.

Example 37. Requesting entity has pending subscription

<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'/>
  </pubsub>
  <error type='auth'>
    <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <pending-subscription xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

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.

Example 38. Requesting entity is blocked

<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'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the node does not allow entities to subscribe, the service SHOULD return a <feature-not-implemented/> error to the subscriber, specifying a pubsub-specific error condition of <unsupported/> and a feature of "subscribe".

Example 39. Subscribing not supported

<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'/>
  </pubsub>
  <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>
    

If the node does not exist, the service SHOULD return an <item-not-found/> error to the subscriber.

Example 40. Node does not exist

<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'/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

For nodes with an access model of "authorize", subscription requests MUST be approved by one of the node owners; therefore the pubsub service sends a message to the node owner(s) requesting authorization (see the Manage Subscription Requests section of this document). Because the subscription request may or may not be approved, the service MUST return a pending notification to the subscriber.

Example 41. Service replies with pending

<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>
    

If the entity must configure its subscription options (see the Configure Subscription Options section of this document) before receiving 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.

Example 42. Service replies with success and indicates that subscription configuration is required

<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>
    

Note: The node shall include the <required/> child element only if the subscriber must configure the subscription before receiving any 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).

Alternatively, if the service is unable to create the subscription without simultaneous configuration, the service MAY return a <not-acceptable/> error, which SHOULD include a pubsub-specific error condition of <configuration-required/>.

Example 43. Service returns error specifying that subscription configuration is required

<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>
    

If the <required/> 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 <subscribe-options/> element in the IQ-result, as shown in the following example).

Example 44. Service replies with success and indicates that subscription options are supported but not required

<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>
    

6.2 Unsubscribe from a Node

To unsubscribe from a node, the subscriber sends an IQ-set whose <pubsub/> child contains an <unsubscribe/> element that specifies the node and the subscribed JID.

Example 45. Entity unsubscribes from a node

<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>
    

If the request can be successfully processed, the service MUST return an IQ result.

Example 46. Service replies with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'/>
    

There are several reasons why the unsubscribe request might fail:

  1. The requesting entity has multiple subscriptions to the node but does not specify a subscription ID.
  2. The request does not specify an existing subscriber.
  3. The requesting entity does not have sufficient privileges to unsubscribe the specified JID.
  4. The node does not exist.
  5. The request specifies a subscription ID that is not valid or current.

These error cases are described more fully below.

If the requesting entity has multiple subscriptions to the node but does not specify a subscription ID, the service MUST return a <bad-request/> error, which SHOULD also include a pubsub-specific error condition of <subid-required/>.

Example 47. Entity did not specify SubID

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe node='princely_musings' jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <subid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

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-request/> and which SHOULD also include a pubsub-specific error condition of <not-subscribed/>.

Example 48. Requesting entity is not a subscriber

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe node='princely_musings' jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='cancel'>
    <unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <not-subscribed xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

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 <node@domain.tld/resource>, a service MUST perform this check by comparing the <node@domain.tld> 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.

Example 49. Requesting entity is prohibited from unsubscribing entity

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe
         node='princely_musings'
         jid='bard@shakespeare.lit'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the node does not exist, the pubsub service MUST return an <item-not-found/> error.

Example 50. Node does not exist

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe
         node='princely_musings'
         jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

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 <not-acceptable/> error, which SHOULD also include a pubsub-specific error condition of <invalid-subid/>.

Example 51. Invalid subscription identifier

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe
         node='princely_musings'
         subid='ba49252aaa4f5d320c24d3766f0bdcade78c78d3'
         jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='modify'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-subid xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

6.3 Configure Subscription Options

Implementations MAY allow subscribers to configure subscription options. Implementations SHOULD use the Data Forms protocol to accomplish this configuration (however, an out-of-band mechanism such as a web interface could be offered as well).

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".

Example 52. Pubsub service indicates support for subscription options

<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>
    

A subscriber requests the subscription options by including an <options/> element inside an IQ-get stanza.

Example 53. Subscriber requests subscription options form

<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>
    

If the request can be successfully processed, the service MUST respond with the options.

Example 54. Service responds with the options form

<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 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>
    

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 Data Forms protocol, it MUST use the field variables that are registered with the Jabber Registrar in association with the 'http://jabber.org/protocol/pubsub' namespace (a preliminary representation of those field variables is shown above and in the pubsub#subscribe_options FORM_TYPE section of this document, but MUST NOT be construed as canonical since the Jabber Registrar may standardize additional fields at a later date without changes to this document).

Note: Many of the relevant data form fields are of type "boolean" and MUST be handled accordingly. [16]

There are several reasons why the options request might fail:

  1. The requesting entity does not have sufficient privileges to modify subscription options for the specified JID.
  2. The requesting entity (or specified subscriber) is not subscribed.
  3. The request does not specify both the NodeID and the subscriber's JID.
  4. The request does not specify a subscription ID but one is required.
  5. The request specifies a subscription ID that is not valid or current.
  6. Subscription options are not supported.
  7. The node does not exist.

These error cases are described more fully below.

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, the service MUST assume that the requesting entity wishes to request subscription options for its subscription to the root collection node; see the Root Collection Node section of this document for details).

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 <node@domain.tld/resource>, a service MUST perform this check by comparing the <node@domain.tld> 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.

Example 55. Requesting entity does not have sufficient privileges to modify subscription options

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options node='princely_musings' jid='bernardo@denmark.lit'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the requesting entity (or specified subscriber, if different) is not subscribed, the service MUST return an <unexpected-request/> error, which SHOULD also include a pubsub-specific error condition of <not-subscribed/>.

Example 56. No such subscriber

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='options1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options/>
  </pubsub>
  <error type='modify'>
    <unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <not-subscribed xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

If the subscriber does not specify a JID, the service MUST return a <bad-request/> error, which SHOULD also include a pubsub-specific error condition of <jid-required/>.

Example 57. Subscriber JID not specified

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='options1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options/>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <jid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

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 <bad-request/> error, which SHOULD also include a pubsub-specific error condition of <subid-required/>.

Example 58. SubID required

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options node='princely_musings' jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <subid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

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 <not-acceptable/> error, which SHOULD also include a pubsub-specific error condition of <invalid-subid/>.

Example 59. Invalid subscription identifier

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe
         node='princely_musings'
         subid='991d7fd1616fd041015064133cd097a10030819e'
         jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='modify'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-subid xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

If the node or service does not support subscription options, the service MUST respond with a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "subscription-options".

Example 60. Subscription options not supported

<iq type='error'
    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'/>
  </pubsub>
  <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>
    

If the node does not exist, the pubsub service MUST return an <item-not-found/> error.

Example 61. Node does not exist

<iq type='error'
    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'/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

After receiving the configuration form, the requesting entity SHOULD submit the form in order to update the entity's subscription options for that node.

Example 62. Subscriber submits completed options form

<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>
    

If the service can successfully process the submission, it MUST respond with success.

Example 63. Service responds with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='options2'/>
    

If the subscriber attempts to set an invalid group of options, the service MUST respond with a <bad-request/> error.

Example 64. Service responds with Bad Request for invalid options

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='options2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options node='princely_musings' jid='francisco@denmark.lit'>
      <x xmlns='jabber:x:data'>
        <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'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-options xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

The other errors already mentioned for getting subscription options also apply to setting subscription options.

As noted, if a service supports subscription options, an entity MAY subscribe and provide the subscription options in the same stanza.

Note: The <options/> element MUST follow the <subscribe/> element and MUST NOT possess a 'node' attribute or 'jid' attribute, since the value of the <subscribe/> element's 'node' attribute specifies the desired NodeID and the value of the <subscribe/> element's 'jid' attribute specifies the subscriber's JID; if any of these rules are violated, the service MUST return a <bad-request/> error.

Example 65. Entity subscribes to node and sets configuration options

<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'>
        <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>
    

6.4 Retrieve Items from a Node

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). The service MUST conform to the node's access model in determining whether to return items to the entity that requests them. Specifically:

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 Security Considerations 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.)

The subscriber may request all items by specifying only the Node ID without restrictions.

Example 66. Subscriber requests all items

<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>
    

The service then SHOULD return all items published to the node, although it MAY truncate the result set if a large number of items has been published.

Example 67. Service returns all items

<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>
    

Even if the service or node does not support persistent items, it MAY return the last published item.

Example 68. Service returns last published item

<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>
    

There are several reasons why the items retrieval request might fail:

  1. The requesting entity has multiple subscriptions to the node but does not specify a subscription ID.
  2. The requesting entity is subscribed but specifies an invalid subscription ID.
  3. The node does not return items to unsubscribed entities and the requesting entity is not subscribed.
  4. The service or node does not support persistent items and does not return the last published item.
  5. The service or node does not support item retrieval.
  6. The node has an access model of "presence" and the requesting entity is not subscribed to the owner's presence.
  7. The node has an access model of "roster" and the requesting entity is not in one of the authorized roster groups.
  8. The node has an access model of "whitelist" and the requesting entity is not on the whitelist.
  9. The service or node requires payment for item retrieval.
  10. The requesting entity is blocked from retrieving items from the node (e.g., because having an affiliation of outcast).
  11. The node does not exist.

These error cases are described more fully below.

If the requesting entity has multiple subscriptions to the node but does not specify a subscription ID, the service MUST return a <bad-request/> error to the subscriber, which SHOULD also include a pubsub-specific error condition of <subid-required/>.

Example 69. Entity did not specify SubID

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <subid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

If the requesting entity is subscribed but specifies an invalid subscription ID, the service MUST return a <not-acceptable/> error to the subscriber, which SHOULD also include a pubsub-specific error condition of <invalid-subid/>.

Example 70. Entity specified invalid SubID

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <error type='modify'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-subid xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

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 <not-authorized/> error to the subscriber, which SHOULD also include a pubsub-specific error condition of <not-subscribed/>.

Example 71. Entity is not subscribed

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <error type='auth'>
    <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <not-subscribed xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

If the service or node does not support persistent items and does not return the last published item, the service MUST return a <feature-not-implemented/> error to the subscriber, specifying a pubsub-specific error condition of <unsupported/> and a feature of "persistent-items".

Example 72. Persistent items not supported

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <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>
    

If the service or node does not support item retrieval (e.g., because the node is a collection node), the service MUST return a <feature-not-implemented/> error to the subscriber, specifying a pubsub-specific error condition of <unsupported/> and a feature of "retrieve-items".

Example 73. Item retrieval not supported

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <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>
    

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 <not-authorized/> error, which SHOULD also include a pubsub-specific error condition of <presence-subscription-required/>.

Example 74. Entity is not authorized to retrieve items (presence subscription required)

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <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>
    

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 <not-authorized/> error, which SHOULD also include a pubsub-specific error condition of <not-in-roster-group/>.

Example 75. Entity is not authorized to retrieve items (not in roster group)

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <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>
    

For nodes with a node access model of "whitelist", if the requesting entity is not on the whitelist then the service MUST return a <not-allowed/> error, which SHOULD include a pubsub-specific error condition of <closed-node/>.

Example 76. Node has whitelist access model

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <closed-node xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

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-required/> error to the subscriber.

Example 77. Payment is required to retrieve items

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <error type='auth'>
    <payment-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

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.

Example 78. Requesting entity is blocked

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the node does not exist, the service SHOULD return an <item-not-found/> error to the subscriber.

Example 79. Node does not exist

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

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 Result Set Manipulation [17] instead of the 'max_items' attribute.)

Example 80. Subscriber requests two most recent items

<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 81. Service returns two most recent items

<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>
    

The 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.

Example 82. Subscriber requests specific items by ItemID

<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 83. Service sends requested item(s)

<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>
    

If a subscription identifier is associated with a specific subscription, the service MUST require it so that it can generate different sets of items based on the subscription options associated with a specific subscription. Therefore the entity MUST include the 'subid' attribute with the items element when making the request; if it does not, the service MUST return a <not-acceptable/> error, which SHOULD include a pubsub-specific error condition of <subid-required/>.

Example 84. Subscriber sends request without SubID

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='items5'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
</iq>
    

Example 85. SubID required

<iq type='error'
    from='pubsub.shakespeare.lit'
    id='items5'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
  <error type='modify'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <subid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

7. Publisher Use Cases

7.1 Publish an Item to a Node

Any entity which 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 <publish/> child; the <publish/> element MUST possess a 'node' attribute and depending on the node configuration MAY contain no <item/> elements, one <item/> element, or (for Batch Processing) more than one <item/> element.

Note: It is not necessary for a publication request to include a payload or even an <item/> element in order to trigger a notification. For example, the result of publishing to a transient, notification-only node will be a notification that does not include even an <item/> element (as shown in the Motivating Example section of this document). However, for the sake of convenience we refer to the act of publication as "publishing an item" (rather than, say, "triggering a notification") even though a publication request will not always contain an <item/> element.

Example 86. Publisher publishes an item with an ItemID

<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='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>
  </pubsub>
</iq>
    

If the pubsub service can successfully process the request, it MUST inform the publisher of success.

Example 87. Service replies with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/blogbot'
    id='publish1'/>
    

If the pubsub service can successfully process the request, it MUST send then one <message/> stanza containing a pubsub event notification to each approved subscriber. 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 Handling Notification-Related Errors section of this document).

Depending on the node configuration, the event notification either will or will not contain the payload, as shown in the following examples.

If the node is configured to include payloads, the subscribers will receive payloads with the event notifications.

Example 88. Subscribers receive event notifications with payloads

<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='marcellus@denmark.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>

.
.
.
    

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 Retrieve Items from a Node section of this document.)

Example 89. Subscribers receive event notifications only

<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='marcellus@denmark.lit' id='fez'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'/>
    </items>
  </event>
</message>

.
.
.
    

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 Stanza Headers and Internet Metadata (SHIM) [18] format and SHOULD be included after the event notification information (i.e., as the last child of the <message/> stanza).

Example 90. Subscriber receives notated event notification

<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='pubsub#subid'>123-abc</header>
    <header name='pubsub#subid'>004-yyy</header>
  </headers>
</message>
    

There are several reasons why the publish request might fail:

  1. The requesting entity does not have sufficient privileges to publish.
  2. The node does not support item publication.
  3. The node does not exist.
  4. The payload size exceeds a service-defined limit.
  5. 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.
  6. The request does not match the node configuration.

These error cases are described more fully below.

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).

If the requesting entity does not have sufficient privileges to publish, the service MUST return a <forbidden/> error.

Example 91. Entity does not have sufficient privileges to publish to node

<iq type='error'
    from='pubsub.shakespeare.lit'
    id='publish1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        ... PAYLOAD ...
      </item>
    </publish>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the node does not support item publication (because it is a Collection Node), the service MUST return a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "publish".

Example 92. Node does not support item publication

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='publish1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        ... PAYLOAD ...
      </item>
    </publish>
  </pubsub>
  <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>
    

If the requesting entity attempts to publish an item to a node that does not exist, the service MUST return an <item-not-found/> error.

Example 93. Entity attempts to publish to a non-existent node

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='publish1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        ... PAYLOAD ...
      </item>
    </publish>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the payload size exceeds a service-defined limit, the service MUST return a <not-acceptable/> error, which SHOULD also include a pubsub-specific error condition of <payload-too-big/>.

Example 94. Entity attempts to publish very large payload

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='publish1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        ... HUGE PAYLOAD ...
      </item>
    </publish>
  </pubsub>
  <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>
    

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 <bad-request/> error, which SHOULD also include a pubsub-specific error condition of <invalid-payload/>.

Example 95. Entity attempts to publish item with multiple payload elements or namespace does not match

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='publish1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        ... INVALID PAYLOAD ...
      </item>
    </publish>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-payload xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

If the request does not conform to the configured event type for the node, the service MAY bounce the request with a <bad-request/> error, which SHOULD also include a pubsub-specific error condition. The following rules apply:

Examples of these errors are shown below.

Example 96. Publisher attempts to publish to persistent node with no item

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='publish1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='princely_musings'/>
  </pubsub>
  <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 97. Publisher attempts to publish to payload node with no payload

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='publish1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'/>
    </publish>
  </pubsub>
  <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 98. Publisher attempts to publish to transient notification node with item

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='publish1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'/>
    </publish>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <item-forbidden xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

Finally, in order to facilitate authorization for item removal as described in the Delete an Item from a Node 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.

7.2 Delete an Item from a Node

A service SHOULD allow a publisher to delete an item once it has been published to a node that supports persistent items. To delete an item, the publisher sends a retract request as shown in the following examples. The <retract/> element MUST possess a 'node' attribute, MAY possess a 'notify' attribute, and SHOULD contain one <item/> element (but MAY contain more than one <item/> element for Batch Processing of item retractions); the <item/> element MUST be empty and MUST possess an 'id' attribute.

Example 99. Entity deletes an item from a node

<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 100. Service replies with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='retract1'/>
    

There are several reasons why the item retraction request might fail:

  1. The publisher does not have sufficient privileges to delete the requested item.
  2. The node or item does not exist.
  3. The request does not specify a node.
  4. The request does not include an <item/> element or the <item/> element does not specify an ItemID.
  5. The node does not support persistent items.
  6. The service does not support the deletion of items.

These error cases are described more fully below.

If the requesting entity does not have sufficient privileges to delete the item, the service MUST return a <forbidden/> error.

Example 101. Requesting entity does not have sufficient privileges

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='retract1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <retract node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'/>
    </retract>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the node or item does not exist, the service MUST return an <item-not-found/> error.

Example 102. Non-existent node or item

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='retract1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <retract node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'/>
    </retract>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the request does not specify a node, the service MUST return a <bad-request/> error, which SHOULD also include a pubsub-specific error condition of <node-required/>.

Example 103. Request does not specify a node

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='retract1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <retract/>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <node-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

If the request does not include an <item/> element or the <item/> element does not specify an ItemID, the service MUST return a <bad-request/> error, which SHOULD also include a pubsub-specific error condition of <item-required/>.

Example 104. Request does not specify an item

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='retract1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <retract node='princely_musings'/>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <item-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

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-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "persistent-items".

Example 105. Node does not support persistent items

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='retract1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <retract node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'/>
    </retract>
  </pubsub>
  <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>
    

If the service does not support item deletion, it MUST return a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "delete-nodes".

Example 106. Service does not support item deletion

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='retract1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <retract node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'/>
    </retract>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='delete-nodes'/>
  </error>
</iq>
    

If none of the foregoing errors occurred, then the service MUST delete the item.

If none of the foregoing errors occurred and the <retract/> element included a 'notify' attribute with a value of "true" or "1" [19], then the service MUST delete the item and MUST send message notifications to all subscribers as shown below. The syntax is identical to publish notifications except that instead of an <item/> element, the notification includes a <retract/> element.

Example 107. Subscribers are notified of deletion

<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>

.
.
.
    

If a single entity is subscribed to the node multiple times, the service SHOULD notate the notification of 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 Stanza Headers and Internet Metadata (SHIM) protocol and SHOULD be included after the event notification information (i.e., as the last child of the <message/> stanza).

Example 108. Subscriber receives notated event notification

<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='pubsub#subid'>123-abc</header>
    <header name='pubsub#subid'>004-yyy</header>
  </headers>
</message>
    

8. Owner Use Cases

8.1 Create a Node

8.1.1 General Considerations

A service SHOULD allow entities to create new nodes. However, a service MAY disallow creation of nodes based on the identity of the requesting entity, or MAY disallow node creation altogether (e.g., reserving that privilege to a service-wide administrator).

There are two ways to create a node:

  1. Create a node with default configuration for the specified node type.
  2. Create and configure a node simultaneously.

These methods, along with method-specific error conditions, are explained more fully in the following sections.

In addition to method-specific error conditions, there are several general reasons why the node creation request might fail:

These general error cases are described more fully below.

If the service does not support node creation, it MUST respond with a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "create-nodes".

Example 109. Service does not support node creation

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='create1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='princely_musings'/>
    <configure/>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='create-nodes'/>
  </error>
</iq>
      

If only entities that are registered with the service may create nodes but the requesting entity has not yet registered, the service MUST respond with a <registration-required/> error.

Example 110. Service requires registration

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='create1'>
    <pubsub xmlns='http://jabber.org/protocol/pubsub'>
      <create node='princely_musings'/>
      <configure/>
    </pubsub>
    <error type='auth'>
      <registration-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    </error>
</iq>
      

If the requesting entity does not have sufficient privileges to create nodes, the service MUST respond with a <forbidden/> error.

Example 111. Requesting entity is prohibited from creating nodes

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='create1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='princely_musings'/>
    <configure/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
      

If the requested NodeID already exists, the service MUST respond with a <conflict/> error.

Example 112. NodeID already exists

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='create1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='princely_musings'/>
    <configure/>
  </pubsub>
  <error type='cancel'>
    <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
      

If the node creator does not specify a NodeID but the service does not support instant nodes, the service MUST return a <not-acceptable/> error, which SHOULD include a pubsub-specific error condition of <nodeid-required/>.

Example 113. Service does not support instant nodes

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='create2'>
    <pubsub xmlns='http://jabber.org/protocol/pubsub'>
      <create/>
      <configure/>
    </pubsub>
    <error type='modify'>
      <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
      <nodeid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
    </error>
</iq>
      

If the node creator does not specify a NodeID but the service supports instant nodes, the service SHOULD generate a NodeID that is unique within the context of the service on behalf of the node creator.

Example 114. Entity requests an instant node

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='create2'>
    <pubsub xmlns='http://jabber.org/protocol/pubsub'>
      <create/>
      <configure/>
    </pubsub>
</iq>
      

If no error occurs, the pubsub service SHOULD create the node, generate a NodeID that is unique within the context of that service, and inform the user of success (including the NodeID in the response).

Example 115. Service replies with success and generated NodeID

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='create2'>
    <pubsub xmlns='http://jabber.org/protocol/pubsub'>
      <create node='25e3d37dabbab9541f7523321421edc5bfeb2dae'/>
    </pubsub>
</iq>
      

Note: When a service successfully creates a node on behalf of the requesting entity, it MUST return an IQ result. If the node creation request did not specify a NodeID and the service supports creation of instant nodes, the service MUST specify the created NodeID in the IQ result. Similarly, if the node creation request specified a NodeID but the service modified the NodeID before creating the node as described in the Collection Nodes section of this document, the service MUST also specify the modified node in the IQ result. In all other cases, the service MUST NOT specify the NodeID in the IQ result (since the node creator can determine which node was created by tracking the 'id' attribute that it specified for the IQ-set).

8.1.2 Create a Node With Default Configuration

As explained above, each node type has its own default configuration. By asking the service to create a node with default configuration, the node creator accepts the default configuration. If the service allows node configuration, the owner may reconfigure the node after creating the node (as described in the Configure a Node section of this document). In addition, a service MAY allow entities to determine the default configuration options for a given node type before creating a node (as described in the Request Default Configurations section of this document).

In order to create a node with default configuration, the node creator MUST include an empty <configure/> child element in the creation request. The node creator MAY specify values for the 'pubsub#node_type' and 'pubsub#access_model' configuration fields or MAY accept the defaults, which are "leaf" for the 'pubsub#node_type' field and the value represented by the 'pubsub#access_model' field (i.e., "authorize", "open", "presence", "roster", or "whitelist").

In the following example, the node creator requests a leaf node (the default type) with an open access model (assumed to be the default type for this service).

Example 116. Entity requests leaf node with (default) open access model

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='create1'>
    <pubsub xmlns='http://jabber.org/protocol/pubsub'>
      <create node='princely_musings'/>
      <configure/>
    </pubsub>
</iq>
      

In order to request an access model other than the default for the service, the node creator MUST include a Data Form in the node creation request that specifies a non-default value for the 'pubsub#node_type' field.

Example 117. Entity requests leaf node with non-default access model

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='create2'>
    <pubsub xmlns='http://jabber.org/protocol/pubsub'>
      <create node='princely_musings'/>
      <configure>
        <x xmlns='jabber:x:data' type='submit'>
          <field var='FORM_TYPE' type='hidden'>
            <value>http://jabber.org/protocol/pubsub#node_config</value>
          </field>
          <field var='pubsub#access_model'><value>whitelist</value></field>
        </x>
      </configure>
    </pubsub>
</iq>
      

If the access model is supported and none of the general or method-specific errors has occurred, the service SHOULD create the node and inform the requesting entity of success.

Example 118. Service informs requesting entity of success

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='create1'/>
      

If service does not support the specified access model, it MUST return a <not-acceptable/> error, which SHOULD include a pubsub-specific error condition of <unsupported-access-model/>.

Example 119. Service does not support specified access model

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='create2'>
    <pubsub xmlns='http://jabber.org/protocol/pubsub'>
      <create node='princely_musings'/>
      <configure>
        <x xmlns='jabber:x:data' type='submit'>
          <field var='FORM_TYPE' type='hidden'>
            <value>http://jabber.org/protocol/pubsub#node_config</value>
          </field>
          <field var='pubsub#access_model'><value>whitelist</value></field>
        </x>
      </configure>
    </pubsub>
    <error type='auth'>
      <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
      <unsupported-access-model xmlns='http://jabber.org/protocol/pubsub#errors'/>
    </error>
</iq>
      

(For error handling if the service does not support the specified node type, see the Collection Node section of this document.)

8.1.3 Create and Configure a Node

If an implementation allows node configuration (see the Configure a Node section of this document), it SHOULD allow node creation requests to contain the desired node configuration in the node creation request.

Note: The <configure/> element MUST follow the <create/> element and MUST NOT possess a 'node' attribute, since the value of the <create/> element's 'node' attribute specifies the desired NodeID; if any of these rules are violated, the service MUST return a <bad-request/> error.

Example 120. Entity requests a new node with non-default configuration.

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='create1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='princely_musings'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        <field var='pubsub#title'><value>Princely Musings (Atom)</value></field>
        <field var='pubsub#deliver_payloads'><value>1</value></field>
        <field var='pubsub#persist_items'><value>1</value></field>
        <field var='pubsub#max_items'><value>10</value></field>
        <field var='pubsub#access_model'><value>open</value></field>
        <field var='pubsub#publish_model'><value>publishers</value></field>
        <field var='pubsub#send_item_subscribe'><value>false</value></field>
        <field var='pubsub#presence_based_delivery'><value>false</value></field>
        <field var='pubsub#notify_config'><value>0</value></field>
        <field var='pubsub#notify_delete'><value>0</value></field>
        <field var='pubsub#notify_retract'><value>0</value></field>
        <field var='pubsub#max_payload_size'><value>1028</value></field>
        <field var='pubsub#type'><value>http://www.w3.org/2005/Atom</value></field>
        <field var='pubsub#body_xslt'>
          <value>http://jabxslt.jabberstudio.org/atom_body.xslt</value>
        </field>
      </x>
    </configure>
  </pubsub>
</iq>
      

Example 121. Service replies with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='create1'/>
      

If a service supports this "create-and-configure" feature, it MUST advertise that fact by returning a feature of "http://jabber.org/protocol/pubsub#create-and-configure" in response to service discovery information requests. If the create-and-configure option is not supported but the requesting entity sends such a request anyway, the service SHOULD ignore the configuration part of the request and proceed as if it had not been included.

8.2 Configure a Node

After creating a new node, the node owner may want to modify the node configuration. The process for doing so is shown below.

Example 122. Owner requests configuration form

<iq type='get'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='config1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'/>
  </pubsub>
</iq>
    

Note: The following example shows some of the possible configuration options that MAY be provided. If an implementation implements these features using the Data Forms protocol, that implementation MUST use the fields that are registered with the Jabber Registrar in association with the 'http://jabber.org/protocol/pubsub' namespace (a preliminary representation of those field variables is shown below and in the pubsub#node_config FORM_TYPE section of this document, but MUST NOT be construed as canonical, since the Jabber Registrar may standardize additional fields at a later date without changes to this document). An implementation MAY choose to specify different labels, values, and even field types, but MUST conform to the defined variable naming scheme.

Example 123. Service responds with configuration form

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='config1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'>
      <x xmlns='jabber:x:data' type='form'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        <field var='pubsub#title' type='text-single'
               label='A friendly name for the node'/>
        <field var='pubsub#deliver_payloads' type='boolean'
               label='Deliver payloads with event notifications'>
          <value>true</value>
        </field>
        <field var='pubsub#notify_config' type='boolean'
               label='Notify subscribers when the node configuration changes'>
          <value>0</value>
        </field>
        <field var='pubsub#notify_delete' type='boolean'
               label='Notify subscribers when the node is deleted'>
          <value>false</value>
        </field>
        <field var='pubsub#notify_retract' type='boolean'
               label='Notify subscribers when items are removed from the node'>
          <value>false</value>
        </field>
        <field var='pubsub#persist_items' type='boolean'
               label='Persist items to storage'>
        <value>1</value>
        </field>
        <field var='pubsub#max_items' type='text-single'
               label='Max # of items to persist'>
          <value>10</value>
        </field>
        <field var='pubsub#subscribe' type='boolean'
               label='Whether to allow subscriptions'>
          <value>1</value>
        </field>
        <field var='pubsub#access_model' type='list-single'
               label='Specify the subscriber model'>
          <option><value>authorize</value></option>
          <option><value>open</value></option>
          <option><value>presence</value></option>
          <option><value>roster</value></option>
          <option><value>whitelist</value></option>
          <value>open</value>
        </field>
        <field var='pubsub#roster_groups_allowed' type='list-multi'
               label='Roster groups allowed to subscribe'>
          <option><value>friends</value></option>
          <option><value>courtiers</value></option>
          <option><value>servants</value></option>
          <option><value>enemies</value></option>
        </field>
        <field var='pubsub#publish_model' type='list-single'
               label='Specify the publisher model'>
          <option><value>publishers</value></option>
          <option><value>subscribers</value></option>
          <option><value>open</value></option>
          <value>publishers</value>
        </field>
        <field var='pubsub#max_payload_size' type='text-single'
               label='Max Payload size in bytes'>
          <value>1028</value>
        </field>
        <field var='pubsub#send_item_subscribe' type='boolean'
               label='Send items to new subscribers'>
          <value>0</value>
        </field>
        <field var='pubsub#presence_based_delivery' type='boolean'
               label='Deliver notifications only to available users'>
          <value>0</value>
        </field>
        <field var='pubsub#type' type='text-single'
               label='Specify the type of payload data to be provided at this node'>
          <value>http://www.w3.org/2005/Atom</value>
        </field>
        <field var='pubsub#dataform_xslt' type='text-single'
               label='Payload XSLT'/>
      </x>
    </configure>
  </pubsub>
</iq>
    

There are several reasons why the node configuration request might fail:

  1. The service does not support node configuration.
  2. The requesting entity does not have sufficient privileges to configure the node.
  3. The request did not specify a node.
  4. The node has no configuration options.
  5. The specified node does not exist.

These error cases are described more fully below.

If the service does not support node configuration, the service MUST return a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "config-node".

Example 124. Service does not support node configuration

<iq type='error'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='config1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='config-node'/>
  </error>
</iq>
    

If the requesting entity does not have sufficient privileges to configure the node, the service MUST respond with a <forbidden/> error.

Example 125. Requesting entity is prohibited from configuring this node

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='config1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the request did not specify a node, the service SHOULD return a <bad-request/> error. It is possible that by not including a NodeID, the requesting entity is asking to configure the root node; however, if the requesting entity is not a service-level admin, it makes sense to return <bad-request/> instead of <forbidden/>.

Example 126. Request did not specify a node

<iq type='error'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='config1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <nodeid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

If no configuration options are available (e.g., because node configuration is "locked down"), the service MUST return a <not-allowed/> error to the owner.

Example 127. Node has no configuration options

<iq type='error'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='config1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the node does not exist, the service MUST return an <item-not-found/> error.

Example 128. Node does not exist

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='config1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

After receiving the configuration form, the owner SHOULD submit a completed configuration form.

Example 129. Owner submits node configuration form

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='config2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        <field var='pubsub#title'><value>Princely Musings (Atom)</value></field>
        <field var='pubsub#deliver_payloads'><value>1</value></field>
        <field var='pubsub#persist_items'><value>1</value></field>
        <field var='pubsub#max_items'><value>10</value></field>
        <field var='pubsub#access_model'><value>open</value></field>
        <field var='pubsub#publish_model'><value>publishers</value></field>
        <field var='pubsub#send_item_subscribe'><value>false</value></field>
        <field var='pubsub#presence_based_delivery'><value>false</value></field>
        <field var='pubsub#notify_config'><value>0</value></field>
        <field var='pubsub#notify_delete'><value>0</value></field>
        <field var='pubsub#notify_retract'><value>0</value></field>
        <field var='pubsub#max_payload_size'><value>1028</value></field>
        <field var='pubsub#type'><value>http://www.w3.org/2005/Atom</value></field>
        <field var='pubsub#body_xslt'>
          <value>http://jabxslt.jabberstudio.org/atom_body.xslt</value>
        </field>
      </x>
    </configure>
  </pubsub>
</iq>
    

Example 130. Service replies with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='config2'/>
    

Alternatively, the owner MAY cancel the configuration process, in which case the existing configuration MUST be applied.

Example 131. Owner cancels configuration process

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='config2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'>
      <x xmlns='jabber:x:data' type='cancel'/>
    </configure>
  </pubsub>
</iq>
    

If the requested node configuration change cannot be processed (e.g., because the node owner has attempted to change the configuration so that there are no node owners), the service MUST return a <not-acceptable/> error to the owner.

Example 132. Configuration change cannot be processed

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='config2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the "pubsub#notify_config" option is set to true, the service MUST send a notification of configuration change to all subscribers. (A service SHOULD support this option for leaf nodes and MUST support it for Collection Nodes.) If the node configuration is set to event notifications only, the notification MUST consist of an empty <configuration/> element whose 'node' attribute is set to the NodeID of the node; if the node configuration is set to full payloads, the <configuration/> element MUST in addition contain the node configuration as represented via the Data Forms protocol.

Example 133. Service sends configuration change notification (event notification only)

<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <configuration node='princely_musings'/>
  </event>
</message>
    

Example 134. Service sends configuration change notification (full payload)

<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <configuration node='princely_musings'>
      <x xmlns='jabber:x:data' type='result'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        <field var='pubsub#title'><value>Princely Musings (Atom)</value></field>
        <field var='pubsub#deliver_payloads'><value>1</value></field>
        <field var='pubsub#notify_config'><value>0</value></field>
        <field var='pubsub#notify_delete'><value>0</value></field>
        <field var='pubsub#notify_retract'><value>0</value></field>
        <field var='pubsub#persist_items'><value>1</value></field>
        <field var='pubsub#max_items'><value>10</value></field>
        <field var='pubsub#subscribe'><value>1</value></field>
        <field var='pubsub#access_model'><value>open</value></field>
        <field var='pubsub#publish_model'><value>publishers</value></field>
        <field var='pubsub#max_payload_size'><value>9216</value></field>
        <field var='pubsub#send_item_subscribe'><value>0</value></field>
        <field var='pubsub#presence_based_delivery'><value>0</value></field>
        <field var='pubsub#type'><value>http://www.w3.org/2005/Atom</value></field>
        <field var='pubsub#body_xslt'>
          <value>http://jabxslt.jabberstudio.org/atom_body.xslt</value>
        </field>
      </x>
    </configuration>
  </event>
</message>
    

8.3 Request Default Configuration Options

A service MAY allow entities to determine the default node configuration for new nodes created on the service, in order to help entities determine whether they want to perform create-and-configure as previously described. To get the options, the entity MUST send an empty <default/> element to the service with no NodeID; in response, the service SHOULD return the default node options.

Example 135. Entity requests default configuration options

<iq type='get'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='def1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <default/>
  </pubsub>
</iq>
    

Example 136. Service responds with default configuration options

<iq type='result'
    from='hamlet@denmark.lit/elsinore'
    id='def1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <default>
      <x xmlns='jabber:x:data' type='form'>
        <field var='FORM_TYPE' type='hidden'>
           <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        <field var='pubsub#title' type='text-single'
               label='A friendly name for the node'/>
        <field var='pubsub#deliver_payloads' type='boolean'
             label='Deliver payloads with event notifications'>
          <value>1</value>
        </field>
        <field var='pubsub#notify_config' type='boolean'
               label='Notify subscribers when the node configuration changes'>
          <value>0</value>
        </field>
        <field var='pubsub#notify_delete' type='boolean'
               label='Notify subscribers when the node is deleted'>
          <value>0</value>
        </field>
        <field var='pubsub#notify_retract' type='boolean'
               label='Notify subscribers when items are removed from the node'>
          <value>0</value>
        </field>
        <field var='pubsub#persist_items' type='boolean'
               label='Persist items to storage'>
          <value>1</value>
        </field>
        <field var='pubsub#max_items' type='text-single'
               label='Max # of items to persist'>
          <value>10</value>
        </field>
        <field var='pubsub#subscribe' type='boolean'
               label='Whether to allow subscriptions'>
          <value>1</value>
        </field>
        <field var='pubsub#access_model' type='list-single'
               label='Specify the subscriber model'>
          <option><value>authorize</value></option>
          <option><value>open</value></option>
          <option><value>presence</value></option>
          <option><value>roster</value></option>
          <option><value>whitelist</value></option>
          <value>open</value>
        </field>
        <field var='pubsub#roster_groups_allowed' type='list-multi'
               label='Roster groups allowed to subscribe'>
          <option><value>friends</value></option>
          <option><value>courtiers</value></option>
          <option><value>servants</value></option>
          <option><value>enemies</value></option>
        </field>
        <field var='pubsub#publish_model' type='list-single'
               label='Specify the publisher model'>
          <option><value>publishers</value></option>
          <option><value>subscribers</value></option>
          <option><value>open</value></option>
          <value>publishers</value>
        </field>
        <field var='pubsub#max_payload_size' type='text-single'
               label='Max payload size in bytes'>
          <value>9216</value>
        </field>
        <field var='pubsub#send_item_subscribe' type='boolean'
               label='Send items to new subscribers'>
          <value>0</value>
        </field>
        <field var='pubsub#presence_based_delivery' type='boolean'
               label='Only deliver notifications to available users'>
          <value>0</value>
        </field>
      </x>
    </default>
  </pubsub>
</iq>
    

There are several reasons why the default node configuration options request might fail:

  1. The service does not support node configuration.
  2. The service does not support retrieval of default node configuration.

These error cases are described more fully below.

If the service does not support node configuration, it MUST return a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "config-node".

Example 137. Service does not support node configuration

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='def1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <default/>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='config-node'/>
  </error>
</iq>
    

If the service does not support retrieval of default node configuration options, it MUST return a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "retrieve-default".

Example 138. Service does not support retrieval of default configuration options

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='def1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <default/>
  </pubsub>
  <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'/>
  </error>
</iq>
    

The default configuration options may be different for a collection node vs. a leaf node. In order to specifically request the default configuration options for collection nodes, an entity MUST include a Data Form with a 'pubsub#node_type' field whose value is "collection" in the request (since the default value for the 'pubsub#node_type' field is "leaf").

Example 139. Entity requests default configuration options for collection nodes

<iq type='get'
    from='hamlet@denmark.lit/elsinore'
    id='def2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <default>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        <field var='pubsub#node_type'><value>collection</value></field>
      </x>
    </default>
  </pubsub>
</iq>
    

If the service does not support collection nodes, it MUST return a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "collections".

Example 140. Service does not support collection nodes

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='def2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <default>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        <field var='pubsub#node_type'><value>collection</value></field>
      </x>
    </default>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='collections'/>
  </error>
</iq>
    

8.4 Delete a Node

If a service supports node creation, it MUST support node deletion. If an implementation persists items, it MUST remove all items from persistent storage before the node itself is deleted.

In order to delete a node, a node owner MUST send a node deletion request, consisting of a <delete/> element whose 'node' attribute specifies the NodeID of the node to be deleted.

Example 141. Owner deletes a node

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='delete1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <delete node='princely_musings'/>
  </pubsub>
</iq>
    

If no error occurs, the service MUST inform the owner of success.

Example 142. Service replies with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    id='delete1'/>
    

In addition, the service MUST also send notification of node deletion to all subscribers (which SHOULD include pending and unconfigured subscriptions).

Example 143. Subscribers are notified of node deletion

<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <delete node='princely_musings'/>
  </event>
</message>

<message from='pubsub.shakespeare.lit' to='bernardo@denmark.lit' id='bar'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <delete node='princely_musings'/>
  </event>
</message>

.
.
.
    

There are several reasons why the node deletion request might fail:

  1. The requesting entity does not have sufficient privileges to delete the node.
  2. The node is the root collection node, which cannot be deleted.
  3. The specified node does not exist.

These error cases are described more fully below.

If the requesting entity does not have sufficient privileges to delete the node (e.g., is not an owner), the service MUST return a <forbidden/> error.

Example 144. Entity is not an owner

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='delete1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <delete node='princely_musings'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the requesting entity attempts to delete the root collection node, the service MUST return a <not-allowed/> error.

Example 145. Node is the root

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='delete1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <delete/>
  </pubsub>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the requesting entity attempts to delete a node that does not exist, the service MUST return an <item-not-found/> error.

Example 146. Owner attempts to delete a non-existent node

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='delete1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <delete node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the deleted node is a Collection Node, the implementation MAY associate the "orphaned" leaf nodes with the root collection node or associate them with no collection node.

8.5 Purge All Node Items

If a service persists published items, it MAY enable node owners to purge the node of all published items (thus removing all items from the persistent store, with the exception of the last published item, which MAY be cached). In order to purge a node of all items, a node owner MUST send a node purge request, consisting of a <purge/> element whose 'node' attribute specifies the NodeID of the node to be purged.

Example 147. Owner purges all items from a node

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='purge1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <purge node='princely_musings'/>
  </pubsub>
</iq>
    

If no error occurs, the service MUST purge the node and inform the owner of success.

Example 148. Service replies with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    id='purge1'/>
    

If the node or service has been configured to notify subscribers on deletion of items, a purge request MUST NOT result in sending the same notifications as are sent when deleting items (since purging a node with many persisted items could result in a large number of notifications); instead, the node MUST send a single notification to each subscriber, containing an empty <purge/> child element.

Example 149. Subscribers are notified of node purge

<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <purge node='princely_musings'/>
  </event>
</message>

<message from='pubsub.shakespeare.lit' to='bernardo@denmark.lit' id='bar'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <purge node='princely_musings'/>
  </event>
</message>

.
.
.
    

There are several reasons why the node purge request might fail:

  1. The node or service does not support node purging.
  2. The requesting entity does not have sufficient privileges to purge the node.
  3. The node is not configured to persist items.
  4. The specified node does not exist.

These error cases are described more fully below.

If the node or service does not support node purging, it MUST return a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "purge-nodes".

Example 150. Service does not support node purging

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='purge1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <purge node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='purge-nodes'/>
  </error>
</iq>
    

If the requesting entity does not have sufficient privileges to purge the node (e.g., because it is not a node owner), the service MUST return a <forbidden/> error.

Example 151. Entity is not an owner

<iq type='error'
    from='pubsub.shakespeare.lit'
    id='purge1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <purge node='princely_musings'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the service or node does not persist items (e.g., because the node is a collection node), it MUST return a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "persistent-items".

Example 152. Node is not configured for persistent items

<iq type='error'
    from='pubsub.shakespeare.lit'
    id='purge1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <purge node='princely_musings'/>
  </pubsub>
  <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>
    

If the node does not exist, the service MUST return an <item-not-found/> error.

Example 153. Node does not exist

<iq type='error'
    from='pubsub.shakespeare.lit'
    id='purge1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <purge node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

8.6 Manage Subscription Requests

A service MAY send subscription approval requests to the node owner(s) at any time. An approval request consists of a message stanza containing a Data Form scoped by the "http://jabber.org/protocol/pubsub#subscribe_authorization" FORM_TYPE. The form MUST contain a boolean field that has a 'var' attribute of "pubsub#allow", which is the field that designates whether or not to allow the subscription request. The form SHOULD include fields that specify the node identifier, the subscription id (if applicable), and the JID of the pending subscriber. The message MAY include a <body/> element that contains natural-language text explaining that the message contains a pending subscription form.

Example 154. Service sends authorization request to node owner

<message to='hamlet@denmark.lit' from='pubsub.shakespeare.lit' id='approve1'>
  <x xmlns='jabber:x:data' type='form'>
    <title>PubSub subscriber request</title>
    <instructions>
      To approve this entity&apos;s subscription request,
      click the OK button. To deny the request, click the
      cancel button.
    </instructions>
    <field var='FORM_TYPE' type='hidden'>
      <value>http://jabber.org/protocol/pubsub#subscribe_authorization</value>
    </field>
    <field var='pubsub#subid' type='hidden'><value>123-abc</value></field>
    <field var='pubsub#node' type='text-single' label='Node ID'>
      <value>princely_musings</value>
    </field>
    <field var='pusub#subscriber_jid' type='jid-single' label='Subscriber Address'>
      <value>horatio@denmark.lit</value>
    </field>
    <field var='pubsub#allow' type='boolean'
           label='Allow this JID to subscribe to this pubsub node?'>
      <value>false</value>
    </field>
  </x>
</message>
    

In order to approve the request, the owner shall submit the form and set the "pubsub#allow" field to a value of "1" or "true"; for tracking purposes the message MUST reflect the 'id' attribute originally provided.

Example 155. Owner approves subscription request

<message from='hamlet@denmark.lit/elsinore' to='pubsub.shakespeare.lit' id='approve1'>
  <x xmlns='jabber:x:data' type='submit'>
    <field var='FORM_TYPE' type='hidden'>
      <value>http://jabber.org/protocol/pubsub#subscribe_authorization</value>
    </field>
    <field var='pubsub#subid'>
      <value>123-abc</value>
    </field>
    <field var='pubsub#node'>
      <value>princely_musings</value>
    </field>
    <field var='pubsub#subscriber_jid'>
      <value>horatio@denmark.lit</value>
    </field>
    <field var='pubsub#allow'>
       <value>true</value>
    </field>
  </x>
</message>
    

The service then SHOULD send notification to the approved subscriber (see the Notification of Subscription State Changes section of this document).

Example 156. Subscription approval notification

<message
    from='pubsub.shakespeare.lit'
    to='horatio@denmark.lit'
    id='approvalnotify1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscription node='princely_musings' jid='horatio@denmark.lit' subscription='subscribed'/>
  </pubsub>
</message>
    

In order to deny the request, the owner shall submit the form and set the "pubsub#allow" field to a value of "0" or "false"; as above, the message MUST reflect the 'id' attribute originally provided.

Example 157. Owner denies subscription request

<message from='hamlet@denmark.lit/elsinore' to='pubsub.shakespeare.lit' id='approve1'>
  <x xmlns='jabber:x:data' type='submit'>
    <field var='FORM_TYPE' type='hidden'>
       <value>http://jabber.org/protocol/pubsub#subscribe_authorization</value>
    </field>
    <field var='pubsub#subid'>
       <value>123-abc</value>
    </field>
    <field var='pubsub#node'>
      <value>princely_musings</value>
    </field>
    <field var='pubsub#subscriber_jid'>
       <value>horatio@denmark.lit</value>
    </field>
    <field var='pubsub#allow'>
        <value>false</value>
    </field>
  </x>
</message>
    

The service then SHOULD send notification to the denied subscriber (see the Notification of Subscription State Changes section of this document).

Example 158. Subscription cancellation / denial notification

<message
    from='pubsub.shakespeare.lit'
    to='horatio@denmark.lit'
    id='unsubnotify1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscription node='princely_musings' jid='horatio@denmark.lit' subscription='none'/>
  </pubsub>
</message>
    

In order to cancel the form submission, the owner shall reply with the form's 'type' attribute set to "cancel".

Example 159. Owner cancels form submission

<message from='hamlet@denmark.lit/elsinore' to='pubsub.shakespeare.lit' id='approve1'>
  <x xmlns='jabber:x:data' type='cancel'>
    <field var='FORM_TYPE' type='hidden'>
      <value>http://jabber.org/protocol/pubsub#subscribe_authorization</value>
    </field>
  </x>
</message>
    

The service MUST check the "pubsub#allow" field to see if the subscription should be allowed or denied. If the owner cancels the Data Form, then the subscription request MUST remain in the pending state.

8.6.1 Request All Pending Subscription Requests

A service MAY allow owners to request all the current pending subscription requests for all of their nodes at the service. Implementations MUST use the Ad-Hoc Commands [20] protocol to provide this functionality. The command name ('node' attribute of the command element) MUST have a value of "http://jabber.org/protocol/pubsub#get-pending".

Example 160. Owner requests pending subscription requests

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='pending1'>
  <command xmlns='http://jabber.org/protocol/commands'
           node='http://jabber.org/protocol/pubsub#get-pending'
           action='execute'/>
</iq>
      

If no error occurs, the service SHOULD return a data form for managing subscription requests, which MUST contain a single field with a 'var' attribute value of "node" whose <option/> elements specify the nodes for which the requesting entity has subscription approval privileges (as an optimization, the service MAY specify only the nodes that have subscription requests pending).

Example 161. Service responds with data form to be populated

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='pending1'>
  <command xmlns='http://jabber.org/protocol/commands'
           sessionid='pubsub-get-pending:20031021T150901Z-600'
           node='http://jabber.org/protocol/pubsub#get-pending'
           status='executing'
           action='execute'>
    <x xmlns='jabber:x:data' type='form'>
      <field type='list-single' var='pubsub#node'>
        <option><value>princely_musings</value></option>
        <option><value>news_from_elsinore</value></option>
      </field>
    </x>
  </command>
</iq>
      

There are several reasons why the pending subscription approval request might fail:

  1. The service does not support the ad-hoc commands protocol.
  2. The service supports ad-hoc commands but does not support the "get-pending" feature.
  3. The requesting entity does not have sufficient privileges to approve subscription requests.
  4. The specified node does not exist.

These error cases are described more fully below.

If the service does not support the ad-hoc commands protocol, it MUST respond with a <service-unavailable/> error.

Example 162. Service responds with node not found

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='pending1'>
  <command xmlns='http://jabber.org/protocol/commands'
           node='http://jabber.org/protocol/pubsub#get-pending'
           action='execute'/>
  <error type='cancel'>
    <service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
      

If the service does not support the "get-pending" feature, it MUST respond with a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "get-pending".

Example 163. Service responds with node not found

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='pending1'>
  <command xmlns='http://jabber.org/protocol/commands'
           node='http://jabber.org/protocol/pubsub#get-pending'
           action='execute'/>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='get-pending'/>
  </error>
</iq>
      

If the requesting entity does not have sufficient privileges to approve subscription requests, the service MUST respond with a <forbidden/> error.

Example 164. Entity does not have sufficient privileges to approve subscription requests

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='pending1'>
  <command xmlns='http://jabber.org/protocol/commands'
           node='http://jabber.org/protocol/pubsub#get-pending'
           action='execute'/>
  <error type='cancel'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the requested node does not exist, the service MUST respond with an <item-not-found/> error.

Example 165. Service responds with node not found

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='pending1'>
  <command xmlns='http://jabber.org/protocol/commands'
           node='http://jabber.org/protocol/pubsub#get-pending'
           action='execute'/>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
      

Upon receiving the data form for managing subscription requests, the owner then MAY request pending subscription approval requests for a given node.

Example 166. Owner requests all pending subscription requests for a node

<iq type='set' to='pubsub.shakespeare.lit' id='pending2'>
  <command xmlns='http://jabber.org/protocol/commands'
           sessionid='pubsub-get-pending:20031021T150901Z-600'
           node='http://jabber.org/protocol/pubsub#get-pending'
           action='execute'>
    <x xmlns='jabber:x:data' type='submit'>
      <field var='pubsub#node'>
        <value>princely_musings</value>
      </field>
    </x>
  </command>
</iq>
      

If no error occurs, the service shall respond with success.

Example 167. Service responds with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='pending2'/>
    

The service shall then send one subscription approval message for each pending subscription request, as shown above for a single pending subscription request.

Note: A service SHOULD conform to its affiliation policies in maintaining the list of pending subscriptions. In particular, if the affiliation of an entity with a pending subscription is modified to owner or publisher, the service SHOULD automatically approve the subscription request and remove the entity's previous request from the pending list. Similarly, if the affiliation of an entity with a pending subscription is modified to outcast, the service SHOULD automatically reject the subscription request and remove the entity's previous request from the pending list.

If an entity's subscription request is denied, the service SHOULD send a <message/> to the entity, where the message conforms to the format described in the Notification of Subscription Denial or Cancellation section of this document.

8.7 Manage Subscriptions

A service MAY allow a node owner to edit the list of subscriptions associated with a given node and to set subscriptions for new entities (for nodes of type "whitelist", this enables the node owner to add subscribers); if so, it MUST advertise support for the "pubsub#manage-subscriptions" feature.

In order to request a list of all subscriptions, a node owner MUST send a subscriptions request, consisting of a <subscriptions/> element whose 'node' attribute specifies the NodeID of the relevant node.

Example 168. Owner requests all subscriptions

<iq type='get'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='subman1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <subscriptions node='princely_musings'/>
  </pubsub>
</iq>
    

If no error occurs, the service MUST return the list of subscriptions for entities whose subscription state is "subscribed" or "unconfigured" (it MUST NOT return entities whose subscription state is "none" and SHOULD NOT return entities whose subscription state is "pending"). The result MAY specify multiple <subscription/> elements for the same entity (JID), but each element MUST possess a distinct value of the 'subid' attribute (as shown below).

Example 169. Service returns list of subscriptions

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='subman1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <subscriptions node='princely_musings'>
      <subscription jid='hamlet@denmark.lit' subscription='subscribed'/>
      <subscription jid='polonius@denmark.lit' subscription='unconfigured'/>
      <subscription jid='bernardo@denmark.lit' subscription='subscribed' subid='123-abc'/>
      <subscription jid='bernardo@denmark.lit' subscription='subscribed' subid='004-yyy'/>
    </subscriptions>
  </pubsub>
</iq>
    

There are several reasons why the manage subscriptions request might fail:

  1. The service does not support subscription management.
  2. The requesting entity does not have sufficient privileges to manage subscriptions.
  3. The specified node does not exist.

These error cases are described more fully below.

If an implementation does not support subscription management, it MUST return a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "manage-subscriptions".

Example 170. Node or service does not support subscription management

<iq type='error'
    from='pubsub.shakespeare.lit'
    id='purge1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <subscriptions node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='manage-subscriptions'/>
  </error>
</iq>
    

If the requesting entity is not a node owner, the service MUST return a <forbidden/> error.

Example 171. Entity is not an owner

<iq type='error'
    from='pubsub.shakespeare.lit'
    id='subman1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <subscriptions node='princely_musings'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the node does not exist, the service MUST return an <item-not-found/> error.

Example 172. Node does not exist

<iq type='error'
    from='pubsub.shakespeare.lit'
    id='purge1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <subscriptions node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

Upon receiving the subscriptions list, the node owner MAY modify subscription states. The owner MUST send only modified subscription states (i.e., a "delta"), not the complete list. (Note: If the 'subscription' attribute is not specified in a modification request, then the value MUST NOT be changed.)

Example 173. Owner modifies subscriptions

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='subman2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <subscriptions node='princely_musings'/>
      <subscription jid='bard@shakespeare.lit' subscription='subscribed'/>
    </subscriptions>
  </pubsub>
</iq>
    

Example 174. Service responds with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    id='subman2'/>
    

In order to remove an entity from the subscriptions list, the owner MUST set the value of the 'subscription' attribute to "none" and the service MUST remove that entity from the subscriptions list and not return it in response to future list requests.

The owner MAY change multiple subscriptions in a single request. If one of the entity elements specified is invalid, the service MUST return an IQ error (which SHOULD be <not-acceptable/>) with the invalid entries, where the subscription returned is the original, un-altered subscription.

Example 175. Owner sets subscription for multiple entities

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='subman3'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <subscriptions node='princely_musings'>
      <subscription jid='polonius@denmark.lit' subscription='none'/>
      <subscription jid='bard@shakespeare.lit' subscription='subscribed'/>
    </subscriptions>
  </pubsub>
</iq>
    

Example 176. Service responds with an error

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='subman3'/>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <subscriptions node='princely_musings'>
      <subscription jid='bard@shakespeare.lit' subscription='subscribed'/>
    </subscriptions>
  </pubsub>
  <error type='modify'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If errors occur during a modification request for multiple entities, the pubsub service MUST return any <subscription/> element(s) which caused the error. Returned entities which failed to be modified MUST include the existing 'subscription' attribute. Any entity elements which are not returned in an IQ error case MUST be treated as successful modifications. The owner MAY specify multiple <subscription/> elements for the same entity, but each element MUST possess a distinct value of the 'subid' attribute.

An implementation SHOULD send notification to an entity whose subscription has changed (see the Notification of Subscription State Changes section of this document).

Example 177. Service sends notification of subscription change

<message from='pubsub.shakespeare.lit' to='polonius@denmark.lit'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscription node='princely_musings' jid='polonius@denmark.lit' subscription='none'/>
  </pubsub>
</message>
    

8.8 Manage Affiliations

A service MAY allow a node owner to edit the affiliations of entities associated with a given node and to set affiliations for new entities; if so, it MUST advertise support for the "pubsub#modify-affiliations" feature.

In order to request a list of all affiliated entities, a node owner MUST send an affiliations request, consisting of an <affiliations/> element whose 'node' attribute specifies the NodeID of the relevant node.

Example 178. Owner requests all affiliated entities

<iq type='get'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='ent1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <affiliations node='princely_musings'/>
  </pubsub>
</iq>
    

If no error occurs, the service MUST return the list of entities whose affiliation is "owner", "publisher", or "outcast" (it MUST NOT return entities whose affiliation is "none").

Example 179. Service returns list of affiliated entities

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='ent1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <affiliations node='princely_musings'>
      <affiliation jid='hamlet@denmark.lit' affiliation='owner'/>
      <affiliation jid='polonius@denmark.lit' affiliation='outcast'/>
    </affiliations>
  </pubsub>
</iq>
    

There are several reasons why the affiliated entities request might fail:

  1. The service does not support modification of affiliations.
  2. The requesting entity does not have sufficient privileges to modify affiliations.
  3. The specified node does not exist.

These error cases are described more fully below.

If an implementation does not support modification of affiliations, it MUST return a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "modify-affiliations".

Example 180. Node or service does not support affiliation management

<iq type='error'
    from='pubsub.shakespeare.lit'
    id='purge1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <affiliations node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='modify-affiliations'/>
  </error>
</iq>
    

If the requesting entity is not a node owner, the service MUST return a <forbidden/> error.

Example 181. Entity is not an owner

<iq type='error'
    from='pubsub.shakespeare.lit'
    id='ent1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <affiliations node='princely_musings'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the node does not exist, the service MUST return an <item-not-found/> error.

Example 182. Node does not exist

<iq type='error'
    from='pubsub.shakespeare.lit'
    id='purge1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <affiliations node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

Upon receiving the affiliations list, the node owner MAY modify affiliations. The owner MUST send only modified affiliations (i.e., a "delta"), not the complete list. (Note: If the 'affiliation' attribute is not specified in a modification request, then the value MUST NOT be changed.)

Example 183. Owner modifies affiliations

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='ent2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <affiliations node='princely_musings'/>
      <affiliation jid='hamlet@denmark.lit' affiliation='owner'/>
      <affiliation jid='polonius@denmark.lit' affiliation='none'/>
      <affiliation jid='bard@shakespeare.lit' affiliation='publisher'/>
    </affiliations>
  </pubsub>
</iq>
    

Example 184. Service responds with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    id='ent2'/>
    

In order to remove an entity from the affiliations list, the owner MUST set the value of the 'affiliation' attribute to "none" and the service MUST remove that entity from the affiliations list and not return it in response to future list requests.

The owner MAY change multiple affiliations in a single request. If one of the entity elements specified is invalid, the service MUST return an IQ error (which SHOULD be <not-acceptable/>) with the invalid entries, where the affiliation returned is the original, un-altered affiliation.

The following example shows an entity attempting to make the owner something other than an affiliation of "owner", an action which MUST NOT be allowed if there is only one owner.

Example 185. Owner sets affiliation for multiple entities

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='ent3'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <affiliations node='princely_musings'>
      <affiliation jid='hamlet@denmark.lit' affiliation='none'/>
      <affiliation jid='polonius@denmark.lit' affiliation='none'/>
      <affiliation jid='bard@shakespeare.lit' affiliation='publisher'/>
    </affiliations>
  </pubsub>
</iq>
    

Example 186. Service responds with an error

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='ent3'/>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <affiliations node='princely_musings'>
      <affiliation jid='hamlet@denmark.lit' affiliation='owner'/>
    </affiliations>
  </pubsub>
  <error type='modify'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

The state chart at the beginning of this document is a MUST-IMPLEMENT set of rules for checking possible state transitions. Implementations MAY enforce other (more strict) rules. If errors occur during a modification request for multiple entities, the pubsub service MUST return any <affiliate/> element(s) which caused the error. Returned entities which failed to be modified MUST include the existing 'affiliation' attribute. Any entity elements which are not returned in an IQ error case MUST be treated as successful modifications. The owner MUST NOT specify multiple <affiliate/> elements for the same entity; otherwise the service MUST return a <bad-request/> error.

An implementation MAY send a message to an entity whose affiliation has changed, which MAY contain a <body/> element specifying natural-language text regarding the affiliation change and which SHOULD contain the modified affiliation data.

Example 187. Service sends notification of affiliation change

<message from='pubsub.shakespeare.lit' to='polonius@denmark.lit'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <affiliations node='princely_musings'>
      <affilation jid='polonius@denmark.lit' affiliation='none'/>
    </affiliations>
  </pubsub>
</message>
    

9. Collection Nodes

A pubsub service MAY support collection nodes as well as leaf nodes. Collections enable nodes to be grouped together in any way, including hierarchies and directed acyclic graphs. Collections MUST contain only leaf nodes and/or other collections. Collections MUST NOT contain published items, since only leaf nodes are allowed to contain items (therefore a collection MUST NOT support the "publish" feature or related features such as "persistent-items"). If collections are supported, a service MUST advertise that fact in its "disco#info" responses by including a feature of "pubsub#collections" and MUST support service discovery of child nodes as described in the Discover Nodes section of this document.

9.1 Subscribe to a Collection Node

A service that implements collection nodes SHOULD allow entities to subscribe to collection nodes (subject to access models and local security policies).

In addition to the subscription configuration options already defined, there are two subscription configuration options specific to collection nodes:

In order to subscribe to a collection node, an entity MUST send a subscription request to the node; the subscription request MAY include subscription options, but this is not strictly necessary (especially if the entity does not wish to override the default settings for the "pubsub#subscription_type" and "pubsub#subscription_depth" options).

Example 188. Entity subscribes to a collection node (no configuration)

<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='collsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe jid='francisco@denmark.lit'
               node='blogs'/>
   </pubsub>
</iq>
    

The subscriber will now receive notification of new first-level nodes created within the "blogs" collection.

Example 189. Entity subscribes to a collection node (with configuration)

<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='collsub2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe jid='francisco@denmark.lit'
               node='blogs'/>
    <options>
      <x xmlns='jabber:x:data'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
        </field>
        <field var='pubsub#subscription_type'>
          <value>items</value>
        </field>
        <field var='pubsub#subscription_depth'>
          <value>all</value>
        </field>
      </x>
   </options>
 </pubsub>
</iq>
    

The subscriber will now receive item notifications from nodes at any depth within the "blogs" collection.

Depending on the nature of the node "tree", a subscription type of "items" and depth of "all" may result in an extremely large number of notifications. Therefore, a service MAY disallow such a combination of subscription options, in which case it MUST return a <not-allowed/> error to the requesting entity.

A service MAY allow an entity to subscribe to a collection node in two ways, once with a subscription of type "nodes" (to receive notification of any new nodes added to the collection or the entire tree) and one or more times with a subscription of type "items" (to receive all items published within the tree). However, a service SHOULD NOT allow an entity to subscribe twice to a collection node (once with a subscription depth of "1" and once with a subscription depth of "all") for the same subscription type, since two such subscriptions are unnecessary (a depth of "all" includes by definition a depth of "1"); in this case the service MUST return a <conflict/> error to the requesting entity.

9.2 Root Collection Node

A service that implements collections SHOULD support a root collection. The root collection shall be identified by the lack of a node identifier (i.e., the address of the pubsub service itself, such as "pubsub.shakespeare.lit").

Subscribing to this node with a subscription of type "nodes" and a depth of "1" enables an entity to be notified whenever a new first-level node is created at the pubsub service. Subscribing to this node with a subscription of type "nodes" and a depth of "all" enables an entity to be notified whenever a new node is created anywhere at the pubsub service.

Example 190. Entity subscribes to the root collection node

<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='root1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe jid='francisco@denmark.lit'/>
 </pubsub>
</iq>
    

In order to send notification of new nodes, the service shall send an event that contains a <collection/> element that in turns contains a <node/> element whose 'id' attribute specifies the NodeID of the new node.

Example 191. Notification of new node

<message from='pubsub.shakespeare.lit'
         to='francisco@denmark.lit'
         id='newnode1'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <collection>
      <node id='new-node-id'>
    </collection>
  </event>
</message>
    

The notification event MAY also include the node meta-data, formatted using the Data Forms protocol.

Example 192. Notification of new node

<message from='pubsub.shakespeare.lit'
         to='francisco@denmark.lit'
         id='newnode2'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <collection>
      <node id='new-node-id'>
        <x xmlns='jabber:x:data' type='result'>
          <field var='FORM_TYPE' type='hidden'>
            <value>http://jabber.org/protocol/pubsub#meta-data</value>
          </field>
          <field var='pubsub#creation_date'><var>2003-07-29T22:56Z</var></field>
          <field var='pubsub#creator'><var>hamlet@denmark.lit</var></field>
          <field var='pubsub#description'><var>Atom feed for my blog.</var></field>
          <field var='pubsub#language'><var>en</var></field>
          <field var='pubsub#contact'><value>bard@shakespeare.lit</value></field>
          <field var='pubsub#owner'><value>hamlet@denmark.lit</value></field>
          <field var='pubsub#title'><var>Princely Musings (Atom).</var></field>
          <field var='pubsub#type'><value>http://www.w3.org/2005/Atom</value></field>
        </x>
      </node>
    </collection>
  </event>
</message>
    

9.3 Create a New Collection Node

To create a new collection node, the requesting entity MUST include a Data Form containing a 'pubsub#node_type' field whose <value/> is "collection".

Example 193. Entity requests a new collection node

<iq type='set'
    from='bard@shakespeare.lit/globe'
    to='pubsub.shakespeare.lit'
    id='create3'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='announcements'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        <field var='pubsub#node_type'><value>collection</value></field>
      </x>
    </configure>
  </pubsub>
</iq>
    

Example 194. Service responds with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='bard@shakespeare.lit/globe'
    id='create3'/>
    

In addition to the errors already defined for leaf node creation, there are several reasons why the collection node creation request might fail:

  1. The service does not support collection nodes.
  2. The service does not support creation of collection nodes.
  3. The requesting entity does not have sufficient privileges to create collection nodes.

These error cases are described more fully below.

If the service does not support collection nodes, it MUST respond with a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "collections".

Example 195. Service does not support collection nodes

<iq type='error'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='config1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='collections'/>
  </error>
</iq>
    

If the service supports collection nodes but does not allow new collection nodes to be created, it MUST respond with a <not-allowed/> error.

Example 196. Service does not allow creation of collection nodes

<iq type='error'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='config1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'/>
  </pubsub>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the requesting entity has insufficient privileges to create new collections, the service MUST respond with a <forbidden/> error.

Example 197. Requesting entity has insufficient privileges to create collection nodes

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='hamlet@denmark.lit/elsinore'
    id='config1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

A service MAY offer some node configuration options that are specific to collection nodes and not provided in configuration forms related to leaf nodes. The following are RECOMMENDED:

9.4 Create a Node Associated with a Collection

To create a new node and associate it with an existing collection, the node configuration protocol MUST be used in the node creation request (see the Create and Configure a Node section of this document). In order to specify the associated collection(s), the form MUST include a 'pubsub#collection' field.

Note: Inclusion of the node configuration form is not necessary if the node is being created as a first-level child of the root collection node, since every such child is automatically affiliated with the root collection node (if any).

Note: For the protocol used to associate an existing node with a collection, refer to the Associate an Existing Node with a Collection section of this document.

Example 198. Entity creates a new node associated with a collection

<iq type='set'
    from='bard@shakespeare.lit/globe'
    to='pubsub.shakespeare.lit'
    id='create4'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='plays'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='pubsub#collection'><value>announcements</value></field>
      </x>
    </configure>
  </pubsub>
</iq>
    

The service then creates the node and associates it with the collection.

Note: If the node is a collection node and the requesting entity wishes to request the default configuration, the requesting entity MUST include only the "pubsub#collection" and "pubsub#node_type" fields in the configuration form.

There are several reasons why the request might fail:

  1. The request specified more than one collection node, but the service allows a node to be associated with only one collection node.
  2. The requesting entity does not have sufficient privileges to associate a node with the specified collection node.
  3. No additional nodes can be associated with the collection node.
  4. The specified collection node is actually a leaf node.
  5. The specified collection node does not exist.

These error cases are described more fully below.

An implementation MAY allow a node to be associated with more than one collection node and therefore MAY specify a type of "text-multi" for the "pubsub#collection" field. However, in order to reduce the complexity of implementation, it is RECOMMENDED to allow only one parent collection node for each node and therefore it is RECOMMENDED to specify a type of "text-single" for the "pubsub#collection" field. If a service supports associating a node with multiple collections, it MUST advertise support for the "multi-collection" feature (if that feature is not advertised, entities SHOULD assume that the service allows a node to be associated with only one collection). If the request specifies more than one collection node but the service allows a node to be associated with only one collection node, the service MUST return a <bad-request/> error.

Example 199. Too many collection nodes

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='bard@shakespeare.lit/globe'
    id='create4'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='plays'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='pubsub#collection'>
          <value>announcements</value>
          <value>news</value>
        </field>
        <field var='pubsub#node_type'>
          <value>collection</value>
        </field>
      </x>
    </configure>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the requesting entity does not have sufficient privileges to associate a node with the specified collection node, the service MUST return a <forbidden/> error.

Example 200. Insufficient privileges

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='bard@shakespeare.lit/globe'
    id='create4'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='plays'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='pubsub#collection'><value>announcements</value></field>
      </x>
    </configure>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If no additional nodes can be associated with the collection node because a configurable limit of associated nodes has been reached, the service MUST return a <conflict/> error, which SHOULD also include a pubsub-specific error condition of <max-nodes-exceeded/>.

Example 201. Associated node limit reached

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='bard@shakespeare.lit/globe'
    id='create4'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='plays'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='pubsub#collection'><value>announcements</value></field>
      </x>
    </configure>
  </pubsub>
  <error type='cancel'>
    <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <max-nodes-exceeded xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
    

If the specified collection node is actually a leaf node, the service MUST return an <not-allowed/> error.

Example 202. Collection node is actually a leaf node

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='bard@shakespeare.lit/globe'
    id='create4'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='plays'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='pubsub#collection'><value>announcements</value></field>
      </x>
    </configure>
  </pubsub>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the specified collection node does not exist, the service MUST return an <item-not-found/> error.

Example 203. No such collection node

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='bard@shakespeare.lit/globe'
    id='create4'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='plays'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='pubsub#collection'><value>announcements</value></field>
      </x>
    </configure>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

9.5 Associate an Existing Node with a Collection

Although a node can be associated with a collection when it is created (as described above), it can also be associated with a collection after it has been created. This can be done in two ways:

These methods are described below.

In order to modify the (child) node's "pubsub#collection" configuration field, the owner of the node shall submit a request to edit the node's configuration, receive a configuration form from the service, and then submit a modified configuration form:

Example 204. Node owner modifies node configuration

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='associate1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        ...
        <field var='pubsub#collection'><value>blogs</value></field>
        ...
      </x>
    </configure>
  </pubsub>
</iq>
    

In order to modify the (parent) node's "pubsub#children" configuration field, the owner of the node shall submit a request to edit the node's configuration, receive a configuration form from the service, and then submit a modified configuration form:

Example 205. Node owner modifies node configuration

<iq type='set'
    from='bard@shakespeare.lit/globe'
    to='pubsub.shakespeare.lit'
    id='associate2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='blogs'>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        ...
        <field var='pubsub#children'>
          <value>princely_musings</value>
          <value>kingly_ravings</value>
          <value>starcrossed_stories</value>
          <value>moorish_meanderings</value>
        </field>
        ...
      </x>
    </configure>
  </pubsub>
</iq>
    

9.6 Disassociate a Node from a Collection

A node can be disassociated from a collection after it has been associated (whether at creation time or afterward). This can be done in two ways:

These methods are described below.

In order to modify the (child) node's "pubsub#collection" configuration field, the owner of the node shall submit a request to edit the node's configuration, receive a configuration form from the service, and then submit a modified configuration form:

Example 206. Node owner modifies node configuration

<iq type='set'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='associate1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='princely_musings'>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        ...
        <field var='pubsub#collection'><value></value></field>
        ...
      </x>
    </configure>
  </pubsub>
</iq>
    

Note: To disassociate the node from all collection nodes, the node owner MUST submit an empty <value/> element within the 'pubsub#collection' field as shown in the foregoing example.

In order to modify the (parent) node's "pubsub#children" configuration field, the owner of the node shall submit a request to edit the node's configuration, receive a configuration form from the service, and then submit a modified configuration form:

Example 207. Node owner modifies node configuration

<iq type='set'
    from='bard@shakespeare.lit/globe'
    to='pubsub.shakespeare.lit'
    id='associate2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='blogs'>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        ...
        <field var='pubsub#children'>
          <value>kingly_ravings</value>
          <value>starcrossed_stories</value>
          <value>moorish_meanderings</value>
        </field>
        ...
      </x>
    </configure>
  </pubsub>
</iq>
    

If a node is disassociated from a collection node and a new association is not formed, the implementation MAY associate the node with the root collection node or associate it with no collection node.

Note: The combination of associating and disassociating a node with a collection can be used to move a node from one collection to another.

9.7 Generating Publish Notifications for Collections

If an item is published to a node which is also includeed by a collection, and an entity is subscribed to that collection with a subscription type of "items", then the notifications generated by the service MUST contain additional information. The <items/> element contained in the notification message MUST specify the node identifier of the node that generated the notification (not the collection) and the <item/> element MUST contain a SHIM header that specifies the node identifier of the collection.

Example 208. Subscribers receive notifications from a collection

<message to='francisco@denmark.lit' from='pubsub.shakespeare.lit'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        ...
        <headers xmlns='http://jabber.org/protocol/shim'>
          <header name='pubsub#collection'>blogs</header>
        </headers>
      </item>
    </items>
  </event>
</message>

<message to='bernardo@denmark.lit' from='pubsub.shakespeare.lit'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        ...
        <headers xmlns='http://jabber.org/protocol/shim'>
          <header name='pubsub#collection'>blogs</header>
        </headers>
      </item>
    </items>
  </event>
</message>
.
.
.
    

10. Feature Summary

This section summarizes the features described herein, specifies the appropriate requirements level for each feature (REQUIRED, RECOMMENDED, or OPTIONAL), and provides cross-references to the section of this document in which each feature is described.

Note: The feature names are all of the form "http://jabber.org/protocol/pubsub#name", where "name" is the text specified in the first column below.

Table 9: Service Discovery Features

Name Description Support Section
collections Collection nodes are supported. RECOMMENDED Collection Nodes
config-node Configuration of node options is supported. RECOMMENDED Configure a Node
create-and-configure Simultaneous creation and configuration of nodes is supported. RECOMMENDED Create and Configure a Node
create-nodes Creation of nodes is supported. RECOMMENDED Create a Node
delete-any Any publisher may delete an item (not only the originating publisher). OPTIONAL Delete an Item from a Node
delete-nodes Deletion of nodes is supported. RECOMMENDED Delete a Node
get-pending Retrieval of pending subscription approvals is supported. OPTIONAL Manage Subscription Requests
instant-nodes Creation of instant nodes is supported. RECOMMENDED Create a Node
item-ids Publishers may specify item identifiers. RECOMMENDED  
leased-subscription Time-based subscriptions are supported. OPTIONAL Time-Based Subscriptions (Leases)
manage-subscriptions Node owners may manage subscriptions. OPTIONAL Manage Subscribers
meta-data Node meta-data is supported. RECOMMENDED  
modify-affiliations Node owners may modify affiliations. OPTIONAL Manage Affiliations
multi-collection A single leaf node may be associated with multiple collections. OPTIONAL Create a Node Associated with a Collection and Associate an Existing Node with a Collection
multi-subscribe A single entity may subscribe to a node multiple times. OPTIONAL  
outcast-affiliation The outcast affiliation is supported. RECOMMENDED Affiliations
persistent-items Persistent items are supported. RECOMMENDED  
presence-notifications Presence-based delivery of event notifications is supported. OPTIONAL  
publish Publishing items is supported (note: not valid for collection nodes). REQUIRED Publish an Item to a Node
publisher-affiliation The publisher affiliation is supported. OPTIONAL  
purge-nodes Purging of nodes is supported. OPTIONAL Purge All Node Items
retract-items Item retraction is supported. OPTIONAL Delete an Item from a Node
retrieve-affiliations Retrieval of current affiliations is supported. RECOMMENDED Retrieve Affiliations
retrieve-default Retrieval of default node configuration is supported. RECOMMENDED Request Default Configuration Options
retrieve-items Item retrieval is supported. RECOMMENDED Retrieve Items from a Node
retrieve-subscriptions Retrieval of current subscriptions is supported. RECOMMENDED Retrieve Subscriptions
subscribe Subscribing and unsubscribing are supported. REQUIRED Subscribe to a Node and Unsubscribe from a Node
subscription-options Configuration of subscription options is supported. OPTIONAL Configure Subscription Options
subscription-notifications Notification of subscription state changes is supported. OPTIONAL Notification of Subscription State Changes

11. Error Conditions

Table 10: Error conditions and typical causes

Condition Description
<conflict/> The node already exists.
<feature-not-implemented/> The operation being attempted on a node (or the system) has failed because the service or node does not support the operation; the error SHOULD also specify which feature is unsupported.
<forbidden/> An entity does not have sufficient privileges to perform the action, is requesting an operation for another Jabber ID (e.g., francisco@denmark.lit attempts to subscribe bernardo@denmark.lit to a node), or the requesting entity has an affiliation of "outcast".
<item-not-found/> The node or item specified for some operation does not exist.
<not-allowed/> An entity has attempted to perform an action which the service implements; however the service-wide admin or the node owner has disabled the action for that service or node.
<not-authorized/> An entity has attempted to subscribe to or retrieve items from a node but is not authorized to see the account owner's presence, is not in the appropriate roster group, or is not on the whitelist for subscriptions.
<payment-required/> Subscriptions and item retrieval are based on some kind payment service. Payments would be done out-of-band using some agreed-upon method (not defined herein).
<registration-required/> Entities are required to register before node creation is allowed.

Note: Refer to Error Condition Mappings [21] for more information regarding error syntax.

12. Implementation Notes

12.1 Intended Recipients for Notifications

When a pubsub service generates notifications, it MUST adhere to the delivery rules implicit in the subscription option configuration for each subscriber. In particular, the 'to' address SHOULD be that of the subscribed JID only. The service SHOULD NOT attempt to guess at the most available resource associated with the subscribed JID (e.g., in the context of instant messaging systems).

12.2 Handling Notification-Related Errors

As noted above, a pubsub service SHOULD ensure that the <message/> stanza for each event notification it generates possesses an 'id' attribute with a unique value. (This notification ID is not to be confused with either the node ID or the item ID.) This ID MUST be unique within the context of the pubsub service in order to ensure proper tracking of any delivery-related errors.

Exactly how a service shall handle delivery-related errors is a matter of implementation. In general, such handling is effectively similar to the bounce processing performed by other message delivery systems, such as mail transfer agents and mailing list software. The following are some suggested guidelines regarding the handling of XMPP-specific error conditions in relation to pubsub event notifications (see RFC 3920 and JEP-0086 regarding XMPP error condition semantics):

12.3 Presence-Based Delivery of Events

Implementations of pubsub MAY deliver event notifications only when the subscriber is online. In these cases, the option may be a node configuration option as shown in the examples above. To facilitate this, the pubsub service needs to subscribe to the subscriber's presence and check the subscriber's current presence information before sending any event notifications (as described in RFC 3921). Presence subscriptions MUST be based on the subscribed JID.

12.4 Not Routing Events to Offline Storage

Sending events to users of existing Jabber servers may force event notifications to be routed to offline storage for later delivery (as described in Best Practices for Handling Offline Messages [22]). This may not always be desirable. The possible ways of preventing this behavior include:

12.5 Including a Message Body

If a service understands the semantics for a particular payload type and an entity's subscription is so configured (via the "pubsub#include_body" option), the service SHOULD include an appropriate XMPP <body/> child element along with the payloads it sends in event notifications for a given node, where the body's XML character data summarizes or represents the information contained in the payload (this enables clients that do not understand the payload format to present the appropriate information to an end user). For example, the Atom <summary/> element (see RFC 4287) could be mapped to the XMPP <body/> element. A service MUST NOT provide the "pubsub#include_body" subscription option for a node if it does not have a defined way to transform part or all of the payload format into a sensible message body. A node owner MAY define an XSLT for transforming the payload format into a message body, via the "pubsub#body_xslt" node configuration option.

If the service does not understand the semantics for a particular payload type, it MAY include a <body/> child whose XML character data informs the subscriber that the message contains an event notification (e.g., text such as "This message contains an event notification" would be appropriate).

12.6 Node ID and Item ID Uniqueness

NodeIDs MUST be treated as unique identifiers within the context of a particular pubsub service.

If item identifiers are used, they MUST be treated as unique within the scope of the node. The combination of the NodeID + ItemID MUST be unique within a given service, and MUST specify a single published item at a single node.

If a publisher publishes an item and the ItemID matches that of an existing item, the pubsub service MUST overwrite the existing item and generate a new event notification.

Because it is possible for a node's configuration to change such that ItemIDs are required (e.g., a change from transient to persistent), a service SHOULD use ItemIDs for internal tracking purposes even if it does not include them with the notifications it generates prior to the configuration change.

12.7 Item Caching

A service MAY cache the last item published to a node, even if the node is configured for transient publication (i.e., configured to not persist items). The last published item SHOULD be sent to new subscribers upon successful processing of a subscription request or approval by a node owner.

Note: If a publisher requests Batch Processing of item publications, the concept of "last published item" is undefined; therefore, if information coherence is needed, a publisher SHOULD publish items in separate requests rather than in batch mode.

Note: Particular profiles of the generic publish-subscribe protocol MAY define more stringent requirements regarding the "cache-last-item" feature.

12.8 Batch Processing

A publisher MAY include multiple <item/> elements in a publish request and MAY include multiple <item/> elements in a retract request. This results in "batch processing" of publications or retractions. If the service cannot process any one of the items to be published or retracted, the entire batch MUST fail. Also note that batch publication renders the concept of "last published item" problematic; therefore, if information coherence is needed, a publisher SHOULD publish items in separate requests rather than in batch mode.

12.9 Auto-Subscribing Owners and Publishers

A service MUST allow owners and publishers to subscribe to a node, and to retrieve items from a node even if they are not subscribed. A service MAY auto-subscribe owners and publishers if they are not already subscribed, in which case it SHOULD generate a subscription ID if necessary for the subscription and SHOULD send a notification of successful subscription as described in the Notification of Subscription State Changes section of this document.

12.10 Authorizing Subscription Requests (Pending Subscribers)

How subscription requests are sent to node owners is a matter of implementation. Possibilities include:

An implementation MAY use any of these methods, or some other method not defined herein.

12.11 Notification of Subscription State Changes

Various actions and events may result in changes to a subscription state:

When a subscription state change occurs, a service SHOULD send a message to the (new, former, or denied) subscriber informing it of the change, where the message contains an <event/> element with a single <subscription/> child that specifies the node, JID, and subscription state. The notification MAY contain a <body/> element specifying natural-language text regarding the subscription change. Examples are shown below.

Example 209. Subscription approval notification

<message
    from='pubsub.shakespeare.lit'
    to='horatio@denmark.lit'
    id='approvalnotify1'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <subscription node='princely_musings' jid='horatio@denmark.lit' subscription='subscribed'/>
  </event>
</message>
    

Example 210. Subscription cancellation / denial notification

<message
    from='pubsub.shakespeare.lit'
    to='horatio@denmark.lit'
    id='unsubnotify1'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <subscription node='princely_musings' jid='horatio@denmark.lit' subscription='none'/>
  </event>
</message>
    

If the service has knowledge of the (former or denied) subscriber's presence, it SHOULD send the message to all of the subscriber's resources; if not, it MUST send the message to the subscriber's affiliated JID.

If a service or node supports this feature, it MUST return a feature of "subscription-notifications" in its response to service discovery information requests.

12.12 NodeID Semantics

NodeIDs MAY have semantic meaning in particular profiles, implementations, or deployments of pubsub. However, it is STRONGLY RECOMMENDED that such semantic meaning not be used to encapsulate the hierarchical structure of nodes; instead, node hierarchy SHOULD be encapsulated using collections and their associated child nodes.

12.13 Multiple Node Discovery

A user may publish information that adheres to a certain profile at multiple pubsub nodes, and a potential subscriber may want to discover all of these pubsub nodes. The user may make a list of pubsub nodes publicly available for querying even when the user is offline by using the Service Discovery mechanism for "publishing" items (see Section 4 of JEP-0030). The potential subscriber may then send a "disco#items" request to the user's bare JID (<user@host>), including the 'node' attribute set to the value of the namespace to which the desired information adheres. The user's server then returns a list of pubsub nodes that meet that criterion (with each pubsub node being a separate Service Discovery item). Here is an example.

Example 211. Discovering multiple nodes

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='hamlet@denmark.lit'
    id='multi-1'/>
  <query xmlns='http://jabber.org/protocol/disco#items'
         node='http://www.w3.org/2005/Atom'/>
</iq>

<iq type='result'
    from='hamlet@denmark.lit'
    to='francisco@denmark.lit/barracks'
    id='multi-1'/>
  <query xmlns='http://jabber.org/protocol/disco#items'
         node='http://www.w3.org/2005/Atom'>
    <item jid='pubsub.shakespeare.lit'
          node='princely_musings'
          name='Princely Musings (Atom)'/>
    <item jid='thepub.denmark.lit'
          node='feed-o-rama'
          name='Backup feed'/>
  </query>
</iq>
    

Alternatively, a user may be registered with a server that offers personal eventing services, in which case the user will have one node per namespace as described in JEP-0163.

12.14 Inclusion of SHIM Headers

When SubIDs are used, Stanza Headers and Internet Metadata (SHIM) headers are to be included in order to differentiate notifications sent regarding a particular subscription. The relevant use cases and scenarios are:

The SHIM headers are generated by the node to which the subscriber has a subscription, which may be either a leaf node or a collection node.

SHIM headers are not to be included when the content does not differ based on subscription ID, e.g., when a node sends notification of a configuration change to the node itself, notification that the node has been purged, or notification that the node has been deleted.

12.15 Associating Events and Payloads with the Generating Entity

An implementation MAY enable the node configuration to specify an association between the event notification and the entity to which the published information pertains, but such a feature is OPTIONAL. Here are some possible examples:

Therefore we define three node configuration options:

A node owner MUST NOT define more than one of these options.

An example is shown below.

Example 212. Event notification with extended stanza addressing

<message from='pubsub.shakespeare.lit'
         to='bassanio@merchantofvenice.lit'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='n48ad4fj78zn38st734'>
      <item id='i1s2d3f4g5h6bjeh936'>
        <geoloc xmlns='http://jabber.org/protocol/geoloc'>
          <description>Venice</description>
          <lat>45.44</lat>
          <lon>12.33</lon>
        </geoloc>
      </item>
    </items>
  </event>
  <addresses xmlns='http://jabber.org/protocol/address'>
    <address type='replyto' jid='portia@merchantofvenice.lit'/>
  </addresses>
</message>
    

Alternatively, if a service implements the personal eventing subset of this protocol, the virtual pubsub service is the account owner's bare JID and notifications are sent from that JID; for details, refer to JEP-0163.

12.16 Chaining

The word "chaining" refers to the practice of subscribing one node to another node. For instance, consider a scenario in which the node <pubsub@example.net/NewsBroadcaster> wants to distribute information received from the node "NewsFeed" at <pubsub.example.com>. While it is theoretically possible for <pubsub@example.net/NewsBroadcaster> to directly subscribe to the NewsFeed node (since the former node is directly addressable as a JID), implementations MUST NOT chain nodes in this fashion. Instead, implementations MUST subscribe from the address of the pubsub service rather than the node (in the example shown here, the subscription would be sent from <pubsub@example.net> rather than <pubsub@example.net/NewsBroadcaster>).

12.17 Time-Based Subscriptions (Leases)

In some systems it may be desirable to provide a subscription "leasing" feature in order to expire old or stale subscriptions. Leases can be implemented using configurable subscription options; specifically, when an entity subscribes, the service would require configuration of subscription options and the configuration form would contain a field of "pubsub#expire". This field MUST contain a dateTime (as specified in Jabber Date and Time Profiles [25]).

The leasing process is shown below.

Example 213. Leasing process

<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='lease1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
</iq>

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='lease1'>
  <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>

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='lease2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options node='princely_musings' jid='francisco@denmark.lit'/>
  </pubsub>
</iq>

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='lease2'>
  <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#expire' type='text-single'
               label='Requested lease period'/>
        ...
      </x>
    </options>
  </pubsub>
</iq>

<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='lease3'>
  <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#expire'><value>2006-02-28T11:59Z</value></field>
          ...
        </x>
     </options>
  </pubsub>
</iq>

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='lease3'/>
    

The service MAY send a message to the subscriber when the lease is almost over (e.g., 24 hours before the end of the lease term). This SHOULD be done by sending a <message/> containing an empty pubsub <event/> element and a SHIM header named "pubsub#expire".

Example 214. Service notifies subscriber of impending lease end

<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit/barracks'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'/>
  <headers xmlns='http://jabber.org/protocol/shim'>
    <header name='pubsub#expire'>2006-02-28T23:59Z</header>
  </headers>
</message>
    

When the subscriber wants to renew the lease, it would get the current subscription options, change the value of the "pubsub#expire" field, and submit the new subscription options back to the service. If the new expire value exceeds the maximum value allowed for subscription leases, the service MUST change the value of the field to be the current date/time plus the maximum allowed lease period.

Example 215. Renewing a lease

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='renew1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options node='princely_musings' jid='francisco@denmark.lit'/>
  </pubsub>
</iq>

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='renew1'>
  <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#expire' type='text-single'
               label='Requested lease period'/>
        ...
      </x>
    </options>
  </pubsub>
</iq>

<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='renew2'>
  <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#expire'><value>2006-03-31T23:59Z</value></field>
          ...
        </x>
     </options>
  </pubsub>
</iq>

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='renew2'/>
    

12.18 Content-Based Pubsub Systems

A service MAY enable entities to subscribe to nodes and apply a filter to notifications (e.g., keyword matching such as "send me all news entries from Slashdot that match the term 'Jabber'"). Such a content-based service SHOULD allow an entity to subscribe more than once to the same node and, if so, MUST use subscription identifiers (SubIDs) to distinguish between multiple subscriptions. In order to prevent collisions, a service that supports content-based subscriptions using SubIDs SHOULD generate SubIDs on behalf of subscribers rather than allowing subscribers to set their own SubIDs. [26]

Content-based services SHOULD use subscription options to specify the filter(s) to be applied. Because there many possible filtering mechanisms (many of which may be application-specific), this JEP does not define any such method. However, filtering mechanisms may be defined in separate specifications.

A fictional example of the subscription options configuration process for content-based pubsub is shown below.

Example 216. A content-based subscription

<iq type='set'
    from='marcellus@denmark.lit/castle'
    to='pubsub.shakespeare.lit'
    id='filter1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
</iq>

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='marcellus@denmark.lit/castle'
    id='filter1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscription
        node='princely_musings'
        jid='marcellus@denmark.lit'
        subid='991d7fd1616fd041015064133cd097a10030819e'
        subscription='unconfigured'>
      <subscribe-options>
        <required/>
      </subscribe-options>
    </subscription>
  </pubsub>
</iq>

<iq type='get'
    from='marcellus@denmark.lit/castle'
    to='pubsub.shakespeare.lit'
    id='filter2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options node='princely_musings'
             jid='marcellus@denmark.lit'
             subid='991d7fd1616fd041015064133cd097a10030819e'/>
  </pubsub>
</iq>

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='marcellus@denmark.lit/castle'
    id='filter2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options node='princely_musings'
             jid='marcellus@denmark.lit'
             subid='991d7fd1616fd041015064133cd097a10030819e'>
      <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='http://shakespeare.lit/search#keyword'
               type='text-single'
               label='Keyword to match'/>
        ...
      </x>
    </options>
  </pubsub>
</iq>

<iq type='set'
    from='marcellus@denmark.lit/castle'
    to='pubsub.shakespeare.lit'
    id='filter3'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options node='princely_musings'
             jid='marcellus@denmark.lit'
             subid='991d7fd1616fd041015064133cd097a10030819e'>
        <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='http://shakespeare.lit/search#keyword'><value>peasant</value></field>
          ...
        </x>
     </options>
  </pubsub>
</iq>

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='marcellus@denmark.lit/castle'
    id='filter3'/>
    

The subscriber will then be notified about events that match the keyword.

Example 217. Event notification for matched keyword

<message from='pubsub.shakespeare.lit' to='marcellus@denmark.lit'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <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>
    </items>
  </event>
  <headers xmlns='http://jabber.org/protocol/shim'>
    <header name='pubsub#subid'>991d7fd1616fd041015064133cd097a10030819e</header>
  </headers>
</message>
    

13. Internationalization Considerations

13.1 Field Labels

The Data Forms shown in this specification include English-language labels for various fields; implementations that will display such forms to human users SHOULD provide localized label text for fields that are defined for the registered FORM_TYPEs.

14. Security Considerations

Because the data published to a pubsub node may contain sensitive information (e.g., a user's geolocation), node owners SHOULD exercise care in approving subscription requests. Security considerations regarding particular kinds of information are the responsbility of the using protocol.

A service MUST NOT allow non-owners or other unauthorized entities to complete any actions defined under the Owner Use Cases section of this document.

A service MUST adhere to the defined access model in determining whether to send event notifications or payloads to an entity, or allow an entity to retrieve items from a node. A service MAY enforce additional privacy and security policies when determining whether an entity is allowed to subscribe to a node or retrieve items from a node; however, any such policies shall be considered specific to an implementation or deployment and are out of scope for this document.

15. IANA Considerations

This JEP does not require interaction with the Internet Assigned Numbers Authority (IANA) [27].

16. Jabber Registrar Considerations

16.1 Protocol Namespaces

The Jabber Registrar [28] includes the following namespaces in its registry of protocol namespaces (see <http://www.jabber.org/registrar/namespaces.html>):

16.2 Service Discovery Category/Type

The Jabber Registrar includes a category of "pubsub" in its registry of Service Discovery identities (see <http://www.jabber.org/registrar/disco-categories.html>), as well as three specific types within that category:

Table 11: Service Discovery Types in Pubsub Category

collection A pubsub node of the "collection" type.
leaf A pubsub node of the "leaf" type.
service A pubsub service that supports the functionality defined in JEP-0060. [29]

The registry submission is as follows:

<category>
  <name>pubsub</name>
  <desc>Services and nodes that adhere to JEP-0060.</desc>
  <type>
    <name>collection</name>
    <desc>A pubsub node of the "collection" type.</desc>
    <doc>JEP-0060</doc>
  </type>
  <type>
    <name>leaf</name>
    <desc>A pubsub node of the "leaf" type.</desc>
    <doc>JEP-0060</doc>
  </type>
  <type>
    <name>service</name>
    <desc>A pubsub service that supports the functionality defined in JEP-0060.</desc>
    <doc>JEP-0060</doc>
  </type>
</category>
    

Future submissions to the Jabber Registrar may register additional types.

16.3 Service Discovery Features

The Jabber Registrar maintains a registry of service discovery features (see <http://www.jabber.org/registrar/disco-features.html>), which includes a number of features that may be returned by pubsub services. The following registry submission has been provided to the Jabber Registrar for that purpose.

<var>
  <name>http://jabber.org/protocol/pubsub#collections</name>
  <desc>Collection nodes are supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#config-node</name>
  <desc>Configuration of node options is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#create-and-configure</name>
  <desc>Simultaneous creation and configuration of nodes is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#create-nodes</name>
  <desc>Creation of nodes is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#delete-any</name>
  <desc>Any publisher may delete an item (not only the originating publisher).</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#delete-nodes</name>
  <desc>Deletion of nodes is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#get-pending</name>
  <desc>Retrieval of pending subscription approvals is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#instant-nodes</name>
  <desc>Creation of instant nodes is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#item-ids</name>
  <desc>Publishers may specify item identifiers.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#leased-subscription</name>
  <desc>Time-based subscriptions are supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#meta-data</name>
  <desc>Node meta-data is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#manage-subscription</name>
  <desc>Node owners may manage subscriptions.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#modify-affiliations</name>
  <desc>Node owners may modify affiliations.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#multi-collection</name>
  <desc>A single leaf node may be associated with multiple collections.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#multi-subscribe</name>
  <desc>A single entity may subscribe to a node multiple times.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#outcast-affiliation</name>
  <desc>The outcast affiliation is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#persistent-items</name>
  <desc>Persistent items are supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#presence-notifications</name>
  <desc>Presence-based delivery of event notifications is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#publish</name>
  <desc>Publishing items is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#publisher-affiliation</name>
  <desc>The publisher affiliation is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#purge-nodes</name>
  <desc>Purging of nodes is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#retract-items</name>
  <desc>Item retraction is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#retrieve-affiliations</name>
  <desc>Retrieval of current affiliations is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#retrieve-default</name>
  <desc>Retrieval of default node configuration is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#retrieve-items</name>
  <desc>Item retrieval is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#retrieve-subscriptions</name>
  <desc>Retrieval of current subscriptions is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#subscribe</name>
  <desc>Subscribing and unsubscribing are supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#subscription-options</name>
  <desc>Configuration of subscription options is supported.</desc>
  <doc>JEP-0060</doc>
</var>
<var>
  <name>http://jabber.org/protocol/pubsub#subscription-notifications</name>
  <desc>Notification of subscription state changes is supported.</desc>
  <doc>JEP-0060</doc>
</var>
    

16.4 Field Standardization

JEP-0068 defines a process for standardizing the fields used within Data Forms scoped by a particular namespace, and the Jabber Registrar maintains a registry of such FORM_TYPES (see <http://www.jabber.org/registrar/formtypes.html>). Within pubsub, there are four uses of such forms:

  1. Authorization of subscriptions using the 'http://jabber.org/protocol/pubsub#subscribe_authorization' namespace.
  2. Configuration of subscription options using the 'http://jabber.org/protocol/pubsub#subscribe_options' namespace.
  3. Configuration of a node using the 'http://jabber.org/protocol/pubsub#node_config' namespace.
  4. Setting of meta-data information using the 'http://jabber.org/protocol/pubsub#meta-data' namespace.

The registry submissions associated with these namespaces are defined below.

Note: There is no requirement that configuration fields need to be registered with the Jabber Registrar. However, as specified in Section 3.4 of JEP-0068, names of custom (unregistered) fields MUST begin with the characters "x-" if the form itself is scoped by a registered FORM_TYPE.

16.4.1 pubsub#subscribe_authorization FORM_TYPE

<form_type>
  <name>http://jabber.org/protocol/pubsub#subscribe_authorization</name>
  <jep>JEP-0060</jep>
  <desc>Forms enabling authorization of subscriptions to pubsub nodes</desc>
  <field
      var='pubsub#allow'
      type='boolean'
      label='Whether to allow the subscription'/>
  <field
      var='pubsub#subid'
      type='text-single'
      label='The SubID of the subscription'/>
  <field
      var='pubsub#node'
      type='text-single'
      label='The NodeID of the relevant node'/>
  <field
      var='pubsub#subscriber_jid'
      type='jid-single'
      label='The address (JID) of the subscriber'/>
</form_type>
      

16.4.2 pubsub#subscribe_options FORM_TYPE

<form_type>
  <name>http://jabber.org/protocol/pubsub#subscribe_options</name>
  <jep>JEP-0060</jep>
  <desc>Forms enabling configuration of subscription options for pubsub nodes</desc>
  <field
      var='pubsub#deliver'
      type='boolean'
      label='Whether an entity wants to receive
             or disable notifications'/>
  <field
      var='pubsub#digest'
      type='boolean'
      label='Whether an entity wants to receive digests
             (aggregations) of notifications or all
             notifications individually'/>
  <field var='pubsub#digest_frequency'
         type='text-single'
         label='The minimum number of milliseconds between
                sending any two notification digests'/>
  <field
      var='pubsub#expire'
      type='text-single'
      label='The DateTime at which a leased subscription
             will end or has ended'/>
  <field
      var='pubsub#include_body'
      type='boolean'
      label='Whether an entity wants to receive an XMPP
             message body in addition to the payload
             format'/>
  <field
      var='pubsub#show-values'
      type='list-multi'
      label='The presence states for which an entity
             wants to receive notifications'>
    <option label='XMPP Show Value of Away'>
      <value>away</value>
    </option>
    <option label='XMPP Show Value of Chat'>
      <value>chat</value>
    </option>
    <option label='XMPP Show Value of DND (Do Not Disturb)'>
      <value>dnd</value>
    </option>
    <option label='Mere Availability in XMPP (No Show Value)'>
      <value>online</value>
    </option>
    <option label='XMPP Show Value of XA (Extended Away)'>
      <value>xa</value>
    </option>
  </field>
  <field var='pubsub#subscription_type'
         type='list-single'>
    <option label='Receive notification of new items only'>
      <value>items</value>
    </option>
    <option label='Receive notification of new nodes only'>
      <value>nodes</value>
    </option>
  </field>
  <field var='pubsub#subscription_depth'
         type='list-single'>
    <option label='Receive notification from direct child nodes only'>
      <value>1</value>
    </option>
    <option label='Receive notification from all descendent nodes'>
      <value>all</value>
    </option>
  </field>
</form_type>
      

16.4.3 pubsub#node_config FORM_TYPE

<form_type>
  <name>http://jabber.org/protocol/pubsub#node_config</name>
  <jep>JEP-0060</jep>
  <desc>Forms enabling configuration of pubsub nodes</desc>
  <field var='pubsub#access_model'
         type='list-single'
         label='Who may subscribe and retrieve items'>
    <option label='Subscription requests must be approved and only subscribers may retrieve items'>
      <value>authorize</value>
    </option>
    <option label='Anyone may subscribe and retrieve items'>
      <value>open</value>
    </option>
    <option label='Anyone with a presence subscription of both or from may subscribe and retrieve items'>
      <value>presence</value>
    </option>
    <option label='Anyone in the specified roster group(s) may subscribe and retrieve items'>
      <value>roster</value>
    </option>
    <option label='Only those on a whitelist may subscribe and retrieve items'>
      <value>whitelist</value>
    </option>
  </field>
  <field var='pubsub#body_xslt'
         type='text-single'
         label='The URL of an XSL transformation which can be
                applied to payloads in order to generate an
                appropriate message body element.'/>
  <field var='pubsub#collection'
         type='text-single'
         label='The collection with which a node is affiliated'/>
  <field var='pubsub#dataform_xslt'
         type='text-single'
         label='The URL of an XSL transformation which can be
                applied to the payload format in order to generate
                a valid Data Forms result that the client could
                display using a generic Data Forms rendering
                engine'/>
  <field var='pubsub#deliver_payloads'
         type='boolean'
         label='Whether to deliver payloads with event notifications'/>
  <field var='pubsub#itemreply'
         type='list-single'
         label='Whether owners or publisher should receive replies to items'>
    <option label='Statically specify a replyto of the node owner(s)'>
      <value>owner</value>
    </option>
    <option label='Dynamically specify a replyto of the item publisher'>
      <value>publisher</value>
    </option>
  </field>
  <field var='pubsub#children_association_policy'
         type='list-single'
         label='Who may associate leaf nodes with a collection'>
    <option label='Anyone may associate leaf nodes with the collection'>
      <value>all</value>
    </option>
    <option label='Only collection node owners may associate leaf nodes with the collection'>
      <value>owners</value>
    </option>
    <option label='Only those on a whitelist may associate leaf nodes with the collection'>
      <value>whitelist</value>
    </option>
  </field>
  <field var='pubsub#children_association_whitelist'
         type='jid-multi'
         label='The list of JIDs that may associated leaf nodes with a collection'/>
  <field var='pubsub#children'
         type='text-multi'
         label='The child nodes (leaf or collection) associated with a collection'/>
  <field var='pubsub#children_max'
         type='text-single'
         label='The maximum number of child nodes that can be associated with a collection'/>
  <field var='pubsub#max_items'
         type='text-single'
         label='The maximum number of items to persist'/>
  <field var='pubsub#max_payload_size'
         type='text-single'
         label='The maximum payload size in bytes'/>
  <field var='pubsub#node_type'
         type='list-single'
         label='Whether the node is a leaf (default) or a collection'>
    <option label='The node is a leaf node (default)'>
      <value>leaf</value>
    </option>
    <option label='The node is a collection node'>
      <value>collection</value>
    </option>
  </field>
  <field var='pubsub#notify_config'
         type='boolean'
         label='Whether to notify subscribers when the node configuration changes'/>
  <field var='pubsub#notify_delete'
         type='boolean'
         label='Whether to notify subscribers when the node is deleted'/>
  <field var='pubsub#notify_retract'
         type='boolean'
         label='Whether to notify subscribers when items are removed from the node'/>
  <field var='pubsub#persist_items'
         type='boolean'
         label='Whether to persist items to storage'/>
  <field var='pubsub#presence_based_delivery'
         type='boolean'
         label='Whether to deliver notifications to available users only'/>
  <field var='pubsub#publish_model'
         type='list-single'
         label='The publisher model'>
    <option label='Only publishers may publish'>
      <value>publishers</value>
    </option>
    <option label='Subscribers may publish'>
      <value>subscribers</value>
    </option>
    <option label='Anyone may publish'>
      <value>open</value>
    </option>
  </field>
  <field var='pubsub#replyroom'
         type='jid-multi'
         label='The specific multi-user chat rooms to specify for replyroom'/>
  <field var='pubsub#replyto'
         type='jid-multi'
         label='The specific JID(s) to specify for replyto'/>
  <field var='pubsub#roster_groups_allowed'
         type='list-multi'
         label='The roster group(s) allowed to subscribe and retrieve items'/>
  <field var='pubsub#send_item_subscribe'
         type='boolean'
         label='Whether to send items to new subscribers'/>
  <field var='pubsub#subscribe' type='boolean'
         label='Whether to allow subscriptions'>
    <value>1</value>
  </field>
  <field var='pubsub#title'
         type='text-single'
         label='A friendly name for the node'/>
  <field var='pubsub#type'
         type='text-single'
         label='The type of node data, usually specified by
                the namespace of the payload (if any); MAY
                be list-single rather than text-single'/>
</form_type>
      

16.4.4 pubsub#meta-data FORM_TYPE

<form_type>
  <name>http://jabber.org/protocol/pubsub#meta-data</name>
  <jep>JEP-0060</jep>
  <desc>Forms enabling setting of meta-data information about pubsub nodes</desc>
  <field var='pubsub#contact'
         type='jid-multi'
         label='The JIDs of those to contact with questions'/>
  <field var='pubsub#creation_date'
         type='text-single'
         label='The datetime when the node was created'/>
  <field var='pubsub#creator'
         type='jid-single'
         label='The JID of the node creator'/>
  <field var='pubsub#description'
         type='text-single'
         label='A description of the node'/>
  <field var='pubsub#language'
         type='text-single'
         label='The default language of the node'/>
  <field var='pubsub#num_subscribers'
         type='text-single'
         label='The number of subscribers to the node'/>
  <field var='pubsub#owner'
         type='jid-multi'
         label='The JIDs of those with an affiliation of owner'/>
  <field var='pubsub#publisher'
         type='jid-multi'
         label='The JIDs of those with an affiliation of publisher'/>
  <field var='pubsub#title'
         type='text-single'
         label='The name of the node'/>
  <field var='pubsub#type'
         type='text-single'
         label='Payload type'/>
  </field>
</form_type>
      

16.5 SHIM Headers

The Jabber Registrar includes "pubsub#collection", "pubsub#expire", and "pubsub#subid" in its registry of SHIM headers (see <http://www.jabber.org/registrar/shim.html>). The registry submission is as follows:

<header>
  <name>pubsub#collection</name>
  <desc>The collection via which a notification was received from the originating node.</desc>
  <doc>JEP-0060</doc>
</header>
<header>
  <name>pubsub#expire</name>
  <desc>The DateTime at which a pubsub leased subscription will end or has ended.</desc>
  <doc>JEP-0060</doc>
</header>
<header>
  <name>pubsub#subid</name>
  <desc>A subscription identifer within the pubsub protocol.</desc>
  <doc>JEP-0060</doc>
</header>
    

Future submissions to the Jabber Registrar may register additional SHIM headers that can be used in relation to the pubsub protocol, and such submission may occur without updating this specification.

16.6 URI Query Types

As authorized by XMPP URI Query Components [30], the Jabber Registrar maintains a registry of queries and key-value pairs for use in XMPP URIs (see <http://www.jabber.org/registrar/querytypes.html>).

The "pubsub" querytype is defined herein for interaction with pubsub services, with two keys: (1) "action" (whose defined values are "subscribe" and "unsubscribe") and (2) "node" (to specify a pubsub node).

Example 218. Pubsub Subscribe Action: IRI/URI

xmpp:pubsub.shakespeare.lit?pubsub;action=subscribe;node=princely_musings
    

Example 219. Pubsub Subscribe Action: Resulting Stanza

<iq to='pubsub.shakespeare.lit' type='set'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe node='princely_musings'/>
  </pubsub>
</iq>
    

Example 220. Pubsub Unsubscribe Action: IRI/URI

xmpp:pubsub.shakespeare.lit?pubsub;action=unsubscribe;node=princely_musings
    

Example 221. Pubsub Unsubscribe Action: Resulting Stanza

<iq to='pubsub.shakespeare.lit' type='set'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <unsubscribe node='princely_musings'/>
  </pubsub>
</iq>
    

The following submission registers the "pubsub" querytype.

<querytype>
  <name>pubsub</name>
  <proto>http://jabber.org/protocol/pubsub</proto>
  <desc>enables interaction with a publish-subscribe service</desc>
  <doc>JEP-0060</doc>
  <keys>
    <key>
      <name>action</name>
      <desc>the pubsub action</desc>
      <values>
        <value>
	  <name>subscribe</name>
          <desc>enables subscribing to a pubsub node</desc>
        </value>
        <value>
	  <name>unsubscribe</name>
          <desc>enables unsubscribing from a pubsub node</desc>
        </value>
      </values>
    </key>
    <key>
      <name>node</name>
      <desc>the pubsub node</desc>
    </key>
  </keys>
</querytype>
    

17. XML Schemas

17.1 http://jabber.org/protocol/pubsub

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='http://jabber.org/protocol/pubsub'
    xmlns='http://jabber.org/protocol/pubsub'
    elementFormDefault='qualified'>

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      JEP-0060: http://www.jabber.org/jeps/jep-0060.html
    </xs:documentation>
  </xs:annotation>

  <xs:import
      namespace='jabber:x:data'
      schemaLocation='http://jabber.org/protocol/x-data/x-data.xsd'/>

  <xs:element name='pubsub'>
    <xs:complexType>
      <xs:choice>
        <xs:sequence>
          <xs:element ref='create'/>
          <xs:element ref='configure' minOccurs='0'/>
        </xs:sequence>
        <xs:sequence>
          <xs:element ref='subscribe' minOccurs='0'/>
          <xs:element ref='options' minOccurs='0'/>
        </xs:sequence>
        <xs:choice minOccurs='0'>
          <xs:element ref='affiliations'/>
          <xs:element ref='items'/>
          <xs:element ref='publish'/>
          <xs:element ref='retract'/>
          <xs:element ref='subscription'/>
          <xs:element ref='subscriptions'/>
          <xs:element ref='unsubscribe'/>
        </xs:choice>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:element name='affiliations'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='affiliation' minOccurs='0' maxOccurs='unbounded'/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name='affiliation'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='affiliation' use='required'>
            <xs:simpleType>
              <xs:restriction base='xs:NCName'>
                <xs:enumeration value='outcast'/>
                <xs:enumeration value='owner'/>
                <xs:enumeration value='publisher'/>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
          <xs:attribute name='node' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='configure'>
    <xs:complexType>
      <xs:choice minOccurs='0' xmlns:xdata='jabber:x:data'>
        <xs:element ref='xdata:x'/>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:element name='create'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='node' type='xs:string' use='optional'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='items'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='item' minOccurs='0' maxOccurs='unbounded'/>
      </xs:sequence>
      <xs:attribute name='max_items' type='xs:positiveInteger' use='optional'/>
      <xs:attribute name='node' type='xs:string' use='required'/>
      <xs:attribute name='subid' type='xs:string' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='item'>
    <xs:complexType>
      <xs:sequence minOccurs='0'>
        <xs:any namespace='##other'/>
      </xs:sequence>
      <xs:attribute name='id' type='xs:string' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='options'>
    <xs:complexType>
      <xs:sequence minOccurs='0'>
        <xs:any namespace='jabber:x:data'/>
      </xs:sequence>
      <xs:attribute name='jid' type='xs:string' use='required'/>
      <xs:attribute name='node' type='xs:string' use='optional'/>
      <xs:attribute name='subid' type='xs:string' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='publish'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='item' minOccurs='0' maxOccurs='unbounded'/>
      </xs:sequence>
      <xs:attribute name='node' type='xs:string' use='required'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='retract'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='item' minOccurs='1' maxOccurs='unbounded'/>
      </xs:sequence>
      <xs:attribute name='node' type='xs:string' use='required'/>
      <xs:attribute name='notify' type='xs:boolean' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='subscribe-options'>
    <xs:complexType>
      <xs:sequence>
        <xs:element name='required' type='empty' minOccurs='0'/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name='subscribe'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='jid' type='xs:string' use='required'/>
          <xs:attribute name='node' type='xs:string' use='optional'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='subscriptions'>
    <xs:complexType>
      <xs:element ref='subscription' minOccurs='0' maxOccurs='unbounded'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='subscription'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='subscribe-options' minOccurs='0'/>
      </xs:sequence>
      <xs:attribute name='jid' type='xs:string' use='required'/>
      <xs:attribute name='node' type='xs:string' use='optional'/>
      <xs:attribute name='subid' type='xs:string' use='optional'/>
      <xs:attribute name='subscription' use='optional'>
        <xs:simpleType>
          <xs:restriction base='xs:NCName'>
            <xs:enumeration value='none'/>
            <xs:enumeration value='pending'/>
            <xs:enumeration value='subscribed'/>
            <xs:enumeration value='unconfigured'/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>

  <xs:element name='unsubscribe'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='jid' type='xs:string' use='required'/>
          <xs:attribute name='node' type='xs:string' use='optional'/>
          <xs:attribute name='subid' type='xs:string' use='optional'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name='empty'>
    <xs:restriction base='xs:string'>
      <xs:enumeration value=''/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>
    

17.2 http://jabber.org/protocol/pubsub#errors

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='http://jabber.org/protocol/pubsub#errors'
    xmlns='http://jabber.org/protocol/pubsub#errors'
    elementFormDefault='qualified'>

  <xs:annotation>
    <xs:documentation>
      This namespace is used for error reporting only, as
      defined in JEP-0060:

      http://www.jabber.org/jeps/jep-0060.html
    </xs:documentation>
  </xs:annotation>

  <xs:element name='closed-node' type='empty'/>
  <xs:element name='configuration-required' type='empty'/>
  <xs:element name='invalid-jid' type='empty'/>
  <xs:element name='invalid-options' type='empty'/>
  <xs:element name='invalid-payload' type='empty'/>
  <xs:element name='invalid-subid' type='empty'/>
  <xs:element name='item-forbidden' type='empty'/>
  <xs:element name='item-required' type='empty'/>
  <xs:element name='jid-required' type='empty'/>
  <xs:element name='max-nodes-exceeded' type='empty'/>
  <xs:element name='nodeid-required' type='empty'/>
  <xs:element name='not-in-roster-group' type='empty'/>
  <xs:element name='not-subscribed' type='empty'/>
  <xs:element name='payload-too-big' type='empty'/>
  <xs:element name='payload-required' type='empty'/>
  <xs:element name='pending-subscription' type='empty'/>
  <xs:element name='presence-subscription-required' type='empty'/>
  <xs:element name='subid-required' type='empty'/>
  <xs:element name='unsupported'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='feature' use='required'>
            <xs:simpleType>
              <xs:restriction base='xs:NCName'>
                <xs:enumeration value='collections'/>
                <xs:enumeration value='config-node'/>
                <xs:enumeration value='create-and-configure'/>
                <xs:enumeration value='create-nodes'/>
                <xs:enumeration value='delete-any'/>
                <xs:enumeration value='delete-nodes'/>
                <xs:enumeration value='get-pending'/>
                <xs:enumeration value='instant-nodes'/>
                <xs:enumeration value='item-ids'/>
                <xs:enumeration value='leased-subscription'/>
                <xs:enumeration value='manage-subscriptions'/>
                <xs:enumeration value='meta-data'/>
                <xs:enumeration value='modify-affiliations'/>
                <xs:enumeration value='multi-collection'/>
                <xs:enumeration value='multi-subscribe'/>
                <xs:enumeration value='outcast-affiliation'/>
                <xs:enumeration value='persistent-items'/>
                <xs:enumeration value='presence-notifications'/>
                <xs:enumeration value='publish'/>
                <xs:enumeration value='publisher-affiliation'/>
                <xs:enumeration value='purge-nodes'/>
                <xs:enumeration value='retract-items'/>
                <xs:enumeration value='retrieve-affiliations'/>
                <xs:enumeration value='retrieve-default'/>
                <xs:enumeration value='retrieve-items'/>
                <xs:enumeration value='retrieve-subscriptions'/>
                <xs:enumeration value='subscribe'/>
                <xs:enumeration value='subscription-options'/>
                <xs:enumeration value='subscription-notifications'/>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
  <xs:element name='unsupported-access-model' type='empty'/>

  <xs:simpleType name='empty'>
    <xs:restriction base='xs:string'>
      <xs:enumeration value=''/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>
    

17.3 http://jabber.org/protocol/pubsub#event

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='http://jabber.org/protocol/pubsub#event'
    xmlns='http://jabber.org/protocol/pubsub#event'
    elementFormDefault='qualified'>

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      JEP-0060: http://www.jabber.org/jeps/jep-0060.html
    </xs:documentation>
  </xs:annotation>

  <xs:import
      namespace='jabber:x:data'
      schemaLocation='http://jabber.org/protocol/x-data/x-data.xsd'/>

  <xs:element name='event'>
    <xs:complexType>
      <xs:choice minOccurs='0'>
        <xs:element ref='collection'/>
        <xs:element ref='configuration'/>
        <xs:element ref='delete'/>
        <xs:element ref='items'/>
        <xs:element ref='purge'/>
        <xs:element ref='subscription'/>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:element name='collection'>
    <xs:complexType>
      <xs:sequence minOccurs='1'>
        <xs:element ref='node'/>
      </xs:sequence>
      <xs:attribute name='node' type='xs:string' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='configuration'>
    <xs:complexType>
      <xs:sequence minOccurs='0' xmlns:xdata='jabber:x:data'>
        <xs:element ref='xdata:x'/>
      </xs:sequence>
      <xs:attribute name='node' type='xs:string' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='delete'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='node' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='items'>
    <xs:complexType>
      <xs:choice>
        <xs:element ref='item' minOccurs='0' maxOccurs='unbounded'/>
        <xs:element ref='retract' minOccurs='0' maxOccurs='unbounded'/>
      </xs:choice>
      <xs:attribute name='node' type='xs:string' use='required'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='item'>
    <xs:complexType>
      <xs:choice minOccurs='0'>
        <xs:any namespace='##other'/>
      </xs:choice>
      <xs:attribute name='id' type='xs:string' use='optional'/>
      <xs:attribute name='node' type='xs:string' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='node'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='id' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='purge'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='node' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='retract'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='id' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='subscription'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='jid' type='xs:string' use='required'/>
          <xs:attribute name='node' type='xs:string' use='optional'/>
          <xs:attribute name='subid' type='xs:string' use='optional'/>
          <xs:attribute name='subscription' use='optional'>
            <xs:simpleType>
              <xs:restriction base='xs:NCName'>
                <xs:enumeration value='none'/>
                <xs:enumeration value='pending'/>
                <xs:enumeration value='subscribed'/>
                <xs:enumeration value='unconfigured'/>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name='empty'>
    <xs:restriction base='xs:string'>
      <xs:enumeration value=''/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>
    

17.4 http://jabber.org/protocol/pubsub#owner

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='http://jabber.org/protocol/pubsub#owner'
    xmlns='http://jabber.org/protocol/pubsub#owner'
    elementFormDefault='qualified'>

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      JEP-0060: http://www.jabber.org/jeps/jep-0060.html
    </xs:documentation>
  </xs:annotation>

  <xs:import
      namespace='jabber:x:data'
      schemaLocation='http://jabber.org/protocol/x-data/x-data.xsd'/>

  <xs:element name='pubsub'>
    <xs:complexType>
      <xs:choice>
        <xs:element ref='affiliations'/>
        <xs:element ref='configure'/>
        <xs:element ref='delete'/>
        <xs:element ref='purge'/>
        <xs:element ref='subscriptions'/>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:element name='affiliations'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='affiliation' minOccurs='0' maxOccurs='unbounded'/>
      </xs:sequence>
      <xs:attribute name='node' type='xs:string' use='required'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='affiliation'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='affiliation' use='required'>
            <xs:simpleType>
              <xs:restriction base='xs:NCName'>
                <xs:enumeration value='none'/>
                <xs:enumeration value='outcast'/>
                <xs:enumeration value='owner'/>
                <xs:enumeration value='publisher'/>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
          <xs:attribute name='jid' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='configure'>
    <xs:complexType>
      <xs:choice minOccurs='0' xmlns:xdata='jabber:x:data'>
        <xs:element ref='xdata:x'/>
      </xs:choice>
      <xs:attribute name='node' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='default'>
    <xs:complexType>
      <xs:choice minOccurs='0' xmlns:xdata='jabber:x:data'>
        <xs:element ref='xdata:x'/>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:element name='delete'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='node' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='purge'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='node' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='subscriptions'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='subscription' minOccurs='0' maxOccurs='unbounded'/>
      </xs:sequence>
      <xs:attribute name='node' type='xs:string' use='required'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='subscription'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='subscription' use='required'>
            <xs:simpleType>
              <xs:restriction base='xs:NCName'>
                <xs:enumeration value='none'/>
                <xs:enumeration value='pending'/>
                <xs:enumeration value='subscribed'/>
                <xs:enumeration value='unconfigured'/>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
          <xs:attribute name='jid' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

</xs:schema>
    

18. Acknowledgements

Thanks to Bob Wyman, Gaston Dombiak, and Matt Tucker for their feedback.

19. Author Note

Peter Millard, primary author of this specification from version 0.1 through version 1.7, died on April 26, 2006. The remaining co-authors are indebted to him for his many years of work on publish-subscribe technologies.


Notes

1. RFC 4287: The Atom Syndication Format <http://www.ietf.org/rfc/rfc4287.txt>.

2. RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core <http://www.ietf.org/rfc/rfc3920.txt>.

3. JEP-0030: Service Discovery <http://www.jabber.org/jeps/jep-0030.html>.

4. JEP-0163: Personal Eventing via Pubsub <http://www.jabber.org/jeps/jep-0163.html>.

5. RFC 3921: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence <http://www.ietf.org/rfc/rfc3921.txt>.

6. JEP-0045: Multi-User Chat <http://www.jabber.org/jeps/jep-0045.html>.

7. These nodes are equivalent to those used in JEP-0030: Service Discovery.

8. JEP-0055: Jabber Search <http://www.jabber.org/jeps/jep-0055.html>.

9. JEP-0004: Data Forms <http://www.jabber.org/jeps/jep-0004.html>.

10. JEP-0128: Service Discovery Extensions <http://www.jabber.org/jeps/jep-0128.html>.

11. JEP-0068: Field Data Standardization for Data Forms <http://www.jabber.org/jeps/jep-0068.html>.

12. The Dublin Core Metadata Initiative (DCMI) is an organization dedicated to promoting the widespread adoption of interoperable metadata standards. For further information, see <http://www.dublincore.org/>.

13. The value SHOULD be a DateTime as defined in JEP-0082, and MUST conform to one of the profiles defined therein.

14. The pubsub type SHOULD be the namespace that defines the payload (such as 'http://www.w3.org/2005/Atom'), if payloads are supported.

15. JEP-0091: Delayed Delivery <http://www.jabber.org/jeps/jep-0091.html>.

16. In accordance with Section 3.2.2.1 of XML Schema Part 2: Datatypes, the allowable lexical representations for the xs:boolean datatype are the strings "0" and "false" for the concept 'false' and the strings "1" and "true" for the concept 'true'; implementations MUST support both styles of lexical representation.

17. JEP-0059: Result Set Manipulation <http://www.jabber.org/jeps/jep-0059.html>.

18. JEP-0131: Stanza Headers and Internet Metadata (SHIM) <http://www.jabber.org/jeps/jep-0131.html>.

19. In accordance with Section 3.2.2.1 of XML Schema Part 2: Datatypes, the allowable lexical representations for the xs:boolean datatype are the strings "0" and "false" for the concept 'false' and the strings "1" and "true" for the concept 'true'; implementations MUST support both styles of lexical representation.

20. JEP-0050: Ad-Hoc Commands <http://www.jabber.org/jeps/jep-0050.html>.

21. JEP-0086: Error Condition Mappings <http://www.jabber.org/jeps/jep-0086.html>.

22. JEP-0160: Best Practices for Handling Offline Messages <http://www.jabber.org/jeps/jep-0160.html>.

23. JEP-0079: Advanced Message Processing <http://www.jabber.org/jeps/jep-0079.html>.

24. JEP-0080: User Geolocation <http://www.jabber.org/jeps/jep-0080.html>.

25. JEP-0082: Jabber Date and Time Profiles <http://www.jabber.org/jeps/jep-0082.html>.

26. Another way to implement content-based subscriptions is to host one node per keyword or other filter; however, this is likely to require an extremely large number of nodes.

27. The Internet Assigned Numbers Authority (IANA) is the central coordinator for the assignment of unique parameter values for Internet protocols, such as port numbers and URI schemes. For further information, see <http://www.iana.org/>.

28. The Jabber Registrar maintains a list of reserved Jabber protocol namespaces as well as registries of parameters used in the context of protocols approved by the Jabber Software Foundation. For further information, see <http://www.jabber.org/registrar/>.

29. Prior to version 1.5 of JEP-0060, this type was called "generic".

30. JEP-0147: XMPP URI Query Components <http://www.jabber.org/jeps/jep-0147.html>.


Revision History

Version 1.8 (2006-06-27)

(psa)

Version 1.7 (2005-03-03)

(psa/rm)

Version 1.6 (2004-07-13)

Added service discovery features for pubsub#meta-data, and pubsub#retrieve-items. Added pubsub#subscription_depth configuration option. Specified pubsub-specific error condition elements qualified by pubsub#errors namespace.

(pgm/psa)

Version 1.5 (2004-07-07)

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 Jabber Registrar submissions. Corrected schemas.

(pgm/psa)

Version 1.4 (2004-06-22)

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.

(pgm)

Version 1.3 (2004-04-25)

Editorial review; added one implementation note.

(psa)

Version 1.2 (2004-03-09)

Added XMPP error handling.

(psa)

Version 1.1 (2004-01-14)

Added Jabber Registrar Considerations subsection for Service Discovery category/type registration.

(psa)

Version 1.0 (2003-10-28)

Per a vote of the Jabber Council, advanced status to Draft.

(psa)

Version 0.16 (2003-10-23)

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.

(pgm)

Version 0.15 (2003-10-21)

Fixed invalid XML in examples for subscription deny/allow.

(pgm)

Version 0.14 (2003-10-21)

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.

(pgm)

Version 0.13 (2003-09-30)

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.

(pgm)

Version 0.12 (2003-08-13)

Defined public vs. private nodes; described how changes to existing nodes might trigger meta-node events (e.g., configuration changes); changed <x/> to <event/> for #events namespace; added meta-data about meta-nodes; fully defined Jabber Registrar considerations.

(pgm/psa)

Version 0.11 (2003-06-25)

Removed subscription notifications since they have inherent issues. Removed empty implementation note sub-section.

(pgm)

Version 0.10 (2003-06-11)

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.

(pgm)

Version 0.9 (2003-04-30)

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.

(pgm)

Version 0.8 (2003-04-03)

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 Jabber Registrar and the meta NodeIDs. Added authorization notes to subscription options.

(pgm)

Version 0.7 (2003-02-14)

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.

(pgm)

Version 0.6 (2003-02-06)

Added more details and an example about publishing without NodeID. Added more implementation notes about NodeIDs and persistent storage.

(pgm)

Version 0.5 (2003-01-22)

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.

(pgm)

Version 0.4 (2003-01-21)

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 Jabber Registrar for the features show. Added text explaining the max_items attribute. Changed "last items" to "most recent items". Removed default configuration acceptance -- owners should just cancel. Added the notify_retract configuration option. Clarified error handling for affiliation modifications.

(pgm)

Version 0.3 (2003-01-20)

Added subscription attribute for entities. Removed subscriber from the affiliations table. Clarified configuration details. Clarified JabberID usages. Added Jabber Registrar Considerations. Added link to JEP-0068 about the FORM_TYPE element in subscription request notifications. Fixed some typos in examples. Added unsupported configuration namespace to example. Added a default configuration example.

(pgm)

Version 0.2 (2003-01-02)

Added numerous implementation notes; added get-pending action with regard to subscriptions; added error table; changed purge and delete to use IQ type='set'.

(pgm)

Version 0.1 (2002-11-19)

Initial version.

(pgm)


END