例子 130. 实体请求一个即时节点
<iq type='set' from='hamlet@denmark.lit/elsinore' to='pubsub.shakespeare.lit' id='create2'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <create/> </pubsub> </iq>
如果没有发生错误, pubsub服务应该创建该节点, 生成一个那个服务上下文中唯一的NodeID, 并通知该用户成功了(应答中包含该NodeID).
例子 131. 服务应答成功和生成的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>
注意: 当一个服务代表请求实体成功创建一个节点, 它必须返回一个 IQ result (根据 XMPP Core). 如果该节点创建请求未指定一个NodeID且服务支持创建即时节点, 该服务必须在该 IQ result 中指定已创建的NodeID. 类似的, 如果该节点创建请求指定了一个NodeID但是服务在创建该节点之前修改了该NodeID, 该服务必须也在 IQ result 中指定已修改的节点. 在所有其他情况下, 该服务可以在该 IQ result 中指定NodeID但是节点创建者不能(MUST NOT)依赖从服务接收到它(因为节点创建者能通过跟踪 IQ-set 指定的'id'属性来确定哪个节点被创建了).
以缺省配置创建一个节点
如上文解释的, 每个节点有它自己的缺省配置. 通过以缺省配置向服务请求创建一个节点, 该节点创建者接受缺省配置. 如果服务允许节点配置, 所有者可以在创建节点之后重新配置该节点(如本文的配置节点所述). 另外, 一个服务可以允许实体在创建节点之前为一个给定的节点类型决定缺省配置(如本文的请求缺省配置所述).
为了以缺省配置创建一个节点, 节点创建者可以简单的包含一个空的<create/>子元素.
在以下例子中, 节点创建者以一个公开访问模式(假定是该服务的缺省类型)请求一个叶子节点(缺省类型).
例子 132. 实体以(缺省的)公开访问模式请求叶子节点
<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'/> </pubsub> </iq>
注意: 'pubsub#node_type' 配置字段的的缺省设置是"leaf".
为了向服务请求一个不同于缺省的访问模式, 该节点创建者必须在节点创建请求中包含一个数据表单来为 'pubsub#access_model' 字段指定一个非缺省的值.
例子 133. 实体以非缺省访问模式请求叶子节点
<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>
如果该访问模式是被支持的并且没有发生常规或方法特有的错误, 服务应该创建该节点并通知请求实体成功.
例子 134. 服务通知请求实体成功
<iq type='result' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='create1'/>
如果服务不支持指定的访问模式, 它必须返回一个<not-acceptable/>错误, 指定一个pubsub特有的错误条件<unsupported-access-model/>.
例子 135. 服务不支持指定的访问模式
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='create2'> <error type='modify'> <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <unsupported-access-model xmlns='http://jabber.org/protocol/pubsub#errors'/> </error> </iq>
(对于如果服务不支持指定的节点类型的错误处理, 参考 XEP-0248 .)
创建并配置节点
如果一个实现允许节点配置(见本文的配置节点), 它应该允许创建请求在节点创建请求中包含期望的节点配置.
注意: <configure/>元素必须跟随<create/>元素且不能(MUST NOT)拥有 'node' 属性, 因为<create/>元素的 'node' 属性的值指定了期望的NodeID; 如果这些规则中的任何一个规则被违反了, 该服务必须返回一个<bad-request/>错误.
例子 136. 实体以非缺省配置请求一个新节点
<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_notifications'><value>1</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#item_expire'><value>604800</value></field> <field var='pubsub#access_model'><value>open</value></field> <field var='pubsub#publish_model'><value>publishers</value></field> <field var='pubsub#purge_offline'><value>0</value></field> <field var='pubsub#send_last_published_item'><value>never</value></field> <field var='pubsub#presence_based_delivery'><value>false</value></field> <field var='pubsub#notification_type'><value>headline</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#notify_sub'><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>
例子 137. 服务应答成功
<iq type='result' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='create1'/>
如果一个服务支持这个 "create-and-configure" 特性, 它必须在对服务查询信息请求的应答中通过返回一个特性 "http://jabber.org/protocol/pubsub#create-and-configure" 来声明那一事实. 如果 create-and-configure 选项不被支持但是请求实体还是发送了这样一个请求, 服务应该忽略该请求的配置部分而当成没有包含这些配置一样处理.
配置节点
在创建了一个新节点之后, 该节点所有者可能想修改该节点的配置. 推荐支持这个特性.
请求
例子 138. 所有者请求配置表单
<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>
成功场景
如果没有发生错误, 服务器必须返回一个配置表单给该节点所有者, 它应该包含当前的节点配置作为缺省值.
注意: 接下来的例子展示了一些可以提供的可能的配置选项. 如果一个实现使用 数据表单 协议实现了这些特性, 那个实现必须使用已经注册到XMPP注册处的和 'http://jabber.org/protocol/pubsub' 命名空间相关的字段(那些字段变量的初步表述见下文以及本文的pubsub#node_config FORM_TYPE, 但是不能(MUST NOT)被解释为标准, 因为XMPP注册处可以晚些时候标准化额外的字段而不用改变本文). 一个实现可以选择指定不同的标签, 值, 以及甚至字段类型, 但必须遵循已定义的变量名scheme.
例子 139. 服务应答配置表单
<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_notifications' type='boolean' label='Whether to deliver event notifications'> <value>true</value> </field> <field var='pubsub#deliver_payloads' type='boolean' label='Whether to 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#notify_sub' type='boolean' label='Notify owners about new subscribers and unsubscribes'> <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#item_expire' type='text-single' label='Time after which to automatically purge items'> <value>604800</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#purge_offline' type='boolean' label='Purge all items when the relevant publisher goes offline?'> <value>0</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_last_published_item' type='list-single' label='When to send the last published item'> <option label='Never'><value>never</value></option> <option label='When a new subscription is processed'><value>on_sub</value></option> <option label='When a new subscription is processed and whenever a subscriber comes online'> <value>on_sub_and_presence</value> </option> <value>never</value> </field> <field var='pubsub#presence_based_delivery' type='boolean' label='Deliver event notifications only to available users'> <value>0</value> </field> <field var='pubsub#notification_type' type='list-single' label='Specify the delivery style for event notifications'> <option><value>normal</value></option> <option><value>headline</value></option> <value>headline</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>
错误场景
有很多原因可能导致节点配置请求失败:
- 服务不支持节点配置.
- 请求实体没有足够权限配置该节点.
- 请求未指定一个节点.
- 节点没有配置选项.
- 指定的节点不存在.
这些错误场景的完整描述在下面章节.
不支持节点配置
如果服务不支持节点配置, 该服务必须返回一个<feature-not-implemented/>错误, 指定一个pubsub特有的错误条件<unsupported/>和一个特性 "config-node" .
例子 140. 服务不支持节点配置
<iq type='error' from='hamlet@denmark.lit/elsinore' to='pubsub.shakespeare.lit' id='config1'> <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>
权限不足
如果请求实体没有足够权限去配置该节点, 服务必须应答一个<forbidden/>错误.
例子 141. 请求实体被禁止配置该节点
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='config1'> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
要求NodeID
如果请求未指定一个节点, 服务应该返回一个<bad-request/>错误. 有可能不包含一个NodeID是因为请求实体向根节点请求配置; 无论如何, 如果请求实体不是一个服务器范围的管理员, 最好返回<bad-request/>而不是<forbidden/>.
例子 142. 请求未指定一个节点
<iq type='error' from='hamlet@denmark.lit/elsinore' to='pubsub.shakespeare.lit' id='config1'> <error type='modify'> <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <nodeid-required xmlns='http://jabber.org/protocol/pubsub#errors'/> </error> </iq>
无配置选项
如果没有配置选项可用(例如, 因为节点配置"被封止了"), 该服务必须返回一个<not-allowed/>错误给所有者.
例子 143. 节点无配置选项
<iq type='error' from='hamlet@denmark.lit/elsinore' to='pubsub.shakespeare.lit' id='config1'> <error type='cancel'> <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
节点不存在
如果节点不存在, 服务必须返回一个<item-not-found/>错误.
例子 144. 节点不存在
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='config1'> <error type='cancel'> <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
表单提交
在接收到配置表单之后, 所有者应该提交一个完成的配置表单.
例子 145. 所有者提交节点配置表单
<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_notifications'><value>1</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#item_expire'><value>604800</value></field> <field var='pubsub#access_model'><value>roster</value></field> <field var='pubsub#roster_groups_allowed'> <value>friends</value> <value>servants</value> <value>courtiers</value> </field> <field var='pubsub#publish_model'><value>publishers</value></field> <field var='pubsub#purge_offline'><value>0</value></field> <field var='pubsub#send_last_published_item'><value>never</value></field> <field var='pubsub#presence_based_delivery'><value>false</value></field> <field var='pubsub#notification_type'><value>headline</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#notify_sub'><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>
替代的, 所有者可以取消配置过程, 在这种情况下必须应用现有的配置.
例子 146. 所有者取消配置过程
<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>
表单处理
成功
如果表单能被成功处理, 服务必须返回一个 IQ-result.
例子 147. 服务应答成功
<iq type='result' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='config2'/>
注意: 如果该节点类型从叶子改成集合且有条目和该节点相关, 服务必须清除节点的所有条目(通知或不通知订阅者).
失败
如果请求的节点配置变更不能被处理(例如, 因为节点所有者尝试修改配置使得它没有节点所有者), 服务必须返回一个<not-acceptable/>错误给所有者.
例子 148. 配置变更不能被处理
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='config2'> <error type='modify'> <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
成功并通知
如果 "pubsub#notify_config" 选项被设为true, 服务必须通知订阅者配置变更. (服务应该为叶子节点支持这个选项,必须为集合节点支持这个选项,如 XEP-0248 所述.) 如果节点配置被设为仅通知, 该通知必须包含一个空的<configuration/>元素,它的'node'属性被设为该节点的NodeID; 如果该节点配置被设为全载荷, <configuration/>元素必须额外包含该节点配置并通过 数据表单 协议展示它.
例子 149. 服务发送配置变更通知(仅事件通知)
<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>
例子 150. 服务发送配置变更通知(带载荷)
<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_notifications'><value>1</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#notify_sub'><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#item_expire'><value>604800</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#purge_offline'><value>0</value></field> <field var='pubsub#max_payload_size'><value>9216</value></field> <field var='pubsub#send_last_published_item'><value>never</value></field> <field var='pubsub#presence_based_delivery'><value>0</value></field> <field var='pubsub#notification_type'><value>headline</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>
请求缺省节点配置选项
一个实体可能希望请求关于缺省节点配置的信息, 例如 为了确定是否执行前文所述的 创建并配置 . 对这个特性的支持是可选的.
请求
要获得节点选项, 该实体必须不带NodeID发送一个空的<default/>元素给服务; 在应答中, 该服务应该返回缺省节点选项.
例子 151. 实体请求缺省节点配置选项
<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>
成功场景
如果没有发生错误, 服务必须返回缺省节点配置选项.
例子 152. 服务应答缺省节点配置选项
<iq type='result' from='pubsub.shakespeare.lit' to='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_notifications' type='boolean' label='Deliver event notifications'> <value>true</value> </field> <field var='pubsub#deliver_payloads' type='boolean' label='Deliver payloads with event notifications'> <value>1</value> </field> <field var='pubsub#description' type='text-single' label='A description of the node'/> <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#notify_sub' type='boolean' label='Notify owners about new subscribers and unsubscribes'> <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#item_expire' type='text-single' label='Time after which to automatically purge items'> <value>604800</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#purge_offline' type='boolean' label='Purge all items when the relevant publisher goes offline?'> <value>0</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_last_published_item' type='list-single' label='When to send the last published item'> <option label='Never'><value>never</value></option> <option label='When a new subscription is processed'><value>on_sub</value></option> <option label='When a new subscription is processed and whenever a subscriber comes online'> <value>on_sub_and_presence</value> </option> <value>never</value> </field> <field var='pubsub#presence_based_delivery' type='boolean' label='Deliver notifications only to available users'> <value>0</value> </field> <field var='pubsub#notification_type' type='list-single' label='Specify the delivery style for notifications'> <option><value>normal</value></option> <option><value>headline</value></option> <value>headline</value> </field> </x> </default> </pubsub> </iq>
错误场景
有很多原因可能导致缺省节点配置选项请求失败:
- 服务不支持节点配置.
- 服务不支持获取缺省节点配置.
这些错误场景的完整描述见下面章节.
不支持节点配置
如果服务不支持节点配置, 它必须返回一个<feature-not-implemented/>错误, 指定一个pubsub特有的错误条件<unsupported/>和一个特性 "config-node" .
例子 153. 服务不支持节点配置
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='def1'> <error type='cancel'> <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <unsupported xmlns='http://jabber.org/protocol/pubsub#errors' feature='config-node'/> </error> </iq>
不支持缺省节点配置获取
如果服务不支持获取缺省节点配置选项, 它必须返回一个<feature-not-implemented/>错误, 指定一个pubsub特有的错误条件<unsupported/>和一个特性 "retrieve-default" .
例子 154. 服务不支持获取缺省节点配置选项
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='def1'> <error type='cancel'> <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <unsupported xmlns='http://jabber.org/protocol/pubsub#errors' feature='retrieve-default'/> </error> </iq>
删除节点
如果一个服务支持节点创建, 它必须支持节点删除. 如果一个实现持久化了条目, 它必须在节点被删除之前从持久化存储删除所有条目.
请求
为了删除一个节点, 一个节点所有者必须发送一个节点删除请求, 包含一个<delete/>元素, 其 'node' 属性指定要被删除的节点的NodeID.
例子 155. 所有者删除一个节点
<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>
该删除请求可以包含包含一个替换节点的URI,请求可以被重定向到那. 典型的这是一个 XMPP URI 或 IRI ,如 PubSub URIs所述, 但是它也可以是一个 HTTP URI 或任何其他形式.
例子 156. 所有者删除一个节点并重定向
<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'> <redirect uri='xmpp:hamlet@denmark.lit?;node=blog'/> </delete> </pubsub> </iq>
对重定向的支持在pubsub服务的部分中是可选的.
成功场景
如果没发生错误, 服务必须通知所有者成功.
例子 157. 服务应答成功
<iq type='result' from='pubsub.shakespeare.lit' id='delete1'/>
另外, 该服务也必须发送节点删除的通知给所有订阅者(它应该包含未决和未配置的订阅).
例子 158. 订阅者被通知节点删除了
<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'> <event xmlns='http://jabber.org/protocol/pubsub#event'> <delete node='princely_musings'> <redirect uri='xmpp:hamlet@denmark.lit?;node=blog'/> </delete> </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'> <redirect uri='xmpp:hamlet@denmark.lit?;node=blog'/> </delete> </event> </message>
错误场景
有很多原因可能导致节点删除失败:
- 请求实体没有足够权限删除该节点.
- 该节点是根集合节点, 它不能被删除(见 XEP-0248 ).
- 指定的节点不存在.
这些错误场景的完整描述见下面章节.
权限不足
如果请求实体没有足够权限删除该节点(例如, 不是一个所有者), 该服务必须返回一个<forbidden/>错误.
例子 159. 实体不是一个所有者
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='delete1'> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
节点不存在
如果请求实体尝试删除一个不存在的节点, 服务必须返回一个<item-not-found/>错误.
例子 160. 所有者尝试删除一个不存在的节点
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='delete1'> <error type='cancel'> <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
清除所有节点条目
如果一个服务持久化了发布的条目, 一个节点所有者可能想清除该节点的所有已发布条目(也就是从持久化存储中移除所有条目, 除了最后发布的条目以外, 它可以被缓存). 实现这个特性对于一个服务是可选的.
请求
为了清除一个节点的所有条目, 一个节点所有者发送一个节点清除请求,包含一个<purge/>元素,它的 'node' 属性指定要被清理的节点的NodeID.
例子 161. 所有者从一个节点清除所有条目
<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>
成功场景
如果没发生错误, 服务必须清理该节点并通知所有者成功了.
例子 162. 服务应答成功
<iq type='result' from='pubsub.shakespeare.lit' id='purge1'/>
如果该节点或服务已经被配置成通知订阅者条目删除了, 一个清除请求不能(MUST NOT)导致发送和删除条目时一样的通知(因为清理一个节点的很多持久化条目可能导致大量的通知); 取而代之的是, 该节点必须发送一个单独的通知给每个订阅者, 包含一个空的<purge/>子元素.
例子 163. 订阅者被通知节点清理了
<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>
错误场景
有很躲原因可能导致节点清理请求失败:
- 该节点或服务不支持节点清理.
- 请求实体没有足够权限清理该节点.
- 该节点未被配置成持久化条目.
- 指定的节点不存在.
这些错误的完整描述在下面章节.
不支持节点清理
如果该节点或服务不支持节点清理, 它必须返回一个<feature-not-implemented/>错误, 指定一个pubsub特有的错误条件<unsupported/>和一个特性 "purge-nodes" .
例子 164. 服务不支持节点清理
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='purge1'> <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>
权限不足
如果请求实体没有足够权限清理该节点(例如, 因为它不是节点所有者), 该服务必须返回一个<forbidden/>错误.
例子 165. 实体不是一个所有者
<iq type='error' from='pubsub.shakespeare.lit' id='purge1'> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
节点未持久化条目
如果该服务或节点未持久化条目(例如, 因为该节点是一个集合节点, 如 XEP-0248 所述), 它必须返回一个<feature-not-implemented/>错误, 指定一个pubsub特有的错误条件<unsupported/>和一个特性 "persistent-items" .
例子 166. 节点未被配置成持久化条目
<iq type='error' from='pubsub.shakespeare.lit' id='purge1'> <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>
节点不存在
如果该节点不存在, 服务必须返回一个<item-not-found/>错误.
例子 167. 节点不存在
<iq type='error' from='pubsub.shakespeare.lit' id='purge1'> <error type='cancel'> <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
管理订阅请求
任何时候一个服务可以发送订阅批准请求给该节点的所有者. 一个订阅批准求情包含一个message节,这个节包含了一个由 "http://jabber.org/protocol/pubsub#subscribe_authorization" FORM_TYPE 限定的数据表单. 这个格式必须包含一个布尔值字段,其 'var' 属性的值为 "pubsub#allow", 这个字段指出是否允许订阅请求. 这个表单应该包含字段来指定节点标识符和未决订阅者的JID. 该message可以包含一个<body/>元素以包含自然语言文本来解释该消息所包含的一个未决订阅表单
例子 168. 服务发送授权请求给节点所有者
<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'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>
为了批准请求, 所有者将提交该表单并把 "pubsub#allow" 字段的值设为 "1" 或 "true"; 为了追踪的目的该message必须反映最初提供的 'id' 属性.
例子 169. 所有者批准订阅请求
<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>
然后服务应该通知被批准的订阅者(见本文的 订阅状态变更通知).
例子 170. 订阅批准通知
<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>
为了禁止请求, 所有者将提交该表单并把 "pubsub#allow" 字段的值设为 "0" 或 "false"; 如上, 该message必须反映最初提供的 'id' .
例子 171. 所有者禁止订阅请求
<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>
然后服务应该通知被禁止的订阅者(见本文的 订阅状态变更通知).
例子 172. 订阅 取消/禁止 通知
<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>
为了取消该表单的提交, 所有者将把表单的 'type' 属性设为 "cancel" 来应答.
例子 173. 所有者取消表单提交
<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>
服务必须检查 "pubsub#allow" 字段来看是否订阅应该被允许或禁止. 如果所有者取消数据表单, 那么该订阅请求必须保持在未决状态.
处理未决订阅请求
一个节点所有者可能想在一个服务上获取它们的节点上的所有未决订阅请求. 对于一个服务来说实现该特性是可选的.
这个特性必须使用Ad-Hoc Commands 21协议来实现, 这里的命令名称(command元素的 'node' 属性)的值必须为 "http://jabber.org/protocol/pubsub#get-pending".
请求
例子 174. 所有者请求未决的请求
<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>
成功场景
如果没发生错误, 服务应该为管理的订阅请求返回一个数据表单, 它必须包含一个单独的字段,其 'var' 属性值为 "pubsub#node" ,其<option/>元素指定请求实体有批准权限的节点们(为了优化, 服务可以只指定那些有未决订阅请求的节点们).
例子 175. 服务以所在的数据表单应答
<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 var='FORM_TYPE' type='hidden'> <value>http://jabber.org/protocol/pubsub#subscribe_authorization</value> </field> <field type='list-single' var='pubsub#node'> <option><value>princely_musings</value></option> <option><value>news_from_elsinore</value></option> </field> </x> </command> </iq>
错误场景
有很多原因可能导致获取未决的订阅批准请求失败:
- 服务不支持 ad-hoc commands 协议.
- 服务支持 ad-hoc commands 但是不支持 "get-pending" 特性.
- 请求实体没有足够权限批准订阅请求.
- 指定的节点不存在.
这些错误场景的完整描述见下面章节.
不支持Ad-Hoc Commands
如果服务不支持ad-hoc commands协议, 它必须应答一个<service-unavailable/>错误.
例子 176. 服务以未找到节点应答
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='pending1'> <error type='cancel'> <service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
不支持Get-Pending
如果服务不支持 "get-pending" 特性, 它必须应该一个<feature-not-implemented/>错误, 指定一个pubsub特有的错误条件<unsupported/>和一个特性 "get-pending".
例子 177. 服务以未找到节点应答
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='pending1'> <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>
权限不足
如果请求实体没有足够权限批准订阅请求, 服务必须返回一个<forbidden/>错误.
例子 178. 实体没有足够权限批准订阅请求
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='pending1'> <error type='cancel'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
节点不存在
如果请求的节点不存在, 服务必须应答一个<item-not-found/>错误.
例子 179. 服务以未找到节点应答
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='pending1'> <error type='cancel'> <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
按节点请求
在接收到管理的订阅请求的数据表单之后, 接着所有者可以获取给定节点的未决订阅批准请求.
例子 180. 所有者获取某个节点的所有未决订阅请求
<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>
如果没发生错误, 服务将应答成功.
例子 181. 服务应答成功
<iq from='pubsub.shakespeare.lit' id='pending2' to='hamlet@denmark.lit/elsinore' type='result'> <command xmlns='http://jabber.org/protocol/commands' sessionid='pubsub-get-pending:20031021T150901Z-600' node='http://jabber.org/protocol/pubsub#get-pending' action='completed'/> </iq>
服务接着将为每个未决的订阅请求发送一个订阅批准消息, 如上文所述的每个单独的未决订阅请求.
注意: 一个服务应该遵循它的从属关系策略来维护一个未决订阅的列表. 特别是, 如果某个带有一个未决订阅的实体的从属关系被修改成所有者或发布者, 服务应该自动批准该订阅请求并把该实体从未决列表中移除之前的请求. 类似的, 如果某个带有一个未决订阅的实体的从属关系被修改成被排斥者, 服务应该自动拒绝该订阅请求并从未决列表中移除该实体之前的请求. (如果一个实体的订阅请求被禁止, 服务应该发送一个<message/>给该实体, 这个message遵循本文的订阅状态变更通知所述的格式.)
管理订阅
一个节点所有者可能想编辑和一个给定节点相关的订阅的列表. 对这个特性("pubsub#manage-subscriptions")的支持是可选的.
获取订阅列表
首先所有者获取订阅列表.
请求
为了请求一个所有订阅的列表, 节点所有者必须发送一个订阅请求, 包含一个<subscriptions/>元素,它的 'node' 属性指定相关节点的NodeID.
例子 182. 所有者请求所有订阅
<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>
成功场景
如果没发生错误, 服务必须返回那些订阅状态为 "subscribed" 或 "unconfigured" 的实体的订阅列表(它不能(MUST NOT)返回订阅状态为 "none" 的实体,不应该(SHOULD NOT)返回订阅状态为 "pending" 的实体). 结果可以为同一个实体(JID)指定多个<subscription/>元素, 但是每个元素必须拥有一个值为唯一的 'subid' 属性(如下所述).
例子 183. 服务返回订阅列表
<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>
错误场景
有很多原因可能导致管理订阅请求失败:
- 服务不支持订阅管理.
- 请求实体没有足够权限管理订阅.
- 指定的节点不存在.
这些错误场景的完整描述见下面章节.
如果一个实现不支持订阅管理, 它必须返回一个<feature-not-implemented/>错误, 指定一个pubsub特有的错误条件<unsupported/>和一个特性 "manage-subscriptions".
例子 184. 节点或服务不支持订阅管理
<iq type='error' from='pubsub.shakespeare.lit' id='purge1'> <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>
如果请求实体不是一个节点所有者, 服务必须返回一个<forbidden/>错误.
例子 185. 实体不是一个所有者
<iq type='error' from='pubsub.shakespeare.lit' id='subman1'> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
如果该节点不存在, 服务必须返回一个<item-not-found/>错误.
例子 186. 节点不存在
<iq type='error' from='pubsub.shakespeare.lit' id='purge1'> <error type='cancel'> <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
修改订阅
请求
在接收到订阅列表之后, 节点所有者可以修改订阅状态. 该所有者必须只发送修改过的订阅状态(即, 一个 "delta"), 而不是完整的列表. (注意: 如果在一个修改请求中未指定 'subscription' 属性, 那么该值不能(MUST NOT)被变更.)
例子 187. 所有者修改订阅
<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>
成功场景
例子 188. 服务应答成功
<iq type='result' from='pubsub.shakespeare.lit' id='subman2'/>
错误场景
有很多原因可能导致修改订阅请求失败:
- 服务不支持订阅管理.
- 请求实体没有足够权限管理订阅.
- 指定的节点不存在.
这些错误场景的完整描述见下面章节.
如果一个实现不支持订阅管理, 它必须返回一个<feature-not-implemented/>错误, 指定一个pubsub特有的错误条件<unsupported/>和一个特性 "manage-subscriptions".
’‘’例子 189. 节点或服务不支持订阅管理
<iq type='error' from='pubsub.shakespeare.lit' id='subman2'> <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>
如果请求实体不是个节点所有者, 该服务必须返回一个<forbidden/>错误.
例子 190. 实体不是一个所有者
<iq type='error' from='pubsub.shakespeare.lit' id='subman1'> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
如果该节点不存在, 服务必须返回一个<item-not-found/>错误.
例子 191. 节点不存在
<iq type='error' from='pubsub.shakespeare.lit' id='subman2'> <error type='cancel'> <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
多重修改
所有者可以在一个请求中变更多个订阅. 如果该实体元素中的一个是非法的, 该服务必须返回一个带着错误条目的 IQ 错误(它应该是<not-acceptable/>), 这里返回的是原始的, 未改变过的订阅.
例子 192. 所有者为多个实体设置订阅
<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>
例子 193. 服务应答一个错误
<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>
如果在一个对多个实体修改的请求中发生错误, pubsub服务必须返回任何导致该错误的<subscription/>元素(们). 返回的修改失败的实体必须包含现有的 'subscription' 属性. 任何未在一个 IQ 错误场景中返回的实体元素必须被视为已经成功修改. 所有者可以为相同实体指定多个<subscription/>元素, 但是每个元素必须拥有一个值为唯一的 'subid' 属性.
删除订阅者
为了从订阅列表移除一个实体, 所有者必须把 'subscription' 属性的值设为 "none" 且服务必须从订阅列表中移除那个实体并在未来的列表请求中不再返回它.
通知订阅者
一个实现应该通知一个实体它的订阅已经改变(见本文的订阅状态变更通知).
例子 194. 服务发送订阅变更通知
<message from='pubsub.shakespeare.lit' to='polonius@denmark.lit'> <event xmlns='http://jabber.org/protocol/pubsub#event'> <subscription node='princely_musings' jid='polonius@denmark.lit' subscription='none'/> </event> </message>
管理从属关系
一个节点可能想管理和一个给定节点相关的实体的从属关系并为新实体设置从属关系. 对此特性("pubsub#modify-affiliations")的支持是可选的.
获取从属关系列表
首先所有者获取从属关系列表.
请求
为了请求一个所有从属的实体的列表, 一个节点所有者必须发送一个从属关系请求, 包含一个<affiliations/>元素,它的 'node' 属性指定相关节点的NodeID.
例子 195. 所有者请求所有从属的实体
<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>
成功场景
如果未发生错误, 该服务必须返回从属关系为 "owner", "member", "publisher", "publish-only", 或 "outcast" 的实体的列表(它不能(MUST NOT)返回从属关系为 "none" 的实体).
例子 196. 服务返回从属的实体的列表
<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>
错误场景
有很多原因可能导致从属实体请求失败:
- 服务不支持从属关系修改.
- 请求实体没有足够权限修改从属关系.
- 指定的节点不存在.
这些错误场景的完整描述见下面章节.
如果一个实现不支持从属关系修改, 它必须返回一个<feature-not-implemented/>错误, 指定一个pubsub特有的错误条件<unsupported/>和一个特性 "modify-affiliations".
例子 197. 节点或服务不支持从属关系管理
<iq type='error' from='pubsub.shakespeare.lit' id='ent1'> <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>
如果请求实体不是一个节点所有者, 服务必须返回一个<forbidden/>错误.
例子 198. 实体不是一个所有者
<iq type='error' from='pubsub.shakespeare.lit' id='ent1'> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
如果该节点不存在, 该服务必须返回一个<item-not-found/>错误.
例子 199. 节点不存在
<iq type='error' from='pubsub.shakespeare.lit' id='ent1'> <error type='cancel'> <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
修改从属关系
一个节点所有者可能想编辑和一个给定节点相关的一个实体的从属关系或为一个新实体设置从属关系.
请求
为了修改一个从属关系, 一个节点所有者必须发送一个 IQ set , 包含要修改的从属关系或从属关系们. 该所有者必须只发送要修改的从属关系(即, 一个 "delta"), 而不是完整的列表 (注意: 如果在一个修改请求中未指定 'affiliation' 属性, 那么其值不能(MUST NOT)被修改.)
例子 200. 所有者修改从属关系
<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='bard@shakespeare.lit' affiliation='publisher'/> </affiliations> </pubsub> </iq>
成功场景
例子 201. 服务应答成功
<iq type='result' from='pubsub.shakespeare.lit' id='ent2'/>
错误场景
有很多原因可能导致修改从属关系请求失败:
- 节点或服务不支持请求的从属关系.
- 服务不支持从属关系修改.
- 请求实体没有足够权限来修改从属关系.
- 指定的节点不存在.
这些错误场景的完整描述在下面章节.
如果一个实现不支持从属关系修改, 它必须返回一个<feature-not-implemented/>错误, 指定一个pubsub特有的错误条件<unsupported/>和一个特性 "modify-affiliations".
例子 202. 节点或服务不支持从属关系管理
<iq type='error' from='pubsub.shakespeare.lit' id='ent1'> <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>
如果节点或服务不支持请求的从属关系, 它必须返回一个<feature-not-implemented/>错误, 指定一个pubsub特有的错误条件<unsupported/>和特性 "member-affiliation", "outcast-affiliation", "publisher-affiliation", 或 "publish-only-affiliation" 之一的适当特性.
例子 203. 节点或服务不支持请求的从属关系
<iq type='error' from='pubsub.shakespeare.lit' id='ent1'> <error type='cancel'> <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <unsupported xmlns='http://jabber.org/protocol/pubsub#errors' feature='member-affiliation'/> </error> </iq>
如果请求实体不是节点所有者, 服务必须返回一个<forbidden/>错误.
例子 204. 实体不是一个所有者
<iq type='error' from='pubsub.shakespeare.lit' id='ent1'> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
如果该节点不存在, 服务必须返回一个<item-not-found/>错误.
例子 205. 节点不存在
<iq type='error' from='pubsub.shakespeare.lit' id='ent1'> <error type='cancel'> <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
多重修改
所有者可以在一个单独的请求中变更多个从属关系. 如果指定的实体元素之一是非法的, 服务必须返回一个 IQ error (它应该是<not-acceptable/>) 并携带该非法的条目, 这里返回的从属关系是原始的, 未改变的从属关系.
下面的例子展示一个实体尝试让一些从属关系为 "owner" 的实体变成其他从属关系, 如果只有一个所有者那么这个动作是不能(MUST NOT)被允许的.
例子 206. 所有者为多个实体设置从属关系
<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>
例子 207. 服务应答一个错误
<iq type='error' from='pubsub.shakespeare.lit' to='hamlet@denmark.lit/elsinore' id='ent3'> <error type='modify'> <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
在本文开始的状态图是一组 必须实现 的规则,用于检查可能的状态变迁. 实现可以强制其他(更严格的)规则. 如果在一个为多个实体做修改的请求期间发生错误, pubsub错误必须返回任何导致错误的<affiliation/>元素(们). 返回修改失败的实体必须包含现有的 'affiliation' 属性. 在一个 IQ error 中未返回的任何实体元素必须被视为成功地修改了. 所有者不能(MUST NOT)为相同实体指定多个<affiliation/>元素; 否则服务必须返回一个<bad-request/>错误.
删除实体
为了从从属关系列表中删除一个实体, 所有者必须把 'affiliation' 属性的值设为 "none" 并且服务必须从从属关系列表中移除那个实体且在将来的列表请求中不应答它.
通知实体
一个实现可以发送一个事件通知给一个从属关系改变了的实体, 它可以包含一个<body/>元素来指定关于从属关系变更的自然语言文本且它应该包含修改过的从属关系数据.
例子 208. 服务发送从属关系变更通知
<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>
IM帐号集成
发布-订阅 功能能被集成到现有的即时消息和出席信息服务中(见 RFC 3921), 这样每个注册的帐号相当于一个虚拟的pubsub服务(有时候称为 "pubsub-on-a-JID"). 在这类部署中, 每个pubsub服务的根pubsub节点有和该帐号的纯JID(<localpart@domain.tld> 或 <domain.tld>)相同的地址, 它典型地和一个IM用户(例如, <hamlet@denmark.lit>)关联. 因为一个IM用户典型地有一个名册 "好友" 并分享出席信息给那些好友, 该虚拟pubsub服务能使用名册和出席信息来为订阅者提供一些有用的快捷方式, 特别是本章所描述的自动订阅和过滤通知特性.
注意: PEP把接收者的PEP通知捆绑到订阅者的出席信息, 但没把PEP通知的生成捆绑到发布者的出席信息. 如果发布者希望在结束它的出席信息会话之前停止生成PEP事件(或生成一个 "空" 事件, 好像某些PEP载荷能做的那样), 该发布者必须直接引导它的客户端去这样做而不能(MUST NOT)依赖于当PEP服务从发布者接收到unavailable出席信息时PEP服务自动 "清零" 它的PEP信息.
如果一个即时消息和出席信息帐号也是一个虚拟pubsub服务, 来自该帐号的纯JID对服务查询信息("disco#info")的应答必须包含一个特性 "http:/jabber.org/protocol/pubsub#pubsub-on-a-jid":
例子 209. IM服务器代表IM帐号返回支持的特性
<iq from='hamlet@denmark.lit' id='bvg194j7' to='francisco@denmark.lit/barracks' type='result'> <query xmlns='http://jabber.org/protocol/disco#info'> <identity category='account' type='registered'/> <feature var='http://jabber.org/protocol/pubsub#pubsub-on-a-jid'/> </query> </iq>
注意: 因为对于一个客户端生成的任何节来说,帐号所有者的纯JID是缺省目的地址, 客户端经常在这类节中省略 "to" 属性; 在这一点上, 参见 RFC 6120 和 (关于名册) RFC 6121.
自动订阅
当一个联系人通过分享XMPP出席信息从属于帐号所有者, "auto-subscribe" 特性极大地简化了订阅过程. 特别是, 对 "auto-subscribe" 的支持有以下的内涵:
帐号所有者
因为帐号所有者本身隐性地订阅了它自己的XMPP出席信息(例如, 每个XMPP资源从该帐号所有者的所有资源接收出席信息), 一个服务必须认为该帐号所有者有一个对该帐号所有者的根集合节点的pubsub订阅,该订阅的订阅类型为 "items" 且订阅层次为 "all". 这一点对所有访问模式都是对的.
出席信息订阅者
在节点处于以下几种访问模式下,如果一个实体(即, 一个IM帐号)对某个帐号所有者的纯JID(<localpart@domain.tld> 或 <domain.tld>)有一个XMPP出席信息订阅, 服务必须认为该联系人有一个对该帐号所有者的根集合节点的订阅类型为 "items" 且订阅层次为 "all" 的pubsub订阅:
- 该节点的访问模式为 "open".
- 该节点的访问模式为 "presence".
- 该节点的访问模式为 "roster" 且联系人在指定的名册组.
如果该联系人没有权限从任何帐号所有者的根集合节点之下的特定节点接收信息(例如, 因为一个特定节点的访问模式是 "roster" 但是该联系人不在指定的名册组中), 该服务不能(MUST NOT)发送关于那个节点的通知给该联系人并且也不能(MUST NOT)返回任何关于那个节点存在一个潜在的订阅的错误给该联系人(例如, 当联系人发送出席信息给该帐号所有者的时候,服务不能(MUST NOT)返回一个pubsub订阅错误给该联系人).
注意: 当一个IM联系人对帐号所有者有一个订阅, 自动的pubsub订阅必须基于包含在该出席信息订阅请求的 'from' 地址的纯JID, 它对于一个IM联系人将是一个纯JID (<localpart@domain.tld> 或 <domain.tld>).
出席信息分享者
如果该节点有一个开放访问模式, 如果某实体在没有出席信息订阅的情况下曾经发送了出席信息给该帐号所有者,pubsub服务应该也认为该实体临时或隐性地订阅了该节点. 在这种情况下, 该订阅应该基于该出席信息节的 'from' 地址, 它将是一个全JID (<localpart@domain.tld/resource> 或 <domain.tld/resource>). 当该服务从该全JID接收到unavailable出席信息, 它必须取消该临时订阅.
过滤通知
一个联系人可能不想接收某个用户的虚拟pubsub服务上所有节点的通知. 一个联系人应该标记它的参数给该帐号所有者的服务器,通过包含 XEP-0115 信息,指定该联系人希望接收到通知的节点(如果有的话)的NodeIDs. 这个信息被一个pubsub服务用于支持 "filtered-notifications" 特性,只从那些和订阅者的参数匹配的NodeIDs发送通知.
为了让这变为可能, 所有可能的NodeIDs能被加上字符串 "+notify" 以指示该联系人希望从该指定的NodeID接收到通知. 因而如果Romeo想接收到的定位数据的通知(User Geolocation 22) 和 歌曲数据 (User Tune 23)而不是活动数据(User Activity 24), 它的客户端在它发送的对 disco#info 的应答结果中将声明支持如下字符串: 25
这组字符串接着将被声明,通过把它们包含到 标识符+特性 哈希封装到 'ver' 属性里,如 XEP-0115 所述.
例子 210. 联系人携带caps发送出席信息
<presence from='romeo@montague.lit/orchard'> <c xmlns='http://jabber.org/protocol/caps' node='http://www.chatopus.com/#2.2' ver='AFBT0mPr29zQE5aGtCJp97CIS6E='/> </presence>
缓存 XEP-0115 信息是该帐号所有者的服务器的责任. 当该服务器从一个联系人接收出席信息, 它必须检查那个出席信息的实体能力数据并为该联系人的客户端把那个数据和期望的NodeIDs关联起来. 该服务器不能(MUST NOT)发送和该联系人未曾通过 "NodeID+notify" 的disco#info特性请求的任何NodeIDs相关的通知. 这使得一个客户端能关闭所有通知(例如, 因为带宽限制)并容易地接收所有期望的数据格式,只要简单地在它的 disco#info 结果中增加适当的 "NodeID+notify" 支持和客户端能力的支持. 无论如何, 它也暗示一个客户端只能在一个全局基础上请求通知而不能请求, 比如说, 只从在该用户的名册中的特定联系人请求心情信息. 社区一致统一这是一个可接受的折衷. 而且, 注意这只在如果帐号所有者对联系人有一个出席信息订阅且该联系人也有对该帐号所有者有一个出席信息订阅的时候发生.
一些例子可能有助于演示通知过滤的概念. 这里我们显示由以上列出的联系人中的两个生成的出席信息(benvolio@montague.lit 和 juliet@capulet.lit 之间没有任何订阅和被订阅出席信息,所以没有被纳入这些协议流程).
例子 211. 带caps的出席信息
<presence from='nurse@capulet.lit/chamber'> <c xmlns='http://jabber.org/protocol/caps' node='http://exodus.jabberstudio.org/#0.9.1' ver='wXj6c5xhT9frdqhvTSjkdejUUP8='/> </presence> <presence from='romeo@montague.lit/orchard'> <c xmlns='http://jabber.org/protocol/caps' node='http://www.chatopus.com/#2.2' ver='1FDrLLbYMpzvcI95jgSHABSWDRY='/> </presence>
我们假定Juliet的服务器不知道任何这些能力, 所以它代表Juliet本身发送服务查询信息请求给每个客户端(实际上, capulet.lit服务器将很快建立一个客户端能力的缓存, 有了这个结果,它将不需要发送这些服务查询请求):
例子 212. 帐号服务器查询联系人
<iq from='juliet@capulet.lit' to='nurse@capulet.lit/chamber' type='get' id='disco123'> <query xmlns='http://jabber.org/protocol/disco#info'/> </iq> <iq from='nurse@capulet.lit/chamber' to='juliet@capulet.lit' type='result' id='disco123'> <query xmlns='http://jabber.org/protocol/disco#info'> <identity category='client' type='pc'/> <feature var='http://jabber.org/protocol/activity'/> <feature var='http://jabber.org/protocol/activity+notify'/> <feature var='http://jabber.org/protocol/geoloc'/> <feature var='http://jabber.org/protocol/geoloc+notify'/> <feature var='http://jabber.org/protocol/muc'/> <feature var='http://jabber.org/protocol/tune'/> <feature var='http://jabber.org/protocol/tune+notify'/> </query> </iq>
该服务器也将查询为<romeo@montague.lit> identity+features :
例子 213. 帐号服务器查询联系人
<iq from='juliet@capulet.lit' to='romeo@montague.lit/orchard' type='get' id='disco234'> <query xmlns='http://jabber.org/protocol/disco#info'/> </iq> <iq from='romeo@montague.lit/orchard' to='juliet@capulet.lit' type='result' id='disco234'> <query xmlns='http://jabber.org/protocol/disco#info'> <identity category='client' type='pda'/> <feature var='http://jabber.org/protocol/geoloc'/> <feature var='http://jabber.org/protocol/geoloc+notify'/> <feature var='http://jabber.org/protocol/tune'/> <feature var='http://jabber.org/protocol/tune+notify'/> </query> </iq>
(如 XEP-0115 提到的, 该服务器必须使用生成的方法来检查 'ver' 属性提供的哈希值以确保未中毒.)
现在我们回到帐号所有者的发布和通知的服务器生成, 因为服务器有caps信息,过滤被激活了:
- 如果Juliet发布一个tune条目给 presence-access "http://jabber.org/protocol/tune" 节点, 她的服务器将发送通知给<nurse@capulet.lit/chamber>和<romeo@montague.lit/orchard>(全JIDs).
- 如果Juliet发布一个activity条目给 presence-access "http://jabber.org/protocol/activity" 节点, 她的服务器将只发送通知给<nurse@capulet.lit/chamber>.
- 如果Juliet发布一个geolocation条目给 roster-access "http://jabber.org/protocol/geoloc" 节点,并带着 "pubsub#roster_groups_allowed" 变量,其值为 "Friends", 她的服务器将只发送通知给<romeo@montague.lit/orchard>,因为nurse不在那个名册组中.
特性汇总
本章汇总这里描述的特性, 为每个特性指定了适当的要求(REQUIRED, RECOMMENDED, 或 OPTIONAL), 并给描述的每个特性和本文的章节提供了横向参考.
注意: 特性名称的格式都是 "http://jabber.org/protocol/pubsub#name", 这里 "name" 是在第一行下面指定的文本.
表 7: 服务查询特性
名称 | 描述 | 支持 | 章节 |
---|---|---|---|
access-authorize | 缺省访问模式为 "authorize" (授权). | 可选 | 节点访问模式 |
access-open | 缺省访问模式为 "open" (公开). | 可选 | 节点访问模式 |
access-presence | 缺省访问模式为 "presence" (出席信息). | 可选 | 节点访问模式 |
access-roster | 缺省访问模式为 "roster" (名册). | 可选 | 节点访问模式 |
access-whitelist | 缺省访问模式为 "whitelist" . | 可选 | 节点访问模式 |
auto-create | 服务支持在对不存在的节点发布的时候自动创建节点 | 可选 | 自动创建节点 |
auto-subscribe | 服务支持基于出席信息订阅自动订阅到一个节点. | 推荐 | 自动订阅 |
collections | 支持集合节点. | 可选 | 参考 XEP-0248 |
config-node | 支持节点选项配置. | 推荐 | 配置节点 |
create-and-configure | 支持同时创建和配置节点. | 推荐 | 创建并配置节点 |
create-nodes | 支持i节点创建. | 推荐 | 创建节点 |
delete-items | 支持删除条目. | 推荐 | 从节点删除条目 |
delete-nodes | 支持删除节点. | 推荐 | 删除节点 |
filtered-notifications | 基于实体能力数据过滤通知. | 推荐 | 过滤通知 |
get-pending | 支持获取未决的订阅批准. | 可选 | 管理订阅请求 |
instant-nodes | 支持创建即时节点. | 推荐 | 创建节点 |
item-ids | 发布者可以指定条目标识符. | 推荐 | |
last-published | 缺省的,最后发布的条目会被发送给新订阅者和现有的订阅者中有可用的出席信息的接收者. | 推荐 | 事件类型 |
leased-subscription | 支持基于时间的订阅. | 可选 | 基于时间的订阅(租用) |
manage-subscriptions | 节点所有者可以管理订阅. | 可选 | 管理订阅 |
member-affiliation | 支持成员从属关系. | 推荐 | 从属关系 |
meta-data | 支持节点元数据. | 推荐 | |
modify-affiliations | 节点所有者可以修改从属关系. | 可选 | 管理从属关系 |
multi-collection | 一个的难度的叶子节点可以被关联到多个集合. | 可选 | 参考 XEP-0248 |
multi-subscribe | 一个单独实体可以多次订阅一个节点. | 可选 | 多重订阅 |
outcast-affiliation | 支持被排斥者从属关系. | 推荐 | 从属关系 |
persistent-items | 支持持久化条目. | 推荐 | |
presence-notifications | 支持基于出席信息递送事件通知. | 可选 | |
presence-subscribe | 授权的联系人自动订阅到一个用户的虚拟pubsub服务. | 推荐 | 自动订阅 |
publish | 支持发布条目. | 必需 | 发布条目到节点 |
publish-options | 支持带选项发布一个条目. | 可选 | 发布选项 |
publish-only-affiliation | 支持 仅发布 从属关系. | 可选 | 从属关系 |
publisher-affiliation | 支持发布者从属关系. | 推荐 | 从属关系 |
purge-nodes | 支持清理节点. | 可选 | 清除所有节点条目 |
retract-items | 支持条目收回. | 可选 | 从节点删除条目 |
retrieve-affiliations | 支持获取当前从属关系. | 推荐 | 获取从属关系 |
retrieve-default | 支持获取缺省节点配置. | 推荐 | 请求缺省节点配置选项 |
retrieve-default-sub | 支持获取缺省订阅配置. | 可选 | 请求缺省订阅配置选项 |
retrieve-items | 支持获取条目. | 推荐 | 从节点获取条目 |
retrieve-subscriptions | 支持获取当前订阅. | 推荐 | 获取订阅 |
subscribe | 支持订阅和取消订阅. | 必需 | 订阅节点 和 从节点取消订阅 |
subscription-options | 支持订阅选项的配置. | 可选 | 配置订阅选项 |
subscription-notifications | 支持订阅状态变更通知. | 可选 | 订阅状态变更通知 |
错误条件
表 8: 错误条件和典型原因
条件 | 描述 |
---|---|
<conflict/> | 节点已存在. |
<feature-not-implemented/> | 对一个节点(或系统)尝试操作失败,因为服务或节点不支持该操作; 该错误也应该指定不支持哪个特性. |
<forbidden/> | 一个实体没有足够权限来执行该动作, 请求对另一个Jabber ID的操作(例如, francisco@denmark.lit 尝试订阅 bernardo@denmark.lit 到一个节点), 或请求实体的从属关系为被排斥者 "outcast". |
<item-not-found/> | 一些操作所指定的节点或条目不存在. |
<not-allowed/> | 一个实体尝试执行一个服务实现的动作; 无论如何服务范围的管理员或节点所有者已经禁止那个服务或节点的这个动作. |
<not-authorized/> | 一个实体尝试从一个节点订阅或获取条目但是未被授权查看该帐号所有者的出席信息, 不在适当的名册组中, 或不在订阅白名单上. |
<payment-required/> | 订阅和条目获取是基于某种付费服务的. 付费将在带外完成,使用某些事先商定的方法(不在此定义). |
<registration-required/> | 实体在被允许创建节点之前被要求注册. |
实现备注
通知触发
有很多中可能的触发器用来为当前发布的条目或最后发布的条目发送一个事件通知给一个实体, 总结如下:
- 实体显式地从节点请求一个或多个条目并被授权获取条目们; 当服务接收到这样一个请求, 它发送条目们到该实体.
- 实体是某节点的授权订阅者(显式地通过订阅或隐性地基于一个所有者或发布者角色); 当发布者发送一个发布请求, 服务发送当前发布的条目给该实体(遵循适当的出席信息检查和通知过滤).
- 实体未订阅但是可以选择这么做,即曾经发送包含适当实体能力数据的出席信息给一个支持过滤通知的服务(基于一个对通知感兴趣的表达有效地建立一个 "临时订阅" ); 当服务首次接收到这样的出席信息, 它发送最后发布的条目给该实体(只在第一次接收到这样的出席信息之后发送它, 在收到随后的包含同样的通知兴趣的出席信息更新时不再发送).
- 实体未订阅但是可以选择这么做,即曾经发送包含适当实体能力数据的出席信息给一个支持过滤通知的服务(有效建立一个 "临时订阅"); 当发布者发送一个发布一个和该实体表达的通知兴趣匹配的请求, 该服务发送当前发布的条目给该实体.
- 实体获得对该节点的访问,因为节点访问模式的改变; 结果是, 该服务发送最后发布的条目给该实体.
- 实体被加入到和节点访问模式 "roster" 关联的名册组; 结果是, 该服务发送最后发布的条目给该实体.
期望的通知接收者
当一个pubsub服务生成了通知, 它必须遵循隐含在每个订阅者的订阅选项配置中的递送规则. 特别是, 'to' 地址应该只能是订阅的JID. 服务不应(SHOULD NOT)尝试猜测和订阅JID关联的最可用的资源(例如, 在即时消息系统上下文中).
通知相关的错误处理
如上面提到的, 一个pubsub服务应该确保它为每个事件通知生成的<message/>节拥有一个有值的 'id' 属性. (这个通知ID不能和节点ID或条目ID混淆.) 这个ID在该pubsub服务上下文中必须是唯一的以确保跟踪任何递送相关的错误.
服务如何准确地处理递送相关的错误将是一个实现的问题. 通常, 这类处理的效果类似其他消息递送系统执行的弹回操作, 类似邮件传送代理和邮件列表软件. 接下来是一些关于处理和pubsub事件通知相关的XMPP特有错误条件的建议指南(见 RFC 3920 和 XEP-0086 中关于XMPP错误条件的语义):
- 如果该XMPP错误的类型是 "cancel" (例如, <item-not-found/>), 或该错误条件是<gone/>, pubsub服务应该终止该实体对那个节点的订阅并可以终止那个实体对所有位于该服务上的节点的订阅.
- 如果该XMPP错误的类型是 "auth" (例如, <registration-required/>) 或 "wait" (例如, <remote-server-timeout/>), 或错误条件是<bad-request/>, <redirect/>, 或 <not-acceptable/>, 该pubsub服务应该为那个实体增加一个弹回计数并可以在一个配置的时间段之后重新发送该事件通知. 该服务可以终止该实体对那个节点的订阅,如果弹回计数达到一个配置的限制.
临时订阅
一个实现可以让一个实体能临时订阅到一个节点, 即, 只在订阅者在线的这个当前出席信息会话中订阅. 要临时订阅, 订阅者必须把 "pubsub#expire" 订阅配置选项设为一个 "presence" 的文字值.
例子 214. 一个临时订阅
<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>presence</value></field> ... </x> </options> </pubsub> </iq>
该服务接着将在它从订阅者那里接收到类型为 "unavailable" 的出席信息的时候自动取消订阅.
一个实现可以让节点所有者能强制所有订阅都是临时的, 它对于那些也被配置成使用基于出席信息递送的节点是有用的. 这个设定使用 "pubsub#tempsub" 节点配置选项,值设为true.
例子 215. 所有者把所有订阅设为临时
<iq type='set' from='hamlet@denmark.lit/elsinore' to='pubsub.shakespeare.lit' id='configtemp'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <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#tempsub'><value>true</value></field> </x> </configure> </pubsub> </iq>
事件基于出席信息递送
pubsub实现可以只在订阅者在线的时候递送事件通知. 在这些情况下, 选项可以是一个上面例子中展示的节点配置选项. 为了便于实现这个目的, 该pubsub服务需要订阅该订阅者的出席信息并在发送任何事件通知之前检查订阅者的当前出席信息(如 RFC 3921 所述). 出席信息订阅必须基于该订阅的JID.
不路由事件到离线存储
发送事件给现有的Jabber服务器的用户可以强制事件通知被路由到离线存储中用于晚些时候递送(如离线消息处理最佳实践] 27). 这可能不总是必要的. 阻止这个行为的可能的方法包括:
包含消息主体
如果一个服务理解一个特定载荷类型的语义且一个实体的订阅是配置成这样的(把 "pubsub#include_body" 订阅选项设为true), 该服务应该在它为给定节点发送的事件通知的载荷中包含一个适当的 XMPP <body/> 子元素, 这里 body 的XML字符串数据汇总或展现了包含在该载荷中的信息(这使那些不理解该载荷格式的客户端能展示适当的信息给一个终端用户). 例如, Atom <summary/> 元素(见 RFC 4287 )可以被映射成 XMPP <body/> 元素. 一个服务不能(MUST NOT)为一个节点提供 "pubsub#include_body" 订阅选项,如果它没有一个已定义的方法来把部分或全部载荷格式转换成一个合理的消息主体. 一个节点所有者可以为把载荷格式转换成一个消息主体定义一个XSLT, 通过 "pubsub#body_xslt" 节点配置选项. 这个XSLT由pubsub服务在接收到一个发布请求之后和发送适当的通知之前应用, 不是由客户端在发送一个发布请求之前应用.
如果服务不理解一个特定载荷类型的语义,因而不能把该载荷转换成一个自然人可读的消息主体, 它不应(SHOULD NOT)包含一个<body/>元素.
如果一个订阅者对同一个节点有多个订阅, 其中的一些 SubIDs 把 include_body 设为 true 而其他一些则把 include_body 设为 false, 该服务应该在所有通知中包含一个主体.
节点ID和条目ID唯一性
在一个特定的pubsub服务上下文中, NodeIDs必须被视为唯一的标识符.
如果使用了条目标识符, 在该节点的范围内它们必须被视为唯一的. NodeID + ItemID 的组合在一个给定的服务中必须是唯一的, 且必须在一个单独的节点指定一个单独的已发布条目.
如果一个发布者发布了一个条目且ItemID和一个现有的条目吻合, 该pubsub服务必须覆写现有的条目并生成新的事件通知.
因为有可能一个节点的配置被改变了之后要求使用ItemIDs(例如, 从临时的改成持久的), 服务应该为了内部跟踪的目的使用ItemIDs, 即使它在配置变更之前生成的通知没有包含ItemIDs.
条目缓存
一个服务可以缓存最后发布到节点的条目, 即使该节点被配置成用于临时发布(即, 配置成非持久化条目). 最后发布的条目应该在成功处理订阅请求或由一个节点批准之后被发送给最新的订阅者.
注意: 通用的 发布-订阅 协议的特定范本可以对于 "cache-last-item" 特性定义更严格的要求.
批处理
一个发布者可以在一个发布请求中包含多个<item/>元素以及在一个收回请求中包含多个<item/>元素. 这就是发布或收回的 "批处理" .
如果服务不能处理发布或收回的条目中的任何一个, 整个批处理必须失败且服务不能(MUST NOT)发布或收回任何条目.
如果一个批量发布包含如此多的条目以至于所有条目的发布将超出该节点的最大数量限制, 该服务必须返回一个<not-allowed/>错误, 它应该也包含一个pubsub特有的错误条件<max-items-exceeded/>.
注意: 批量发布造成了 "最后发布的条目" 概念的问题; 所以, 如果需要信息一致性, 一个发布者应该在分开的请求中发布条目而不是用批处理模式.
自动订阅的所有者和发布者
一个服务必须允许所有者和发布者订阅一个节点, 以及从一个节点获取条目,即使他们没有订阅. 服务可以自动订阅所有者和发布者,如果他们未曾订阅, 在这种情况下如果对订阅是必要的话它应该生成一个订阅ID,并且应该发送一个成功订阅的通知,如本文的订阅状态变更通知所述.
授权订阅请求(未决订阅者)
订阅请求如何被发送给节点所有者是一个实现的问题. 可能包括:
- 发送请求给全部所有者(这些可以被放到离线存储中,如 XEP-0160 所述)并且第一个批准的人做主.
- 服务将订阅所有者的出席信息, 且只发送给在线的所有者.
- 全部所有者投票决定新订阅者.
- 允许任何所有者否决该订阅者.
一个实现可以使用这些方法中的任何一个, 或一些这里没定义的方法.
订阅状态变更通知
各种动作和事件可以导致一个订阅状态的变更:
- 批准或拒绝一个订阅请求,如管理订阅请求用例所述
- 撤销一个现有的订阅, 它有很多可能的触发器 "triggers" :
- 实体简单地取消订阅该节点
- 节点类型是 "presence" 且潜在的出席信息订阅被撤销
- 节点类型是 "roster" 且该实体被移动到未授权的名册组
当发生了一个订阅状态变更, 一个服务应该发送一个消息给这个(新的, 之前的, 或拒绝的)订阅者以向它通知这个变更, 这里该消息包含一个<event/>元素,并带有一个单独的<subscription/>子元素来指定该节点, JID, 和订阅状态. 该通知可以包含一个<body/>元素来指定关于该订阅变更的自然语言文本. 服务对其发送通知的那个JID的地址就是该订阅请求中的 'jid' 属性所设置的那个.
例子 216. 订阅批准通知
<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>
例子 217. 订阅 撤销/拒绝 通知
<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>
如果服务有该订阅者(之前的或拒绝的)的出席信息的知识, 它应该发送消息给该订阅者的所有资源; 如果没有, 它必须发送该消息给该订阅者的从属的JID.
如果一个服务或节点支持这个特性, 它必须在它对服务查询信息请求的应答中返回一个特性 "subscription-notifications" .
NodeID语义
NodeIDs在pubsub的特定的范本,实现,或部署中可以有语义. 无论如何, 强烈建议这类语义不被用于封装节点的层次结构; 反之, 节点层次应该使用集合节点和它们的关联子节点来封装,如 XEP-0248 所述.
包含SHIM头
当使用了SubIDs的时候, 节头和互联网元数据(SHIM) 头被包含在里面以区分被发送的关联到特定订阅的不同通知. 相关用例和场景为:
SHIM头是由订阅者订阅了的那个节点生成的, 它可以是一个叶子节点或一个集合节点(参考 XEP-0248 ).
当内容不是基于订阅ID来区分的时候,SHIM头不会被包含, 例如, 当一个节点发送配置变更通知, 该节点已经被清理的通知, 或该节点被删除的通知给该节点本身.
和生成实体关联的事件和载荷
一个实现可以让节点配置能指定事件通知和实体之间的用于发布信息的关联, 但是这样一个特性是可选的. 这里是一些可能的例子:
- 在一个使用用户位置 29的地理位置通知服务上下文中, 用户可以生成地理未知信息或该信息可由一个自动的服务生成(例如, 一个由移动电话供应商提供的服务), 但是在这两种情况下该信息都是关于该用户的地理位置,所以所有应答应该去到该用户(它可能是节点所有者).
- 在一个群组博客上下文中, 不同用户可以发布到该博客而应答可以给一个博文的发布者而不是该博客的所有者.
- 在一个集成了pubsub和多用户聊天系统的上下文中, 节点所有者可以是房间所有者但是所有应答需要被发送到房间而不是该所有者.
因此我们定义了 "itemreply" 节点配置选项, 有两个可能的值:
- "owner" (即, 节点所有者或节点所有者的别名)
- "publisher" (即, 该条目的发布者)
一个节点所有者不能(MUST NOT)定义多于一个这类选项.
一个例子如下.
例子 218. 带发布者JID的事件通知
<message from='pubsub.shakespeare.lit' to='bassanio@merchantofvenice.lit'> <event xmlns='http://jabber.org/protocol/pubsub#event'> <items node='n48ad4fj78zn38st734'> <item id='i1s2d3f4g5h6bjeh936' publisher='portia@merchantofvenice.lit'> <geoloc xmlns='http://jabber.org/protocol/geoloc'> <description>Venice</description> <lat>45.44</lat> <lon>12.33</lon> </geoloc> </item> </items> </event> </message>
作为一种选择, 如果一个服务实现了本协议的个人事件子集, 该虚拟pubsub服务是该帐号所有者的纯JID且通知被从那个JID发送; 细节参考 XEP-0163 .
链接
单词 "chaining" 指的是订阅一个节点到另一个节点的实践. 比如, 考虑一个场景,节点<pubsub@example.net/NewsBroadcaster>想分发信息从<pubsub.example.com>上的节点 "NewsFeed" 收到的信息. 因为理论上对于<pubsub@example.net/NewsBroadcaster>来说直接订阅NewsFeed节点是有可能的(因为之前的节点被直接寻址为一个JID), 实现不能(MUST NOT)以这种方式链接节点. 反之, 实现必须从该pubsub服务而不是该节点的地址来订阅(在这里展示的例子中, 该订阅将被从<pubsub@example.net>而不是<pubsub@example.net/NewsBroadcaster>)发送.
基于时间的订阅(租用)
在一些系统中可能想要提供一个订阅 "leasing" 特性以让旧的或不新鲜的订阅超时失效. 租用能用可配置的订阅选项来实现; 具体来说, 当一个实体订阅了, 该服务将要求订阅选项配置且配置格式将包含一个字段 "pubsub#expire". 这个字段必须包含一个dateTime(定义于XMPP日期和事件范本 30).
租用过程如下所示.
例子 219. 租用过程
<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'/>
当该租用快要结束的时候(例如, 在该租约结束之前24小时),该服务可以发送一个消息给该订阅者. 要做到这必须发送一个包含了一个由 'http://jabber.org/protocol/pubsub#event' 命名空间限定的<subscription/>元素的<message/>,这个<subscription/>元素必须包含一个 'expiry' 属性.
例子 220. 服务通知订阅者租约快到期了
<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit/barracks'> <event xmlns='http://jabber.org/protocol/pubsub#event'> <subscription expiry='2006-02-28T23:59Z' jid='francisco@denmark.lit' node='princely_musings' subid='ba49252aaa4f5d320c24d3766f0bdcade78c78d3' subscription='subscribed'/> </event> </message>
当该订阅者想更新租用, 它将获得当前的订阅选项, 修改 "pubsub#expire" 字段的值, 并提交该新订阅选项给回服务. 如果新的过期值超过了订阅租用允许的最大值, 该服务必须把该字段的值改为当前的 date/time 加上最大允许租用时间.
例子 221. 更新一个租用
<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'/>
基于内容的Pubsub系统
一个服务可以让实体能订阅节点并应用一个过滤器到通知(例如, 关键字匹配,类似 "从Slashdot发送所有匹配术语 'Jabber' 的新闻条目给我"). 这样一个基于内容的服务应该允许一个实体多次订阅相同的节点并且, 如果是这样, 必须用订阅标识符(SubIDs)来区分多个订阅. 为了防止冲突, 一个支持基于内容订阅的使用SubIDs的服务应该代表订阅者生成SubIDs而不是允许订阅者设置他们自己的SubIDs. 31
基于内容的服务应该使用订阅选项来指定被应用的过滤器(们). 因为有很多可能的过滤机制(其中一些可以是应用特有的), 本文不订阅任何这类放大. 无论如何, 过滤机制可以被定义在独立的协议中.
下面是一个用于基于内容的pubsub的订阅选项配置过程的虚构的例子.
例子 222. 一个基于内容的订阅
<iq type='set' from='bard@shakespeare.lit/globe' 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='bard@shakespeare.lit/globe' id='filter1'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <subscription node='princely_musings' jid='bard@shakespeare.lit' subid='991d7fd1616fd041015064133cd097a10030819e' subscription='unconfigured'> <subscribe-options> <required/> </subscribe-options> </subscription> </pubsub> </iq> <iq type='get' from='bard@shakespeare.lit/globe' to='pubsub.shakespeare.lit' id='filter2'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <options node='princely_musings' jid='bard@shakespeare.lit' subid='991d7fd1616fd041015064133cd097a10030819e'/> </pubsub> </iq> <iq type='result' from='pubsub.shakespeare.lit' to='bard@shakespeare.lit/globe' id='filter2'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <options node='princely_musings' jid='bard@shakespeare.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='x-http://shakespeare.lit/search#keyword' type='text-single' label='Keyword to match'/> ... </x> </options> </pubsub> </iq> <iq type='set' from='bard@shakespeare.lit/globe' to='pubsub.shakespeare.lit' id='filter3'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <options node='princely_musings' jid='bard@shakespeare.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='x-http://shakespeare.lit/search#keyword'><value>peasant</value></field> ... </x> </options> </pubsub> </iq> <iq type='result' from='pubsub.shakespeare.lit' to='bard@shakespeare.lit/globe' id='filter3'/>
该订阅者接着将被通知匹配该关键字的事件.
例子 223. 为匹配的关键字的事件通知
<message from='pubsub.shakespeare.lit' to='bard@shakespeare.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='SubID'>991d7fd1616fd041015064133cd097a10030819e</header> </headers> </message>
单件节点
对于一些节点, 期望在任何时间至少有一个和该节点关联的条目存在(例如, 一个客户端可能想使用一个由那个客户端控制的命名空间命名的节点名来存储它的参数). 当想用这个模式的时候, 推荐该发布者指定一个 "current" ItemID来确保一个新条目的发布将覆盖现有的条目.
例子 224. 发布到一个单件节点
<iq type='set' from='horatio@denmark.lit/mobile' to='pubsub.shakespeare.lit' id='single1'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <publish node='elsinore-doorbell'> <item id='current'/> </publish> </pubsub> </iq>
自然的, 该节点所有者能通过把 max_items 配置选项设为 "1" 来强制该单件节点模式.
PubSub URIs
一个 XMPP URI (见 RFC 5122 32)能被用于识别或交互的目的. 一些例子如下.
以下URI只是标识一个pubsub节点.
例子 225. XMPP URI 用于节点
xmpp:pubsub.shakespeare.lit?;node=princely_musings
以下URI识别位于一个节点的一个特定条目.
例子 226. XMPP URI 用于一个pubsub条目
xmpp:pubsub.shakespeare.lit?;node=princely_musings;item=ae890ac52d0df67ed7cfdf51b644e901
以下URI定义如何订阅一个节点(详见本文的URI查询类型).
例子 227. URI 用于订阅一个pubsub节点
xmpp:pubsub.shakespeare.lit?pubsub;action=subscribe;node=princely_musings
以下URI定义如何从一个节点获取一个特定的条目.
例子 228. URI 用于获取一个pubsub条目
xmpp:pubsub.shakespeare.lit?pubsub;action=retrieve;node=princely_musings;item=ae890ac52d0df67ed7cfdf51b644e901
XML Schemas
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 XEP-0060: http://xmpp.org/extensions/xep-0060.html </xs:documentation> </xs:annotation> <xs:import namespace='jabber:x:data' schemaLocation='http://xmpp.org/schemas/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='default'/> <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='member'/> <xs:enumeration value='none'/> <xs:enumeration value='outcast'/> <xs:enumeration value='owner'/> <xs:enumeration value='publisher'/> <xs:enumeration value='publish-only'/> </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='default'> <xs:complexType> <xs:simpleContent> <xs:extension base='empty'> <xs:attribute name='node' type='xs:string' use='optional'/> <xs:attribute name='type' use='optional' default='leaf'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='collection'/> <xs:enumeration value='leaf'/> </xs:restriction> </xs:simpleType> </xs:attribute> </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:sequence minOccurs='0' maxOccurs='unbounded'> <xs:element ref='subscription'/> </xs:sequence> <xs:attribute name='node' type='xs:string' use='optional'/> </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>
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 XEP-0060: http://xmpp.org/extensions/xep-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-items-exceeded' 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='too-many-subscriptions' 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='access-authorize'/> <xs:enumeration value='access-open'/> <xs:enumeration value='access-presence'/> <xs:enumeration value='access-roster'/> <xs:enumeration value='access-whitelist'/> <xs:enumeration value='auto-create'/> <xs:enumeration value='auto-subscribe'/> <xs:enumeration value='collections'/> <xs:enumeration value='config-node'/> <xs:enumeration value='create-and-configure'/> <xs:enumeration value='create-nodes'/> <xs:enumeration value='delete-items'/> <xs:enumeration value='delete-nodes'/> <xs:enumeration value='filtered-notifications'/> <xs:enumeration value='get-pending'/> <xs:enumeration value='instant-nodes'/> <xs:enumeration value='item-ids'/> <xs:enumeration value='last-published'/> <xs:enumeration value='leased-subscription'/> <xs:enumeration value='manage-subscriptions'/> <xs:enumeration value='member-affiliation'/> <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='presence-subscribe'/> <xs:enumeration value='publish'/> <xs:enumeration value='publish-options'/> <xs:enumeration value='publish-only-affiliation'/> <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>
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 XEP-0060: http://xmpp.org/extensions/xep-0060.html </xs:documentation> </xs:annotation> <xs:import namespace='jabber:x:data' schemaLocation='http://xmpp.org/schemas/x-data.xsd'/> <xs:element name='event'> <xs:complexType> <xs:choice> <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:choice> <xs:element ref='associate'/> <xs:element ref='disassociate'/> </xs:choice> <xs:attribute name='node' type='xs:string' use='optional'/> </xs:complexType> </xs:element> <xs:element name='associate'> <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='disassociate'> <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='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:sequence> <xs:element ref='redirect' minOccurs='0' maxOccurs='1'/> </xs:sequence> <xs:attribute name='node' type='xs:string' use='required'/> </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:attribute name='publisher' type='xs:string' use='optional'/> </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='redirect'> <xs:complexType> <xs:simpleContent> <xs:extension base='empty'> <xs:attribute name='uri' 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='expiry' type='xs:dateTime' use='optional'/> <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>
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 XEP-0060: http://xmpp.org/extensions/xep-0060.html </xs:documentation> </xs:annotation> <xs:import namespace='jabber:x:data' schemaLocation='http://xmpp.org/schemas/x-data.xsd'/> <xs:element name='pubsub'> <xs:complexType> <xs:choice> <xs:element ref='affiliations'/> <xs:element ref='configure'/> <xs:element ref='default'/> <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='member'/> <xs:enumeration value='none'/> <xs:enumeration value='outcast'/> <xs:enumeration value='owner'/> <xs:enumeration value='publisher'/> <xs:enumeration value='publish-only'/> </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:sequence> <xs:element ref='redirect' minOccurs='0' maxOccurs='1'/> </xs:sequence> <xs:attribute name='node' type='xs:string' use='required'/> </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='redirect'> <xs:complexType> <xs:simpleContent> <xs:extension base='empty'> <xs:attribute name='uri' 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:simpleType name='empty'> <xs:restriction base='xs:string'> <xs:enumeration value=''/> </xs:restriction> </xs:simpleType> </xs:schema>
致谢
感谢 Kirk Bateman, Robin Collier, Blaine Cook, Ovidiu Craciun, Brian Cully, Dave Cridland, Guillaume Desmottes, Gaston Dombiak, William Edney, Seth Fitzsimmons, Fabio Forno, Nathan Fritz, Julien Genestoux, Anastasia Gornostaeva, Joe Hildebrand, Curtis King, Tuomas Koski, Petri Liimatta, Tobias Markmann, Pedro Melo, Dirk Meyer, Tory Patnoe, Peter Petrov, Sonny Piers, Christophe Romain, Pavel Šimerda, Andy Skelton, Kevin Smith, Chris Teegarden, Simon Tennant, Matt Tucker, Matthew Wild, Bob Wyman, Matus Zamborsky, and Brett Zamir 的反馈.
作者备注
Peter Millard, 本协议从版本0.1到版本1.7的主要作者, 去世于 April 26, 2006. 其他的联合作者对它多年来在 发布-订阅 技术方面的工作深表感谢.
附录
附录A:文档信息
系列:XEP
序号:0060
发布者:XMPP标准基金会
状态:草案
类型:标准跟踪
版本:1.13
最后更新:2010-07-12
批准机构:XMPP理事会
依赖标准:XMPP Core, XEP-0004, XEP-0030, XEP-0068, XEP-0082, XEP-0131
替代标准:无
被替代标准:无
缩略名:pubsub
用于pubsub命名空间的XML Schema: <http://xmpp.org/schemas/pubsub.xsd>
用于pubsub#errors命名空间的XML Schema: <http://xmpp.org/schemas/pubsub-errors.xsd>
用于pubsub#event命名空间的XML Schema: <http://xmpp.org/schemas/pubsub-event.xsd>
用于pubsub#owner命名空间的XML Schema: <http://xmpp.org/schemas/pubsub-owner.xsd>
原文控制: HTML
附录B:作者信息
Peter Millard
见 作者备注
Peter Saint-Andre
Email: stpeter@jabber.org
JabberID: stpeter@jabber.org
URI: https://stpeter.im/
Ralph Meijer
Email: ralphm@ik.nu
JabberID: ralphm@ik.nu
附录C:法律通告
版权
XMPP扩展协议的版权(1999-2008)归XMPP标准化基金会(XSF)所有.
权限
特此授权,费用全免,对任何获得本协议副本的人,对使用本协议没有限制,包括不限制在软件程序中实现本协议,不限制在网络服务中布署本协议,不限制拷贝,修改,合并,发行,翻译,分发,转授,或销售本协议的副本,被允许使用本协议做了以上工作的人士,应接受前述的版权声明和本许可通知并且必须包含在所有的副本或实质性部分的规格中.除非单独的许可,被重新分发的修改工作,不得含有关于作者,标题,编号,或出版者的规格的误导性资料,并不得宣称修改工作是由本文的作者,作者所属的任何组织或项目,或XMPP标准基金会签注。
免责声明'
## 特别注意:本协议是提供的“原样”的基础,没有担保或任何形式的条件,明示或暗示,包括,但不限于任何担保或关于名称,非侵权性,适销性或适合作某一特定目的的条件. ##
责任限制
在任何情况下以及没有任何法律规定时,不论是侵权行为(包括疏忽),合同或其它方面,除非根据适用法律的要求(如蓄意和有严重疏忽行为)或以书面形式同意,XMPP标准基金会或任何作者不对本协议所造成的损失承担责任,包括任何直接,间接,特殊,偶发,或任何从本协议出,入,连接的字符产生的或实现,布署或其他对本协议的使用导致的相应的损害赔偿(包括但不限于善意的损失,停止作业,电脑失灵或故障,或任何和所有其他商业损害或损失) ,即使XMPP标准基金会或作者已被告知此类损害的可能性。
知识产权的一致性
XMPP扩展协议完全遵守XSF的知识产权策略(可在<http://www.xmpp.org/extensions/ipr-policy.shtml>找到副本或写信给XMPP标准基金会, 1899 Wynkoop Street, Suite 600, Denver, CO 80202 USA).
附录D:和XMPP的关系
可扩展的消息和出席信息协议 (XMPP) 定义于 XMPP Core (RFC 3920) 和 XMPP IM (RFC 3921) 规范里,由 XMPP标准基金会贡献到由依据RFC 2026成立的互联网工程人物组管理的互联网标准流程 Internet Standards Process. 本文定义的任何协议已在互联网标准流程之外开发,并且被理解为 XMPP 的扩展而不是一个XMPP本身的演化, 开发, 或修改.
附录E:讨论地点
主要的XMPP扩展协议讨论地点是 <standards@xmpp.org> 讨论列表.
在 xmpp.org 的其它讨论列表中的讨论可能也有合适的; 所有的列表见 <http://xmpp.org/about/discuss.shtml> .
勘误表可以发送邮件到 <editor@xmpp.org>.
附录F:需求一致性
以下用于本文的需求关键字的解释见于 RFC 2119: "MUST", "SHALL", "REQUIRED"; "MUST NOT", "SHALL NOT"; "SHOULD", "RECOMMENDED"; "SHOULD NOT", "NOT RECOMMENDED"; "MAY", "OPTIONAL".
附录G:备注
1. RFC 4287: The Atom Syndication Format <http://tools.ietf.org/html/rfc4287>.
2. RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core <http://tools.ietf.org/html/rfc6120>.
3. XEP-0030: Service Discovery <http://xmpp.org/extensions/xep-0030.html>.
4. XEP-0248: PubSub Collection Nodes <http://xmpp.org/extensions/xep-0248.html>.
5. XEP-0163: Personal Eventing Protocol <http://xmpp.org/extensions/xep-0163.html>.
6. RFC 3921: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence <http://tools.ietf.org/html/rfc3921>.
7. XEP-0045: Multi-User Chat <http://xmpp.org/extensions/xep-0045.html>.
8. 这些节点等同于那些 XEP-0030: Service Discovery 中使用的节点.
9. 这个规则不适用于根集合节点, 如果有的话.
10. XEP-0055: Jabber Search <http://xmpp.org/extensions/xep-0055.html>.
11. XEP-0004: Data Forms <http://xmpp.org/extensions/xep-0004.html>.
12. XEP-0128: Service Discovery Extensions <http://xmpp.org/extensions/xep-0128.html>.
13. XEP-0068: Field Data Standardization for Data Forms <http://xmpp.org/extensions/xep-0068.html>.
14. XEP-0203: Delayed Delivery <http://xmpp.org/extensions/xep-0203.html>.
15. 根据 XML Schema Part 2: Datatypes 的3.2.2.1节, xs:boolean datatype 允许的词汇表达是字符 "0" 和 "false" 用于概念 '假' 而字符 "1" 和 "true" 用于概念 '真'; 实现必须同时支持两种词汇表达方式.
16. XEP-0059: Result Set Management <http://xmpp.org/extensions/xep-0059.html>.
17. 不再允许包含多个<item/>元素了, 从本协议的版本1.13给出了批量发布的移除功能.
18. 对一个发布请求来说,要触发一个事件通知,包含一个载荷或甚至一个<item/>元素不是必要的. 例如, 发布到一个临时的,仅通知的节点的结果将是一个甚至不包含一个<item/>元素的事件通知. 无论如何, 为了方便讨论,我们参考发布行为 "发布一个条目" (而不是, 说, "触发一个事件通知") ,尽管一个发布请求不总是包含一个<item/>元素.
19. XEP-0131: Stanza Headers and Internet Metadata <http://xmpp.org/extensions/xep-0131.html>.
20. 根据 XML Schema Part 2: Datatypes 的3.2.2.1节, xs:boolean datatype 允许的词汇表达是字符 "0" 和 "false" 用于概念 '假' 而字符 "1" 和 "true" 用于概念 '真'; 实现必须同时支持两种词汇表达方式.
21. XEP-0050: Ad-Hoc Commands <http://xmpp.org/extensions/xep-0050.html>.
22. XEP-0080: User Geolocation <http://xmpp.org/extensions/xep-0080.html>.
23. XEP-0118: User Tune <http://xmpp.org/extensions/xep-0118.html>.
24. XEP-0108: User Activity <http://xmpp.org/extensions/xep-0108.html>.
25. 包含的, 假如说, 'http://jabber.org/protocol/geoloc' NodeID 表示该客户端理解XEP-0080 所述的地理位置命名空间, 而包含 'http://jabber.org/protocol/geoloc+notify' 命名空间表示该客户端理想接收和地理位置相关的通知, 这里的NodeID和地理位置命名空间 'http://jabber.org/protocol/geoloc' 是一样的(这种情况下,在命名空间名称和NodeID之间是一对一对应的).
26. XEP-0086: Error Condition Mappings <http://xmpp.org/extensions/xep-0086.html>.
27. XEP-0160: Best Practices for Handling Offline Messages <http://xmpp.org/extensions/xep-0160.html>.
28. XEP-0079: Advanced Message Processing <http://xmpp.org/extensions/xep-0079.html>.
29. XEP-0080: User Geolocation <http://xmpp.org/extensions/xep-0080.html>.
30. XEP-0082: XMPP Date and Time Profiles <http://xmpp.org/extensions/xep-0082.html>.
31. 另一个实现基于内容的订阅的方法是给每个关键或其他过滤器提供一个节点; 无论如何, 这相当于要求非常大量的节点.
32. RFC 5122: Internationalized Resource Identifiers (IRIs) and Uniform Resource Identifiers (URIs) for the Extensible Messaging and Presence Protocol (XMPP) <http://tools.ietf.org/html/rfc5122>.
33. 互联网号码分配机构(IANA)是为互联网协议分配唯一性的参数值的中间协调者, 类似端口号码和 URI schemes. 更多信息参见 <http://www.iana.org/>.
34. XMPP注册处维护一个保留的协议命名空间的列表和在XMPP标准基金会批准的XMPP扩展协议的上下文中使用的参数的注册项的列表. 更多信息见 <http://xmpp.org/registrar/>.
35. 在XEP-0060的版本1.5之前, 这个类型被称为 "generic".
36. XEP-0147: XMPP URI Query Components <http://xmpp.org/extensions/xep-0147.html>.
附录H:修订历史
注意: 本协议的旧版本可能在 http://xmpp.org/extensions/attic/ 还可用
Version 1.13 (2010-07-12)
- Pending further discussion: added but then removed change to allow notifications via IQ stanzas; removed but then retained batch publishing; removed but then retained SubIDs in subscription approvals.
- Corrected a large number of reported errata.
- Removed delete-any feature.
- Added missing delete-items feature.
- Added special value of "presence" for the pubsub#expire option to support temporary subscriptions.
- Removed replyto and replyroom config options.
- Removed multiple node discovery since it depended on the deprecated Service Discovery Publishing feature.
- Defined "room" value for itemreply config option.
- Added optional 'publisher' attribute to <item/> element.
- Added optional <redirect/> child to <delete/> element.
- Based redirects on URIs for consistency with RFC 6120 gone and redirect errors.
- Clarified meaning of filtered notifications (they are based on NodeIDs, not payload namespaces).
- Added pubsub-on-a-jid service discovery feature for explicit discovery that an IM and presence account also functions as a virtual pubsub service.
- Added purge_offline node configuration option for purging the node when the relevant publisher goes offline, for use in certain extended presence applications.
- Added item_expire node configuration option for automatically removing items after a certain number of seconds.
- Added notification_type node configuration option for defining which value of the <message/> type attribute shall be used for notifications.
- Added retrieve-default-sub feature for retrieving default subscription configuration from a node (as you can retrieve default node configuration from the service).
- Clarified suggested rules for payload definitions.
- Mentioned that singleton pattern can be enforced by setting max_items to 1.
- Removed the notion of batch publishing because it makes information coherence and atom handling excessively difficult.
- Added error handling for too-many-subscriptions to help prevent a certain denial of service attack.
- Added process for retrieving default subscription configuration options for leaf nodes, by omitting the 'node' attribute on the <default/> element (also added the <default/> element to the schema for the http://jabber.org/protocol/pubsub namespace, since it was missing).
- Removed informational mapping of node meta-data to Dublin Core.
(psa)
Version 1.12 (2008-09-03)
- Specified that service should return ItemID on successful publish if no ItemID was provided in request.
- Described the use of Result Set Management to return some but not all published items.
- Defined pubsub#notify_sub config option so that owners can receive notifications of new subscriptions, unsubscribes, and other subscription changes.
- Harmonized definition of +notify feature with implementation reality.
- Moved text about collections to XEP-0248.
(psa)
Version 1.11 (2008-03-05)
For collection nodes, changed name of node child element to associate and added disassociate child element to handle disassociation use case; corrected SHIM examples to conform to XEP-0131; modified lease expiry notification for consistency with other subscription-related notifications (i.e., not using SHIM header); renamed SHIM headers to Collection and SubID for consistency with HTTP and Email headers.
(rm/psa)
Version 1.10 (2007-09-26)
- In accordance with XMPP Council consensus, moved the auto-create, auto-subscribe, filtered-notifications, and last-published features from XEP-0163 to this specification
- Clarified implications of auto-subscribe feature for handling of account owners, stable presence subscribers, and transient presence sharers
- Updated filtered-notifications text and examples to track changes to XEP-0115
- Added publish-options functionality
- Added developer-friendly How It Works section
- Defined member affiliation to properly implement whitelist feature
- Split several long sections into smaller sub-sections.
- Clarified that a pubsub service must generate an ItemID if the publisher does not provide one.
- Specified recommended ItemID for singleton nodes.
- Summarized triggers for sending notifications.
(psa)
Version 1.9 (2006-09-13)
- Replaced boolean send_item_subscribe node configuration option with more comprehensive send_last_published_item option per list discussion
- Added deliver_notifications node configuration option to enable quiet nodes without notifications, if desired enabling pull-model item retrieval only.
- Modified subscription and affiliation retrieval to return empty element if no results.
(psa)
Version 1.8 (2006-06-27)
- Defined five access models: open, presence, roster, authorize, and whitelist
- Renamed pubsub#subscription_model feature to pubsub#access_model
- Separated affiliations retrieval from subscriptions retrieval
- Removed subscription information from affiliations management
- Changed <entity/> element to <subscription/> element in response to subscription request
- Clarified batch processing of item publication and item deletion
- Added basic example to introduction
- More fully specified node creation flows
- More fully specified recommended behavior for caching last published item, including use of jabber:x:delay protocol
- Specified that semantic meaning of NodeIDs must not be used to encapsulate hierarchy
- More fully specified error conditions
- Changed some feature-related conditions to <unsupported/> plus feature attribute
- Changed some error conditions from <not-authorized/> to <forbidden/>
- Harmonized error conditions for unsubscribe if entity is not subscribed (unexpected-request rather than not-found)
- Further defined error conditions related to item publication
- Specified structure of <affiliations/>, <delete/>, <purge/>, and <subscriptions/> elements qualified by pubsub#owner namespace
- Changed retrieval of default node configuration options to use <default/> element, not <configure/> element
- Allowed caching of last published item
- Added pubsub#deliver subscription option
- Added meta-data fields for pubsub#owners and pubsub#contact
- Changed element for retrieval of default node configuration options from <configure/> to <default/> to prevent ambiguity related to configuration of root collection node
- Specified pubsub#node_type configuration field
- Specified pubsub#collection SHIM header
- Specified conformance with Resourceprep for nodes addressable as JIDs
- Added pubsub#modify-affiliations feature
- Added pubsub#digest_frequency field to subscribe_options FORM_TYPE
- Added pubsub#roster_groups_allowed field to node_config FORM_TYPE
- More clearly specified the requirements level (MUST, SHOULD, MAY) for each service discovery feature
- Defined pubsub#include_body subscription option and the pubsub#body_xslt node configuration option to transform payload format into an XMPP message body, and clarified rules for inclusion of message bodies
- Clarified nature of collections and association of a node to a collection
- Specified that simultaneous subscriptions of type nodes and items are allowed to collection nodes
- Added examples and further explanation of time-based and content-based subscriptions
- Added Internationalization Considerations
- Clarified terminology
- Corrected and updated the schemas
(psa)
Version 1.7 (2005-03-03)
- Reinstated pubsub#subscribe feature (deleted in error)
- Added type attribute for the <create/> and <configure/> elements to differentiate between leaf nodes and collection nodes
- In Section 8.1.7, changed affiliations retrieval support to SHOULD and added pubsub#retrieve-affiliations feature
- In Section 8.1.10, removed two duplicate examples
- In Section 8.1.12, clarified relationship between normal disco#info data and node meta-data (which uses a service discovery extension)
- In Section 8.2.4, specified that node purgation MUST result in one event notification, not a notification per item
- In Section 8.1.8, further specified handling of SubIDs
- Clarified nature of the pubsub#type field
- Mentioned that the forbidden error should be returned in response to certain operations requested by an outcast
- Corrected datatype of max_items attribute from xs:string to xs:positiveInteger
- Corrected <requesting-entity-not-subscribed/> error to <not-subscribed/> since the subscribed JID need not be that of the requesting entity
- Added service discovery features for more optional use cases: retracting items, purging nodes, deleting nodes
- Updated relevant registries
(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 XMPP 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 XMPP 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 XMPP 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 XMPP 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 XMPP 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 XMPP Registrar Considerations. Added link to XEP-0068 about the FORM_TYPE element in subscription request notifications. Fixed some typos in examples. Added unsupported configuration namespace to example. Added a default node configuration example.
(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)