XEP-0016

来自Jabber/XMPP中文翻译计划
2012年12月20日 (四) 04:38Admin (讨论 | 贡献)的版本
跳转到: 导航, 搜索


本文的英文原文来自 XEP-0016

XEP-0016: 隐私列表

摘要: 本文定义了一个XMPP协议扩展, 用于启用和禁用与网络上其他实体的通讯.这个协议,最早在RFC 3921的第十单元被标准化,被用于封锁与未知或不良实体的沟通.封锁能够基于Jabber标识符,订阅状态或者花名册群组.被封锁的节点可以是messages,IQs,进入或者输出的presence节点,或者所有节点.本协议也允许实体创建,修改或者删除它的隐私列表,使得不同的列表可以应用到不同的连接资源上,定义一个默认列表,在特定会话期间拒绝隐私列表的使用.

作者: Peter Millard,Peter Saint-Andre

版权: © 1999 - 2010 XMPP标准化基金会(XSF). 参见法律通告.

状态: 草案

类型: 标准跟踪

版本: 1.6

最后更新日期: 2007-02-15


注意: 这里定义的协议是XMPP标准化基金会的一个草案标准.对本协议的执行是被鼓励的,也适于布署到生产系统,但是在它成为最终标准之前可能还会有一些变动.


目录

绪论

几乎所有的即时通讯应用都已经发现,为用户提供一些方法,用来锁定接收自其他用户的消息和数据包是必要的(对于这些封锁的根本原因是取决于一些个别用户的需求).这个文档定义了一个灵活的方法用于锁定通讯.

注释:在此定义的协议可以用来与简单通讯锁定协同,详情请参阅XEP-0191

协议

本章节是被从RFC 3921的第十章节拷贝过来的,而且没有修改,除了message节点在处理阻止实体试图与用户通讯的订阅方面.

大部分即时通讯系统发现,为用户提供一些锁定来自一些特殊用户通讯的方法,是必要的(这在RFC 2779 [3]的5.1.5, 5.1.15, 5.3.2, 和5.4.10 章节也是被要求的).在XMPP协议中,这些工作被采用'jabber:iq:privacy'命名空间的管理个人隐私列表的操作来完成.

服务器端隐私列表成功的完成了以下用例:

  • 获取一个人的隐私列表.
  • 添加, 删除, 并且编辑一个人的隐私列表.
  • 设置, 改变, 或者撤除激活的列表.
  • 设置, 改变, 或者撤除缺省的列表(即, 缺省激活的那个列表).
  • 基于JID, 群组, 或者订阅类型(或者全部)允许或阻止messages.
  • 基于JID, 群组, 或者订阅类型(或者全部)允许或阻止入站的presence通知.
  • 基于JID, 群组, 或者订阅类型(或者全部)允许或阻止出站的presence通知.
  • 基于JID, 群组, 或者订阅类型(或者全部)允许或阻止IQ节.
  • 基于JID, 群组, 或者订阅类型(或者全部)允许或阻止所有通讯.

注释:Presence通知不包括presence订阅,只包括那些已经被订阅了用户presence信息的,并且被广播到实体的presence信息.所以,它只包括了没有'type'属性或者type属性是'unavailable'的presence节.

语法和语义

一个用户可以定义一个或多个隐私列表,并且被存储在用户服务器上.每个<list/>元素在以<item/>元素形式里包含了一个或多个规则,并且每个<item/>元素用属性来定义来定义隐私规则类型,一个特别的值来表示哪个规则应用,相关动作,和项目处理的顺序中.

语法如下所示:

  <iq>
    <query xmlns='jabber:iq:privacy'>
      <list name='foo'>
        <item
            type='[jid|group|subscription]'
            value='bar'
            action='[allow|deny]'
            order='unsignedInt'>
          [<message/>]
          [<presence-in/>]
          [<presence-out/>]
          [<iq/>]
        </item>
      </list>
    </query>
  </iq>

如果type是'jid','value'的属性必须包含一个合法的JID.JIDs应该符合如下的法则.

  1. <user@domain/resource> (仅匹配那个资源)
  2. <user@domain> (匹配任何资源)
  3. <domain/resource> (仅匹配那个资源)
  4. <domain> (匹配域本身, 以及任何 user@domain 或 domain/resource)

如果type是"group", 那么'value'属性应该包含该用户名册中的一个组的名称. (如果一个客户端尝试从一个不存在于该用户名册中的组中更新, 创建, 或删除一个列表条目, 服务器应该给客户端返回一个<item-not-found/>节错误.)

