Jabber 协议概述
作者: 来源:zz 发表时间:2007-03-29
浏览次数:
字号:大 中 小
5.3 <iq/>的子元素
下面介绍<iq/>元素的子元素。
5.3.1. <error/>
当iq的属性类型被设置为“error”时,将用到本属性。错误代码根据一个含有错误数的“type”属性进行定义,<error/>员司包含该错误的文本描述。比如,下面就是一个坏请求:
<error code="400">Bad Request</error>
在附录中,列有错误编码及其对应的错误描述。
5.3.2. <key/>
<key/>元素为客户端-服务器之间交互提供一层安全保护。它被用户jabber:iq:register和jabber:iq:search名字空间中。
当一个客户端发起一个与服务其之间的交互时,服务器将发送一个包含一个唯一值的<key>给客户端。客户端在返回<iq type=”set”/>的消息中,包含上诉唯一值到<key/>子元素中。这样,服务器就认为该客户端时接收到原来密码的同一实体。
5.3.3. <query/>
<iq/>元素中的<query/>子元素定义所执行的查询的类型。特殊情况下,查询可以拥有一个特殊的名字空间,这个名字空间是一个通过“xmlns”属性定义的<query/>子元素。一个<iq/>元素中只能有一个<query/>子元素。
下面的例子是当我通过我的Linux机器上的Grabber客户端登陆到服务器上,将出现的XML。
<iq type="set">
<query xmlns="jabber:iq:auth">
<username>stpeter</username>
<resource>Gabber</resource>
<digest>f1e881517e9917bb815fed112d81d32b4e4b3aed</digest>
</query>
</iq>
就象你看到的那样,认证查询通过客户端认证名字空间(jabber:iq:auth)向服务器发送认证信息。一般,Jabber核心协议保留jabber:iq:*这样的名字空间。而开发者可以通过增加jabber:iq:*名字空间对Jabber核心进行扩展。这些将在下面的名字空间中进行更完整的描述。
一个空<query/>子元素可以与<iq type=”get”>元素一起发送,这样可以找回与<query/>子元素中指定的名字空间相关的一个Jabber实体的信息。比如,找回一个客户端的花名册(“联系人名单”),下面的XML可以被发送:
<iq to="juliet@capulet.com/balcony" type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
6. 名字空间
现面是Jabber中的标准名字空间:
l jabber:iq:agent——代理工具
l jabber:iq:agents——有效的代理组
l jabber:iq:auth——简单用户认证
l jabber:iq:autoupdate——版本更新申请
l jabber:iq:browse——Jabber浏览
l jabber:iq:conference——一般会议
l jabber:iq:gateway——用户地址网关
l jabber:iq:last——上次使用时间
l jabber:iq:oob——绑定数据输出
l jabber:iq:private——私有数据存储
l jabber:iq:register——注册请求
l jabber:iq:roster——花名册(联系人名单)管理
l jabber:iq:search——用户数据库查询
l jabber:iq:time——客户端时间
l jabber:iq:version——客户端版本
l jabber:x:autoupdate——版本通知申请
l jabber:x:conference——会议邀请
l jabber:x:delay——显示的对象
l jabber:x:encrypted——加密的消息
l jabber:x:envelope——消息封套
l jabber:x:event——消息事件
l jabber:x:expire——消息终止
l jabber:x:oob——绑定数据(文件传输)输出
l jabber:x:roster——内部的花名册条目
l jabber:x:signed——标记的在线状态
l vcard-temp——临时的vCard
下面将详细介绍这些名字空间的细节。
6.1. jabber:iq:agent——代理工具
代理工具名字空间包含一个代理的所有工具。jabber:iq:angents查询通常用于注册到一个指定的服务、代理、传输器。
它也可能检验一个指定代理的所有工具细节。比如,一个客户端可以决定一个开放的注册是否可以进行。
例子:
<iq id="wjAgent" type="result" from="Jabber.org">
<query xmlns="jabber:iq:agent">
<agent jid="aim.jabber.org">
<name>AIM Transport</name>
<description>This is the AIM Transport</description>
<transport>AIM/AOL ScreenName</transport>
<service>aim</service>
<register/>
</agent>
</query>
</iq>
6.2. jabber:iq:angents——可用的代理列表
可用代理列表名字空间包含一组实体,这些实体拥有一些特殊工具,并能够为另一个实体提供服务。大多数情况下,可用代理列表是用来显示一台服务器上的可用传输器列表。
注意:这个名字空间被jabber:iq:browse的支持者所反对(??)。
例子:
<iq id="wjAgents" type="result" from="jabber.org">
<query xmlns="jabber:iq:agents">
<agent jid="users.jabber.org">
<name>User Directory</name>
<description>
You may register and create a public searchable
profile, and search for other registered Jabber
users.
</description>
<service>jud</service>
<register/>
<search/>
</agent>
<agent jid="aim.jabber.org">
<name>AIM Transport</name>
<description>This is the AIM Transport</description>
<transport>AIM/AOL ScreenName</transport>
<service>aim</service>
<register/>
</agent>
</query>
</iq>
6.3. jabber:iq:auth——简单客户端认证
简单客户认证名字空间是对客户端进行认证的一个简单机制,它为客户端到服务器之间的连接创建一个资源。
认证成功返回一个type=”result”的IQ响应。不成功,就返回一个错误IQ元素。
如果没有发送名字空间或密码,如果服务器允许,服务器将创建一个匿名资源。
例子:
<iq type="set" id="JCOM_0">
<query xmlns="jabber:iq:auth">
<username>juliet</username>
<password>secret</password>
<resource>balcony</resource>
</query>
</iq>
<iq type="set" id="JCOM_0">
<query xmlns="jabber:iq:auth">
<username>juliet</username>
<digest>a5e052c48c455bf21d937ccf17225916d9486b09</digest>
<resource>balcony</resource>
</query>
</iq>
<iq type="set" id="JCOM_0">
<query xmlns="jabber:iq:auth">
<username>juliet</username>
<hash499>secret</hash499>
<resource>balcony</resource>
</query>
</iq>
6.4. jabber:iq:autoupdate——版本更新申请
版本更新申请名字空间允许客户端对所有可用软件更新进行申请请求。
例子:
<iq type="get" to="jabber.org" id="1">
<query xmlns="jabber:iq:autoupdate"/>
</iq>
6.5. jabber:iq:browse——Jabber浏览
Jabber浏览名字空间的作用是,一是为Jabber世界中已有的Jabber IDs增加结构的一个途径,一是发现为不同Jabber实体提供的服务或应用。一个Jabber浏览的基本概念就是一个jid-type(类似文件的一个模拟类型的概念)。下面是想象中的最高级别的jid-types,不过随着时间的推移,一些其它的逻辑将被增加进来:
l 应用
l 会议
l 标题
l 关键字
l 回报
l 服务
l 用户
上面每一个范畴都有一个子类列表,如用户/客户端,或用户/设备(“客户端”或“设备”只是一个“资源”的概念),会议/irc,服务/icq,标题/库存。一般的,通过使用jabber:iq:browse名字空间你将拥有一个与上述某一jid-type范畴相对应的元素,这个元素通常有一个指定子类型的“type”属性。
Jabber:iq:browse的一个用户就是代替jabber:iq:agents名字空间来列出一个服务器上所对应的代理或其它服务。下面是一个浏览服务器的例子:
Jabber客户端发送:
<iq type="get" to="jabber.org">
<query xmlns="jabber:iq:browse"/>
</iq>
Jabber服务器返回:
<iq type="result" from="jabber.org">
<service
type="jabber"
jid="jabber.org"
xmlns="jabber:iq:browse>
<service
type="jud"
jid="users.jabber.org"
name="Jabber User Directory">
<ns>jabber:iq:register</ns>
<ns>jabber:iq:search</ns>
</service>
<service
type="aim"
jid="aim.jabber.org"
name="AIM Transport">
<ns>jabber:iq:register</ns>
<ns>jabber:iq:search</ns>
</service>
<conference
type="private"
jid="conference.jabber.org"
name="Private Chatrooms">
</service>
</service>
</iq>
在会议中的一个例子:
<iq type="set" to="room@server">
<conference xmlns="jabber:iq:browse" name="Room Name">
<user jid="room@server/jidhash" name="nick1"/>
<user jid="room@server/jidhash" name="nick2"/>
</conference>
</iq>
6.6. jabber:iq:conference——一般会议
一般会议名字空间提供一个会议室的机制(如群组聊天室),并提供该会议室的入口。这个名字空间与</iq>元素配套使用来获得一个会议室的信息,包括要求加入这个会议室的请求信息,以及为这个会议室设置信息(通常是为了加入这个房间)。一个普通进入房间的请求将和下面的类似:
1. 想要加入的房间提交一个type=”get”的请求。这个XML将是下面的形式:
<iq type="get" to="room@server">
<query xmlns="jabber:iq:conference"/>
</iq>
2. 接受来自要加入的房间的type=”result”的iq响应,其中有进入房间所需要的参数。这个XML将是下面的形式:
<iq type="result" from="room@server">
<query xmlns="jabber:iq:conference">
<nick/>
<secret/>
<privacy/>
<name>Room Name</name>
</query>
</iq>
这里所有的请求元素的子元素都是可选的。昵称(nickname)元素表示进入房间需要一个昵称。密钥(secret)元素表示进入房间的用户需要提供一个密码。独处(privacy)元素表示如果用户在一个type=”set”(下面可以看到例子)的iq包中提供这样的元素,会议服务器将隐藏用户的真实Jabbere ID。名字(name)元素是房间的名字(用jabber:iq:browse浏览房间时可以看到同样的房间名)。
3. 发送当前状态给要加入的房间。XML如下:
<presence to="room@server"/>
4. 想要加入的房间提交一个type=”set”的iq包以及进入所需信息。XML如下:
<iq type="set" to="room@server">
<query xmlns="jabber:iq:conference">
<nick>mynick</nick>
<nick>mysecondnick</nick>
<secret>thesecret</secret>
</query>
</iq>
注意在用户第一个选择被接受时,用户可以提交多个昵称。如果用户没有提供昵称,服务器将指派一个昵称给用户。
5. 收到你加入的房间的通知,这个iq以下面的格式返回:
<iq type="result" from="room@server">
<query xmlns="jabber:iq:conference">
<id>room@server/uniqueidnumber</id>
<nick>mynick</nick>
</query>
</iq>
这个唯一的ID号是用户Jabber ID的一个哈希。
6.7. jabber:iq:gateway——用户地址网关
一般通过一个网关或传输器(比如AIM传输器)来实现与非Jabber网络用户的通信,每一个非Jabber网络都可能拥有唯一的用户地址,这个地址可能和Jabber IDs并不统一。用户地址网关就是解决这个问题的,它使得Jabber客户端向非Jabber网络用户发出订阅时给出正确Jabber IDs变得很容易。这些通过对用户进行提示和会话,引导用户提供创建一个正确Jabber ID所需信息来实现。下面将演示这种普通的交互:
1. 客户端向网关发出带有jabber:iq:gate名字空间查询的iq get:
<iq type="get" to="aim.jabber.org">
<query xmlns="jabber:iq:gateway"/>
</iq>
2. 服务器返回一个包含请求批准及其描述文本的iq:
<iq type="result" from="aim.jabber.org">
<query xmlns="jabber:iq:gateway">
<desc>
Please enter the AOL Screen Name of the person
you would like to contact.
</desc>
<prompt>Screen Name</prompt>
</query>
</iq>
3. 客户端向网关发送一个包含指定信息的iq set:
<iq type="set" to="aim.jabber.org">
<query xmlns="jabber:iq:gateway">
<prompt>Joe Cool</prompt>
</query>
</iq>
4. 服务器返回一个包含正确Jabber ID的iq result
<iq type="result" from="aim.jabber.org">
<query xmlns="jabber:iq:gateway">
<jid>JoeCool@aim.jabber.org</jid>
</query>
</iq>
6.8. jabber:iq:last——最后一次在线时间
最后一次在线时间名字空间提供一个标准的方法,通过这个方法可以查询一个Jabber实体一个或多个服务更新时间,或者一个客户最后一次连接(或活动)到一台服务器上的时间。每一次返回的值都是一个秒的数目。进行查询的实体可以通过下面的法则解释获取的信息:
l user@server/resource——用户最后一次活动的时间
l user@server——用户最后一次连接的时间
l server——服务器最后一次启动的时间
例子(服务器):
<iq type="get" to="jabber.org">
<query xmlns="jabber:iq:last"/>
</iq>
<iq type="result" to="stpeter@jabber.org/Gabber" from="jabber.org">
<query xmlns="jabber:iq:last" seconds="124933"/>
</iq>
例子(客户端):
<iq type="get" to="jer@jabber.org">
<query xmlns="jabber:iq:last"/>
</iq>
<iq type="result" to=stpeter@jabber.org/Gabber from="jer@jabber.org">
<query xmlns="jabber:iq:last" seconds="5024">
Disconnected
</query>
</iq>
6.9. jabber:iq:oob——绑定数据输出
绑定数据输出名字空间为客户端-客户端的文件传输提供一个标准方法,通过服务器的传输/代理的传输器实现一个特殊的名字空间:
例子:
<iq type="set" to="horatio@denmark.com" id="file_1">
<query xmlns="jabber:iq:oob">
<url>http://denmark.com/act4/letter-1.html</url>
<desc>There’s a letter for you sir.</desc>
</query>
</iq>
6.10. jabber:iq:private——私有数据存储
私有数据存储名字空间是Jabber服务器上存储私有数据的一个机制。存储的数据可以是任何合法的XML数据。在服务端存放客户端的当前状态信息是这个名字空间的典型用法。
例子1(客户端存储私有数据):
<iq type="set" id="1001">
<query xmlns="jabber:iq:private">
<winjab xmlns="winjab:prefs">
<defaultnick>Hamlet</defaultnick>
</winjab>
</query>
</iq>
例子2(客户端找回私有数据):
<iq type="get" id="1002">
<query xmlns="jabber:iq:private">
<winjab xmlns="winjab:prefs"/>
</query>
</iq>
另外,对于私有数据存储,1.4版服务器支持服务器上所有有效名字空间(以“jabber”开头的名字空间保留,为Jabber系统进行调用)的XML数据。这个数据存在向服务器端发送type=”set”的iq包的用户的花名册中。
例子1(客户端保存公有数据):
<iq type="set" id="1003">
<query xmlns="stpeter:public:favorites">
<fav_things>
<food>Thai</food>
<color>blue</color>
<composer>Bach</composer>
</fav_things>
</query>
</iq>
例子2(客户端找回公有数据):
<iq type="get" id="1004">
<query xmlns="stpeter:public:favorites">
<fav_things/>
</query>
</iq>
6.11. jabber:iq:register——注册请求
注册请求名字空间对一个或多个服务进行注册。它也被用来更新或删除一个注册。
例子:
<query xmlns="jabber:iq:register">
<instructions>
Some instructions to be displayed when the
user is filling out the form.
</instructions>
<username/>
<password/>
<email/>
<date/>
<key/>
</query>
6.12. jabber:iq:roster——联系人名单管理
联系人名单管理名字空间是客户端用来管理他们的花名册的,该花名册保存在服务器上,这样用户可以在任何地方得到它。花名册是该帐号上所有订阅信息的命令列表,包括用户昵称和联系列表。当用户从任何一个资源登陆上来,服务器将把花名册发送给用户。
花名册是一个条目的列表。每一个条目元素都有描述它的属性。每一个条目元素都包含它所属组的组元素。下面是描述<item/>元素的属性:
l “jid”是条目的Jabber ID
l “subscription”所有和本条目相关的订阅所对应的用户的当前状态。它可以是“none”(不可订阅),“to”(有一个发到该条目的订阅),“from”(从该条目发送一个订阅给我们),“both”(to、from),或者“remove”(从花名册上删除一个条目)。
l “ask”是对这个条目的一个请求的当前状态。Subscribe表示请求对该条目进行订阅,它的值就是,Unsubscribe表示取消订阅。
l “name”表示昵称
通过使用一个<iq type=”set”/>,一个Jabber客户端可以控制用户的JabberID,名称属性,群组元素,并且可以在联系人名单上创建或删除联系人。服务器根据客户端对当前状态订阅请求的响应来管理其它所有属性。
订阅请求的例子:
<iq type="set" id="uniquevalue">
<query xmlns="jabber:iq:roster">
<item jid="romeo@montague.net"
name="Romeo"
subscription="none"
ask="subscribe">
<group>friends</group>
</item>
</query>
</iq>
当一个花名册条目在服务器上改变时,服务器将把这个改变推送给一个用户。这个推送是一个普通的从服务器发送到客户端的<iq type=”set”/>包。下面是一个例子:
<iq type="set">
<query xmlns="jabber:iq:roster">
<item jid="romeo@montague.net" subscription="both"/>
</query>
</iq>
在上面的例子中,服务器推送给客户端一个花名册,表明该用户对romeo@montague.net的当前状态信息有订阅。一个花名册推送可能发生一个连接的任何时间中,该连接是另一个连接修改资源或服务器(修改订阅属性)的结果。客户端只有使用花名册推送来改变花名册的显示。但不是每次花名册推送都对用户起作用。
6.13. jabber:iq:search——用户数据库查询
任何一个代理都可以成为一个查询代理。例如,JUD查询Jabber用户,ICQ传输器查询ICQ用户。
用户发送一个进行可查询域的Get请求:
<iq
type="get"
id="1001"
to="users.jabber.org"
from="romeo@montague.net/orchard">
<query xmlns="jabber:iq:search"/>
</iq>
查询代理返回一个可查域:
<iq type="result" id="1001" from="users.jabber.org">
<query xmlns="jabber:iq:search">
<instructions>Fill in a field to search for any
matching Jabber User
</instructions>
<name/>
<first/>
<last/>
<nick/>
<email/>
<key>067941fd96a6a2752a21abcb6d737130dd51dd50</key>
</query>
</iq>
注意这些域是以提示的形式返回。为了传输的安全还包含一个密钥(下面会看到)。用户现在可以在允许的域内进行标准的查询了。用户发回一个Set请求给代理进行实际查询:
<iq
type="set"
id="1002"
to="users.jabber.org"
from="romeo@montague.net/orchard">
<query xmlns="jabber:iq:search">
<last>Capulet</last>
<key>11b830e604215c3a2a24652c69fd4efa2a7a5746</key>
</query>
</iq>
服务器根据查询返回结果:
<iq type="result" id="1002" from="users.jabber.org">
<query xmlns="jabber:iq:search">
<item jid="juliet@capulet.com">
<name>Juliet Capulet</name>
<first>Juliet</first>
<last>Capulet</last>
<nick>juliC</nick>
<email></email>
</item>
<item jid="sampson@capulet.com>
<name>Sampson Capulet</name>
<first>Sampson</first>
<last>Capulet</last>
<nick>sammy</nick>
<email></email>
</item>
</query>
</iq>
注意有两套items标记含有指定信息。这是因为通过代理发送返回有两种方法:
l 单一返回标签
l 多个“pushed”到用户的标签,类似花名册推送,如在一个时间上的一个记录。
发送的返回的样式是查询代理的一个工具。比如:
<iq type="set" from="icq.jabber.org" id="1003">
<query xmlns="jabber:iq:search">
<item jid="7090245@icq.jabber.org">
<email>juliet@capulet.com</email>
<nick>juliC</nick>
<given>Juliet</given>
<family>Capulet</family>
</item>
</query>
</iq>
多个查询结果通过服务器进行推送。当所有数据发送完毕,服务器将发送下面的返回结果:
<iq type="result" from="icq.jabber.org" id="1003">
<query xmlns="jabber:iq:search"/>
</iq>
客户端接收到多个“sets”,每一个都被记录,最后收到一个表示“数据结尾”的“返回”。在每一个<item>标签中,JID属性都被强制带上。
例子:
<iq
type="get"
id="1001"
to="users.jabber.org"
from="juliet@capulet.com">
<query xmlns="jabber:iq:search"/>
</iq>
6.14. jabber:iq:time——客户端时间
客户端时间名字空间是客户端改变当前时间的一个标准方法。
例子:
<iq type="result" from="stpeter@jabber.org">
<query xmlns="jabber:iq:time">
<utc>20010214T18:55:06</utc>
<display>2/15/00 4:55:06 PM</display>
</query>
</iq>
6.15. jabber:iq:version——客户端版本
客户端版本名字空间是得到另一个用户的客户端的版本信息的一个标准方法。
例子:
<iq type="result" from="stpeter@jabber.org/Gabber">
<query xmlns="jabber:iq:version">
<name>Gabber</name>
<version>0.8.1 (Powered by: jabberoo 1.0.0</version>
<os>Linux 2.2.16-22 i686</os>
</query>
</iq>
6.16. jabber:x:autoupdate——应用程序版本通知
版本更改申请名字空间使服务器可以在一个应用的新版本可用时通知客户端。
例子:
<message from="winjab.sourceforge.net">
<x xmlns="jabber:x:autoupdate">A new version of WinJab
is available, see http://winjab.sourceforge.net/
</x>
</message>
6.17. jabber:x:conference——会议邀请
会议邀请名字空间使用户可以邀请其它Jabber用户到指定会议室。相关联信息——该会议室的Jabber ID,内嵌在一个消息的<x/>元素中。
例子:
<message to="romeo@montague.net" from="juliet@capulet.com">
<body>Wherefore art thou Romeo?</body>
<x xmlns="jabber:x:conference" jid="balcony@conference.capulet.com/>
</message>
6.18. jabber:x:delay——标记对象延时
标记对象延时名字空间是消息和当前状态信息的时间戳信息,其中,当一个Jabber实体不在线时,当前状态信息可以保存并在稍后发送。当实体上线时,包含的信息标记对象延时名字空间使Jabber客户端显示出该包体最早产生的时间,而不是它发送给Jabber实体的时间。
例子:
<message
type=’groupchat’
from=’cauldron@conference.witches.org’>
<body>Thrice the brinded cat hath mew’d.</body>
<x xmlns=’jabber:x:delay’
stamp=’10541031T21:43:40’>Cached In GC History</x>
</message>