如果type是"subscription", 那么'value'属性必须是如 RFC6121定义的 "both", "to", "from"之一, 或者 "none" , 这里 "none" 包括那些该用户完全不知道因而根本不在用户名册中的实体. 这些值是精确匹配的, 所以 "both" 意味着双向订阅(不是只有 "from" 或 "to" ).

如果没有包含'type'属性, 规则提供 "fall-through" 用例.

必须包含'action'属性并且它的值必须要么是"allow"要么是"deny". 4

必须包含'order'属性并且且它的值必须是一个在列表所有条目中具有唯一性的非负整数. (如果一个客户端尝试以不唯一的序号值来创建或更新一个列表, 服务器必须给客户端返回一个 <bad-request/> 节错误.)

<item/>元素可以包含一个或多个子元素使得一个实体能够定义对各种需要屏蔽的节的更细微的控制(即, 不只是屏蔽所有节). 允许的元素有:

  • <message/> -- 屏蔽进来的 message 节
  • <iq/> -- 屏蔽进来的 IQ 节
  • <presence-in/> -- 屏蔽进来的 presence 通知
  • <presence-out/> -- 屏蔽出去的 presence 通知 5

在'jabber:iq:privacy'命名空间中, 一个类型为"set"的IQ节<query/>子元素不能(MUST NOT)包含多个子元素(即, 该节必须只包含一个<active/>元素, 一个<default/>元素, 或一个<list/>元素); 如果发送实体违反了这个规则, 接收实体必须返回一个<bad-request/>节错误.

当一个客户端添加或更新一个隐私列表, <list/>元素应该至少包含一个<item/>子元素; 当一个客户端移除一个隐私列表, <list/>元素不能(MUST NOT)包含任何<item/>子元素.

当一个客户端更新一个隐私列表, 它必须包含所有期望的条目(即, 不是一个"增量").

商业规则

  1. 如果针对某个会话有一个 active 列表设置, 它只影响被激活的会话, 并且只用于该会话期间; 服务器必须只应用该 active 列表并且不能(MUST NOT)应用default列表(即, 列表们没有 "分层").
  2. default列表作为整体适用于该用户, 并且在没有针对某个节地址的目标会话/资源的active列表设置的情况下,或没有该用户的会话的情况下被处理.
  3. 如果没有针对某个会话的active列表设置(或没有该用户的当前会话), 并且没有default列表, 那么所有节应该被接受或被该用户所在的服务器本身根据RFC6121定义的处理XML节的服务器规则来做适当的处理.
  4. 服务器必须首先应用隐私列表的递送规则, 而不是 (1) RFC6121定义的处理XML节的服务器规则中的路由和递送规则 和 (2) RFC6121定义的和订阅相关的presence节的处理(以及对应的名册推送的生成).
  5. 隐私列表条目被服务器处理的顺序是很重要的. 列表条目必须以每个<item/>的'order'属性的数值所决定的升序来处理.
  6. 一旦某个节被匹配了某个隐私列表规则, 服务器必须遵循该规则处理该节并停止处理.
  7. 如果在一个列表中没有 fall-through 条目, 则假定 fall-through 动作为 "allow".
  8. 如果一个用户对一个active列表更新了定义, 基于那个active列表的随后的处理必须使用更新过的定义(对于那个active列表当前适用的所有资源).
  9. 如果在一个用户会话期间,在某个active列表或default列表中定义的订阅状态或名册条目的的名册组发生了改变, 基于那个列表的随后的处理必须考虑到变更的状态或组(对于那个列表当前适用的所有资源).
  10. 当一个规则的定义修改了, 服务器必须发送一个类型为"set"的IQ节给所有已连接的资源, 在该节中包含一个只带有一个<list/>子元素的<query/>元素, 这里'name'属性设置成被修改的隐私列表的名称. 这些"隐私列表推送"遵循和用在名册管理中的"名册推送"同样的语义, 除非列表名称本身(不是完整列表定义或"增量")被推送到已连接资源. 根据接收的资源来确定是否取回修改过的列表定义, 即使该列表当前适用的已连接资源应该这么做.
  11. 当一个资源尝试移除一个列表或指定一个新的default列表,那个列表适用于一个已连接资源而不是发送中的资源, 服务器必须返回一个<conflict/>错误给发送中的资源并且不能(MUST NOT)做出被请求的变更.

取回某人的隐私列表

示例1. 客户端向服务器请求隐私列表们的名称

<iq from='romeo@example.net/orchard' type='get' id='getlist1'>
<query xmlns='jabber:iq:privacy'/>
</iq>

示例2. 服务器发送隐私列表们的名称给客户端, 把active列表和default列表放在前面

<iq type='result' id='getlist1' to='romeo@example.net/orchard'>
<query xmlns='jabber:iq:privacy'>
  <active name='private'/>
  <default name='public'/>
  <list name='public'/>
  <list name='private'/>
  <list name='special'/>
</query>
</iq>

示例3. 客户端向服务器请求一个隐私列表

<iq from='romeo@example.net/orchard' type='get' id='getlist2'>
<query xmlns='jabber:iq:privacy'>
  <list name='public'/>
</query>
</iq>

示例4. 服务器发送一个隐私列表给客户端

<iq type='result' id='getlist2' to='romeo@example.net/orchard'>
<query xmlns='jabber:iq:privacy'>
  <list name='public'>
    <item type='jid'
          value='tybalt@example.com'
          action='deny'
          order='1'/>
    <item action='allow' order='2'/>
  </list>
</query>
</iq>

示例5. 客户端向服务器请求另一个隐私列表

<iq from='romeo@example.net/orchard' type='get' id='getlist3'>
<query xmlns='jabber:iq:privacy'>
  <list name='private'/>
</query>
</iq>

示例6. 服务器发送另一个我隐私列表给客户端

<iq type='result' id='getlist3' to='romeo@example.net/orchard'>
<query xmlns='jabber:iq:privacy'>
  <list name='private'>
    <item type='subscription'
          value='both'
          action='allow'
          order='10'/>
    <item action='deny' order='15'/>
  </list>
</query>
</iq>

示例7. 客户端再向服务器请求另一个隐私列表

<iq from='romeo@example.net/orchard' type='get' id='getlist4'>
<query xmlns='jabber:iq:privacy'>
  <list name='special'/>
</query>
</iq>

示例8. 服务器再发送另一个隐私列表给客户端

<iq type='result' id='getlist4' to='romeo@example.net/orchard'>
<query xmlns='jabber:iq:privacy'>
  <list name='special'>
    <item type='jid'
          value='juliet@example.com'
          action='allow'
          order='6'/>
    <item type='jid'
          value='benvolio@example.org'
          action='allow'
          order='7'/>
    <item type='jid'
          value='mercutio@example.org'
          action='allow'
          order='42'/>
    <item action='deny' order='666'/>
  </list>
</query>
</iq>

在这个例子中, 该用户有三个列表: (1) 'public', 它允许来自任何人的通讯,除了一个特定的实体(这是default列表); (2) 'private', 它只允许和该用户有双向订阅关系的联系人通讯(这是active列表); 和 (3) 'special', 它只允许和三个特定的实体的通讯.

如果该用户尝试取回一个列表但是那个名字的列表不存在, 服务器必须返回一个<item-not-found/>节错误给该用户:

示例. 客户端尝试取回不存在的列表

<iq to='romeo@example.net/orchard' type='error' id='getlist5'>
<query xmlns='jabber:iq:privacy'>
  <list name='The Empty Set'/>
</query>
<error type='cancel'>
  <item-not-found
      xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>

该用户只被允许一次取回一个列表. 如果该用户尝试在同一个请求中取回多个列表, 服务器必须返回一个<bad request/>节错误给该用户:

示例10. 客户端尝试取回多个列表

<iq to='romeo@example.net/orchard' type='error' id='getlist6'>
<query xmlns='jabber:iq:privacy'>
  <list name='public'/>
  <list name='private'/>
  <list name='special'/>
</query>
<error type='modify'>
  <bad-request
      xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>

管理active列表

为了设置或变更服务器当前应用的 active 列表, 该用户必须发送一个类型为"set", 含有'jabber:iq:privacy'命名空间限定的<query/>元素的IQ节,该节包含一个空的<active/>子元素,该子元素拥有一个'name'属性,属性值为期待的列表名称.

示例11. 客户端请求变更active列表

<iq from='romeo@example.net/orchard' type='set' id='active1'>
<query xmlns='jabber:iq:privacy'>
  <active name='special'/>
</query>
</iq>

服务器必须在发送结果给回客户端之前激活并应用请求的列表.

示例12. 服务器承认active列表变成成功

<iq type='result' id='active1' to='romeo@example.net/orchard'/>

如果用户城市设置一个active列表,但是那个名字所代表的列表不存在, 服务器必须返回一个<item-not-found/>节错误给该用户:

示例13. 客户端尝试设置一个不存在的列表成为active

<iq to='romeo@example.net/orchard' type='error' id='active2'>
<query xmlns='jabber:iq:privacy'>
  <active name='The Empty Set'/>
</query>
<error type='cancel'>
  <item-not-found
      xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>

为了撤销任何active列表, 已连接的资源必须发送一个空的<active/>元素,并且不带有'name'属性.

示例14. 客户端撤销active列表们的使用

<iq from='romeo@example.net/orchard' type='set' id='active3'>
<query xmlns='jabber:iq:privacy'>
  <active/>
</query>
</iq>

示例15. 服务器承认撤销任何active列表成功

<iq type='result' id='active3' to='romeo@example.net/orchard'/>

管理default列表

为了变成它的default列表(应用于该用户整体, 而不只是发送中的资源), 该用户必须发送一个类型为"set", 含有'jabber:iq:privacy'命名空间限定的<query/>元素的IQ节,该节包含一个空的 <default/>子元素,该子元素拥有一个'name'属性,属性值为期待的列表名称.

示例16. 用户请求变更default列表

<iq from='romeo@example.net/orchard' type='set' id='default1'>
<query xmlns='jabber:iq:privacy'>
  <default name='special'/>
</query>
</iq>

示例17. 服务器承认default列表变更成功

<iq typ='result' id='default1' to='romeo@example.net/orchard'/>

如果该用户尝试变更的列表是default列表,但是该default列表正在被至少一个和正在发送的资源不同的已连接的资源使用, 服务器必须返回一个<conflict/>节错误给正在发送的资源:

示例18. 客户端尝试变更default列表但是该列表正在被其他资源使用

<iq to='romeo@example.net/orchard' type='error' id='default1'>
<query xmlns='jabber:iq:privacy'>
  <default name='special'/>
</query>
<error type='cancel'>
  <conflict
      xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>

如果用户尝试设置一个default列表,但是该名字所代表的列表不存在, 服务器必须返回一个<item-not-found/>节错误给该用户:

示例19. 客户端尝试设置一个不存在的列表为default

<iq to='romeo@example.net/orchard' type='error' id='default1'>
<query xmlns='jabber:iq:privacy'>
  <default name='The Empty Set'/>
</query>
<error type='cancel'>
  <item-not-found
      xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>

为了撤销使用一个default列表(即, 任何时候都使用域的节路由规则), 用户必须发送一个空的<default/>元素,不带有'name'属性.

示例20. 客户端撤销使用default列表

<iq from='romeo@example.net/orchard' type='set' id='default2'>
<query xmlns='jabber:iq:privacy'>
  <default/>
</query>
</iq>

示例21. 服务器承认撤销default列表成功

<iq type='result' id='default2' to='romeo@example.net/orchard'/>

如果一个已连接的资源尝试整体撤销一个default列表的使用,但是该default列表当前正被应用于至少一个其他的已连接资源, 服务器必须返回一个<conflict/>错误给正在发送的资源:

示例22. 客户端尝试撤销一个default列表但是该列表正在被另一个资源使用

<iq to='romeo@example.net/orchard' type='error' id='default3'>
<query xmlns='jabber:iq:privacy'>
  <default/>
</query>
<error type='cancel'>
  <conflict
      xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>

编辑隐私列表

为了编辑一个隐私列表, 该用户必须发送一个类型为"set", 含有'jabber:iq:privacy'命名空间限定的<query/>元素的IQ节,该节包含一个<list/>子元素,该子元素拥有一个'name'属性,属性值为用户将要修改的列表名称. 这个<list/>元素必须包含一个或多个<item/>元素, 通过在该列表中包含所有元素(而非"增量")来定义该用户期待的修改.

示例23. 客户端编辑一个隐私列表

<iq from='romeo@example.net/orchard' type='set' id='edit1'>
<query xmlns='jabber:iq:privacy'>
  <list name='public'>
    <item type='jid'
          value='tybalt@example.com'
          action='deny'
          order='3'/>
    <item type='jid'
          value='paris@example.org'
          action='deny'
          order='5'/>
    <item action='allow' order='68'/>
  </list>
</query>
</iq>

示例24. 服务器承认列表编辑成功

<iq type='result' id='edit1' to='romeo@example.net/orchard'/>

注意: 对于任何给定的条目,'order'属性的值不是固定. 所以在前一个例子中,如果用户想在"tybalt@example.com"条目和"paris@example.org"条目之间增加4个条目, 该用户的客户端必须在提交该列表给服务器之前重新给条目编号.

现在服务器必须发送一个"privacy list push"给所有已连接资源:

示例25. 隐私列表推送列表编辑

<iq to='romeo@example.net/orchard' type='set' id='push1'>
<query xmlns='jabber:iq:privacy'>
  <list name='public'/>
</query>
</iq>
 
<iq to='romeo@example.net/home' type='set' id='push2'>
<query xmlns='jabber:iq:privacy'>
  <list name='public'/>
</query>
</iq>

根据 XMPP核心 7 中定义的IQ节的语义, 每个已连接资源必须返回一个IQ result给服务器,如下:

示例26. 承认收到隐私列表推送

<iq from='romeo@example.net/orchard'
  type='result'
  id='push1'/>
 
<iq from='romeo@example.net/home'
  type='result'
  id='push2'/>

新增隐私列表

新增一个新的列表和编辑一个现有的列表使用相同的协议. 如果该列表名字和现有列表匹配, 新增一个列表的请求将覆盖那个旧的列表. 和列表编辑一样, 服务器也必须发送一个"隐私列表推送"给所有已连接资源.

移除隐私列表

为了移除一个隐私列表, 该用户必须发送一个类型为"set", 含有'jabber:iq:privacy'命名空间限定的<query/>元素的IQ节,该节包含一个空的<list/>子元素,该子元素拥有一个'name'属性,属性值为用户将要移除的列表名称.

示例27. 客户端移除一个隐私列表

<iq from='romeo@example.net/orchard' type='set' id='remove1'>
<query xmlns='jabber:iq:privacy'>
  <list name='private'/>
</query>
</iq>

示例28. 服务器承认列表移除成功

<iq type='result' id='remove1' to='romeo@example.net/orchard'/>

如果一个用户场尝试移除一个当前被应用于至少一个和正在发送的资源不同的资源的列表, 服务器必须返回一个<conflict/>节错误给该用户; 即, 该用户在尝试移除它之前必须首先把另一个列表设置为active或default. 如果该用户尝试移除一个列表,但是那个名字所代表的列表不存在, 服务器必须返回一个<item-not-found/>节错误给该用户. 如果该用户尝试在同一个请求中移除多个列表, 服务器必须返回一个<bad request/>节错误给该用户.

屏蔽消息

服务器端的隐私列表允许一个用户基于实体的JID,名册组,或订阅状态(或全局地)来屏蔽从其他实体来的消息. 以下例子展示了该协议. (注意: 为了简洁起见, 类型为"result"的IQ节不放在接下来的例子中, "隐私列表推送"也不出现.)

示例29. 用户基于JID屏蔽

<iq from='romeo@example.net/orchard' type='set' id='msg1'>
<query xmlns='jabber:iq:privacy'>
  <list name='message-jid-example'>
    <item type='jid'
          value='tybalt@example.com'
          action='deny'
          order='3'>
      <message/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从指定JID的实体收到消息.

示例30. 用户基于名册组屏蔽

<iq from='romeo@example.net/orchard' type='set' id='msg2'>
<query xmlns='jabber:iq:privacy'>
  <list name='message-group-example'>
    <item type='group'
          value='Enemies'
          action='deny'
          order='4'>
      <message/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从指定名册组中的任何实体收到消息.

示例31. 用户基于订阅类型屏蔽

<iq from='romeo@example.net/orchard' type='set' id='msg3'>
<query xmlns='jabber:iq:privacy'>
  <list name='message-sub-example'>
    <item type='subscription'
          value='none'
          action='deny'
          order='5'>
      <message/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从指定订阅类型的任何实体收到消息.

示例32. 用户全局屏蔽

<iq from='romeo@example.net/orchard' type='set' id='msg4'>
<query xmlns='jabber:iq:privacy'>
  <list name='message-global-example'>
    <item action='deny' order='6'>
      <message/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从任何其他用户收到消息.

屏蔽入站出席信息通知

服务器端隐私列表允许用户基于实体的JID,名册组,或订阅状态(或全局地)屏蔽从其他实体来的出席信息通知. 以下例子展示了该协议.

注意: 出席信息通知不包括出席信息订阅, 只包括因为该用户当前订阅了某个联系人的出席信息,所以广播给该用户的出席信息. 所以只包括没有'type'属性或 type='unavailable'的出席信息节.

示例33. 用户基于JID屏蔽

<iq from='romeo@example.net/orchard' type='set' id='presin1'>
<query xmlns='jabber:iq:privacy'>
  <list name='presin-jid-example'>
    <item type='jid'
          value='tybalt@example.com'
          action='deny'
          order='7'>
      <presence-in/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从指定JID的实体收到出席信息通知.

示例34. 用户基于名册组屏蔽

<iq from='romeo@example.net/orchard' type='set' id='presin2'>
<query xmlns='jabber:iq:privacy'>
  <list name='presin-group-example'>
    <item type='group'
          value='Enemies'
          action='deny'
          order='8'>
      <presence-in/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从指定名册组中的任何实体收到出席信息通知.

示例35. 用户基于订阅类型屏蔽

<iq from='romeo@example.net/orchard' type='set' id='presin3'>
<query xmlns='jabber:iq:privacy'>
  <list name='presin-sub-example'>
    <item type='subscription'
          value='to'
          action='deny'
          order='9'>
      <presence-in/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从指定订阅类型的任何实体收到出席信息通知.

示例36. 用户全局屏蔽

<iq from='romeo@example.net/orchard' type='set' id='presin4'>
<query xmlns='jabber:iq:privacy'>
  <list name='presin-global-example'>
    <item action='deny' order='11'>
      <presence-in/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从任何其他用户收到出席信息通知.

注意: 如果一个客户端屏蔽了从一个以前可用的实体来的出席信息通知, 该用户的服务器应该代替那个联系人发送unavailable出席信息给该用户.(译者注:这合适吗?合适吗?合适吗?)

屏蔽出站出席信息通知

服务器端隐私列表允许用户基于实体的JID,名册组,或订阅状态(或全局地)屏蔽发给其他实体的出席信息通知. 以下例子展示了该协议.

注意: 出席信息通知不包括出席信息订阅, 只包括因为那些联系人当前订阅了该用户的出席信息,所以广播给那些联系人的出席信息. 所以只包括没有'type'属性或 type='unavailable'的出席信息节.

示例37. 用户基于JID屏蔽

<iq from='romeo@example.net/orchard' type='set' id='presout1'>
<query xmlns='jabber:iq:privacy'>
  <list name='presout-jid-example'>
    <item type='jid'
          value='tybalt@example.com'
          action='deny'
          order='13'>
      <presence-out/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会向指定JID的实体发送出席信息通知.

示例38. 用户基于名册组屏蔽

<iq from='romeo@example.net/orchard' type='set' id='presout2'>
<query xmlns='jabber:iq:privacy'>
  <list name='presout-group-example'>
    <item type='group'
          value='Enemies'
          action='deny'
          order='15'>
      <presence-out/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会向指定名册组中的任何实体发送出席信息通知.

示例39. 用户基于订阅类型屏蔽

<iq from='romeo@example.net/orchard' type='set' id='presout3'>
<query xmlns='jabber:iq:privacy'>
  <list name='presout-sub-example'>
    <item type='subscription'
          value='from'
          action='deny'
          order='17'>
      <presence-out/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会向指定订阅类型的任何实体发送出席信息通知.

40. 用户全局屏蔽

<iq from='romeo@example.net/orchard' type='set' id='presout4'>
<query xmlns='jabber:iq:privacy'>
  <list name='presout-global-example'>
    <item action='deny' order='23'>
      <presence-out/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会向任何其他用户发送出席信息通知.

注意: 如果一个客户端屏蔽了对一个联系人的出站出席信息通知, 该用户的服务器必须发送unavailable出席信息给该联系人(但仅限于根据 RFC 6121 定义的规则被允许从该用户收到出席信息通知的联系人)

屏蔽IQ节

服务器端隐私列表允许用户基于实体的JID,名册组,或订阅状态(或全局地)屏蔽从其他实体发来的IQ节. 以下例子展示了该协议.

示例41. 用户基于JID屏蔽

<iq from='romeo@example.net/orchard' type='set' id='iq1'>
<query xmlns='jabber:iq:privacy'>
  <list name='iq-jid-example'>
    <item type='jid'
          value='tybalt@example.com'
          action='deny'
          order='29'>
      <iq/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会收到从指定JID的实体发来的IQ节.

示例42. 用户基于名册组屏蔽

<iq from='romeo@example.net/orchard' type='set' id='iq2'>
<query xmlns='jabber:iq:privacy'>
  <list name='iq-group-example'>
    <item type='group'
          value='Enemies'
          action='deny'
          order='31'>
      <iq/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从指定名册组中的任何实体收到IQ节.

示例43. 用户基于订阅类型屏蔽

<iq from='romeo@example.net/orchard' type='set' id='iq3'>
<query xmlns='jabber:iq:privacy'>
  <list name='iq-sub-example'>
    <item type='subscription'
          value='none'
          action='deny'
          order='17'>
      <iq/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从指定订阅类型的任何实体收到IQ节.

示例44. 用户全局屏蔽

<iq from='romeo@example.net/orchard' type='set' id='iq4'>
<query xmlns='jabber:iq:privacy'>
  <list name='iq-global-example'>
    <item action='deny' order='1'>
      <iq/>
    </item>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从任何其他用户收到IQ节.

屏蔽所有通讯

服务器端隐私列表允许用户基于实体的JID,名册组,或订阅状态(或全局地)屏蔽从其他实体收到或发来的节.注意这包括了订阅相关的被“屏蔽入站出席信息通知”排除了的出席信息节. 以下例子展示了该协议.

示例45. 用户基于JID屏蔽

<iq from='romeo@example.net/orchard' type='set' id='all1'>
<query xmlns='jabber:iq:privacy'>
  <list name='all-jid-example'>
    <item type='jid'
          value='tybalt@example.com'
          action='deny'
          order='23'/>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从指定JID的实体收到或发送任何节.

示例46. 用户基于名册组屏蔽

<iq from='romeo@example.net/orchard' type='set' id='all2'>
<query xmlns='jabber:iq:privacy'>
  <list name='all-group-example'>
    <item type='group'
          value='Enemies'
          action='deny'
          order='13'/>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从指定名册组中的任何实体收到或发送任何节.

示例47. 用户基于订阅类型屏蔽

<iq from='romeo@example.net/orchard' type='set' id='all3'>
<query xmlns='jabber:iq:privacy'>
  <list name='all-sub-example'>
    <item type='subscription'
          value='none'
          action='deny'
          order='11'/>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从指定订阅类型的任何实体收到任何通讯或发送任何节.

示例48. 用户全局屏蔽

<iq from='romeo@example.net/orchard' type='set' id='all4'>
<query xmlns='jabber:iq:privacy'>
  <list name='all-global-example'>
    <item action='deny' order='7'/>
  </list>
</query>
</iq>

作为创建和应用前面的列表的结果, 该用户将不会从任何其他用户收到任何通讯或发送任何节.

被屏蔽实体尝试和用户通讯

如果一个被屏蔽的实体尝试发送一个节到该用户(即, 从该用户的角度来看的入站节), 该用户的服务器将根据以下规则处理该节:

  • 对于presence节(包括通知, 订阅, 和探测), 该服务器不能(MUST NOT)应答并且不能(MUST NOT)返回错误.
  • 对于message节, 该服务器应该返回一个错误, 这个错误应该是 <service-unavailable/>. 8
  • 对于类型为"get"或"set"的IQ节, 该服务器必须返回一个错误, 这个错误应该是 <service-unavailable/>. 其他类型的IQ节必须被服务器安静地放弃.

如果遵循了上述建议, 该用户在联系人看来将是离线状态.

示例49. 被屏蔽的实体尝试发送IQ get

<iq type='get'
  to='romeo@example.net'
  from='tybalt@example.com/pda'
  id='probing1'>
<query xmlns='jabber:iq:version'/>
</iq>

示例50. 服务器返回错误给被屏蔽的实体

<iq type='error'
  from='romeo@example.net'
  to='tybalt@example.com/pda'
  id='probing1'>
<query xmlns='jabber:iq:version'/>
<error type='cancel'>
  <service-unavailable
      xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>

如果该用户尝试发送一个出站节给一个联系人,并且那个节类型被屏蔽了, 该用户的服务器不能(MUST NOT)路由该节到该联系人,而必须返回一个<not-acceptable/>错误:

示例51. 错误: 联系人被屏蔽

<message type='error' from='romeo@montague.net' to='juliet@capulet.com'>
  <body>Can you hear me now?</body>
  <error type='cancel'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</message>

更高级的启发式

当建立一个更高级别的隐私启发式的表达的时候, 客户端应该使用尽可能简单的表达.

例如, 启发 "屏蔽任何不在我的名册中的用户的所有通讯" 可以被组织成以下任意方式之一:

  • 允许所有来自我名册的JID的通讯(即, 把每个JID列成单独的列表条目), 但是屏蔽其他人的通讯
  • 允许任何位于我的名册中的某个组的用户的通讯(即, 把每个组列为单独的列表条目), 但是屏蔽其他人的通讯
  • 允许任何我对其订阅状态为'both'或'to'或'from'的用户的通讯(即, 把每个订阅值单独列出来), 但是屏蔽其他人的通讯
  • 屏蔽任何订阅状态为'none'的用户的通讯

最后一个表达是最简单的所以应该被使用; 这里是本案例中要发送的XML:

<iq type='set' id='heuristic1'>
<query xmlns='jabber:iq:privacy'>
  <list name='heuristic-example'>
    <item type='subscription'
          value='none'
          action='deny'
          order='437'/>
  </list>
</query>
</iq>

发现支持

如果一个实体支持隐私列表协议, 它必须在对于服务发现 9 的信息请求的应答中包含一个"jabber:iq:privacy"(参见 协议命名空间关于一个或多个永久性命名空间的发行)服务发现特性来报告这一事实:

示例52. 服务发现信息请求

<iq from='juliet@example.com/chamber'
    id='disco1'
    to='example.com'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>

示例53. 服务发现信息应答

<iq from='example.com'
    id='disco1'
    to='juliet@example.com/chamber'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    ...
    <feature var='jabber:iq:privacy'/>
    ...
  </query>
</iq>

实现备注

当一个服务器从用户接收到一个屏蔽命令, 它可以取消任何该用户和被屏蔽用户之间的现有的出席信息订阅并且可以发送一个消息给被屏蔽的用户; 无论如何, 建议还是部署所谓"安静屏蔽"(即, 不取消出席信息订阅或不发送通知). 采取哪个办法取决于本地服务策略.

服务也可以在用户执行目录搜索时过滤屏蔽中的用户(参加, 例如, Jabber搜索 10); 无论如何, 那个功能超出了本协议的范围.

安全事项

如果适当地实现, 本协议扩展不会导致引入任何超出 RFC6120RFC6121 定义的新的安全问题.

IANA事项

本协议与互联网编号分配授权机构 11无关。

XMPP注册处事项

协议命名空间

XMPP注册处 12 已经把'jabber:iq:privacy'包含在它的协议命名空间的注册项中(见 <http://xmpp.org/registrar/namespaces.html>).

XML Schema

<?xml version='1.0' encoding='UTF-8'?>
 
<xs:schema
  xmlns:xs='http://www.w3.org/2001/XMLSchema'
  targetNamespace='jabber:iq:privacy'
  xmlns='jabber:iq:privacy'
  elementFormDefault='qualified'>
 
  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      XEP-0016: http://www.xmpp.org/extensions/xep-0016.html
    </xs:documentation>
  </xs:annotation>
 
<xs:element name='query'>
  <xs:complexType>
    <xs:sequence>
      <xs:element ref='active'
                  minOccurs='0'/>
      <xs:element ref='default'
                  minOccurs='0'/>
      <xs:element ref='list'
                  minOccurs='0'
                  maxOccurs='unbounded'/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
 
<xs:element name='active'>
  <xs:complexType>
    <xs:simpleContent>
      <xs:extension base='xs:NMTOKEN'>
        <xs:attribute name='name'
                      type='xs:string'
                      use='optional'/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:element>
 
<xs:element name='default'>
  <xs:complexType>
    <xs:simpleContent>
      <xs:extension base='xs:NMTOKEN'>
        <xs:attribute name='name'
                      type='xs:string'
                      use='optional'/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:element>
 
<xs:element name='list'>
  <xs:complexType>
    <xs:sequence>
      <xs:element ref='item'
                  minOccurs='0'
                  maxOccurs='unbounded'/>
    </xs:sequence>
    <xs:attribute name='name'
                  type='xs:string'
                  use='required'/>
  </xs:complexType>
</xs:element>
 
<xs:element name='item'>
  <xs:complexType>
    <xs:sequence>
      <xs:element name='iq'
                  minOccurs='0'
                  type='empty'/>
      <xs:element name='message'
                  minOccurs='0'
                  type='empty'/>
      <xs:element name='presence-in'
                  minOccurs='0'
                  type='empty'/>
      <xs:element name='presence-out'
                  minOccurs='0'
                  type='empty'/>
    </xs:sequence>
    <xs:attribute name='action' use='required'>
      <xs:simpleType>
        <xs:restriction base='xs:NCName'>
          <xs:enumeration value='allow'/>
          <xs:enumeration value='deny'/>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
    <xs:attribute name='order'
                  type='xs:unsignedInt'
                  use='required'/>
    <xs:attribute name='type' use='optional'>
      <xs:simpleType>
        <xs:restriction base='xs:NCName'>
          <xs:enumeration value='group'/>
          <xs:enumeration value='jid'/>
          <xs:enumeration value='subscription'/>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
    <xs:attribute name='value'
                  type='xs:string'
                  use='optional'/>
  </xs:complexType>
</xs:element>
 
<xs:simpleType name='empty'>
  <xs:restriction base='xs:string'>
    <xs:enumeration value=''/>
  </xs:restriction>
</xs:simpleType>
 
</xs:schema>

作者备注

Peter Millard, 本协议从版本0.1到版本0.3的作者, 去世于 April 26, 2006.

个人工具