注册请求名字空间对一个或多个服务进行注册。它也被用来更新或删除一个注册。
例子:
<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>
联系人名单管理名字空间是客户端用来管理他们的花名册的,该花名册保存在服务器上,这样用户可以在任何地方得到它。花名册是该帐号上所有订阅信息的命令列表,包括用户昵称和联系列表。当用户从任何一个资源登陆上来,服务器将把花名册发送给用户。
花名册是一个条目的列表。每一个条目元素都有描述它的属性。每一个条目元素都包含它所属组的组元素。下面是描述<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="[email protected]"
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="[email protected]" subscription="both"/>
</query>
</iq>
在上面的例子中,服务器推送给客户端一个花名册,表明该用户对[email protected]的当前状态信息有订阅。一个花名册推送可能发生一个连接的任何时间中,该连接是另一个连接修改资源或服务器(修改订阅属性)的结果。客户端只有使用花名册推送来改变花名册的显示。但不是每次花名册推送都对用户起作用。
任何一个代理都可以成为一个查询代理。例如,JUD查询Jabber用户,ICQ传输器查询ICQ用户。
用户发送一个进行可查询域的Get请求:
<iq
type="get"
id="1001"
to="users.jabber.org"
from="[email protected]/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="[email protected]/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="[email protected]">
<name>Juliet Capulet</name>
<first>Juliet</first>
<last>Capulet</last>
<nick>juliC</nick>
<email></email>
</item>
<item jid="[email protected]>
<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="[email protected]">
<email>[email protected]</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="[email protected]">
<query xmlns="jabber:iq:search"/>
</iq>
客户端时间名字空间是客户端改变当前时间的一个标准方法。
例子:
<iq type="result" from="[email protected]">
<query xmlns="jabber:iq:time">
<utc>20010214T18:55:06</utc>
<display>2/15/00 4:55:06 PM</display>
</query>
</iq>
客户端版本名字空间是得到另一个用户的客户端的版本信息的一个标准方法。
例子:
<iq type="result" from="[email protected]/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>
版本更改申请名字空间使服务器可以在一个应用的新版本可用时通知客户端。
例子:
<message from="winjab.sourceforge.net">
<x xmlns="jabber:x:autoupdate">A new version of WinJab
is available, see http://winjab.sourceforge.net/
</x>
</message>
会议邀请名字空间使用户可以邀请其它Jabber用户到指定会议室。相关联信息——该会议室的Jabber ID,内嵌在一个消息的<x/>元素中。
例子:
<message to="[email protected]" from="[email protected]">
<body>Wherefore art thou Romeo?</body>
<x xmlns="jabber:x:conference" jid="[email protected]/>
</message>
标记对象延时名字空间是消息和当前状态信息的时间戳信息,其中,当一个Jabber实体不在线时,当前状态信息可以保存并在稍后发送。当实体上线时,包含的信息标记对象延时名字空间使Jabber客户端显示出该包体最早产生的时间,而不是它发送给Jabber实体的时间。
例子:
<message
type=’groupchat’
from=’[email protected]’>
<body>Thrice the brinded cat hath mew’d.</body>
<x xmlns=’jabber:x:delay’
stamp=’10541031T21:43:40’>Cached In GC History</x>
</message>
加密消息名字空间用来支持使用公共密钥(一般通过客户端使用PGP或GPG,服务端用同样的名字空间进行加密来实现)加密的消息交互。一个相关的名字空间,jabber:x:signed,用来进行当前状态信息的加密。
例子:
<message from=’[email protected]/balcony’ to=’[email protected]/orchard’>
<body>This Message is Encrypted</body>
<x xmlns=’jabber:x:encrypted’>
hQEOA7ucqu53AhlPEAP/ZbU6oPnRAbIcUxMK1XRVnkgZ/Agtq1tcTQuEZxbpZLl4
C/4psQGLgBU5h5Y3/khxtJTPXKn1izyc+DRZ8hqn2p4mwC8ioKTBJ6P6dfEpQEyt
a4bimM5fqdeh4gRkMhwThRSJxBCJBVVWFEViu+0KlHHB5AeeL4qwRGb2dhGjIgQD
/R9x0D0qtgBGwf/TVnRGZYRX7epxCNuNDEYKZSs4LEoTPL8CVsAWOzS2QgS0GBqt
tFDKId6XaNu36dB2D8VHdxQnI8RtHo9pfTYDaXWB3dMGTt896iEO/sTuucYObf3s
K5Kygg0uWpBpvQPj8Y041FhnUBz8DRGCnuFLQxCI6ch4ybauXfOKNOGDQwmsnJZm
6OaeVFUwdsedI3c6VdQtodnWVutckR5BOjnn0VqnhrVTu7cp6VXrrRK4g9atPEe6
C4R/MilBjzIJBcET0jhWuAyiBo3gN/6IqYRZNSXL9ZqGPJwNTlYim1EHN3qBqiUw
zUMamEoRzcusn80Z7kylve5ujIeSD/pVwoawHHvLp92kO2hd0yGD0UrWSfKU1o6y
EY8yhZ5P1v02pIKigAUI2c6LTDxt/KhSxQ==
=fijN
</x>
</message>
消息信封名字空间是表明消息有更多的寻址方式,如联合email进行的寻址。下面是一些所支持的名字空间:
l to
l cc
l replyto
l from
l forwardedby
上述每一个元素都带有一个”jid”属性来标识Jabber实体是发送、中转、还是收到消息。
例子:
<message from=’[email protected]/tomb’ to=’[email protected]/tomb’>
<body>And there I am. Where is my Romeo?</body>
<x xmlns=’jabber:x:envelope’>
<to jid=’[email protected]>Romeo</to>
<forwardedby jid=’[email protected]>God</forwardedby>
</x>
</message>
消息时间名字空间是标识一条消息的状态的一个机制。现在,事件与一条消息如下般相关联:
l <composing/>——个用户正在对消息进行回复
l <delivered/>——发送给指定接收者的消息
l <displayed/>——显示给指定接收者的消息
l <offline/>——为离线进行存储的消息
对于客户端来说,这些消息事件的支持是可选的,而且,只有在另一用户在聊天中发出请求,这些消息事件才会被发送。不同的Jabber客户端将对当前状态消息事件进行不同的显示。
对消息通知的请求的例子:
<message
from="[email protected]/balcony"
to="[email protected]/orchard"
id="1001">
<body>By whose direction found’st thou out this place?</body>
<x xmlns="jabber:x:event">
<composing/>
</x>
</message>
发送消息通知的例子:
<message from="[email protected]/orchard" to="[email protected]/balcony">
<body>By whose direction found’st thou out this place?</body>
<x xmlns="jabber:x:event">
<composing/>
<id>1001<id/>
</x>
</message>
可以同时请求多个消息事件。
消息到期名字空间是说明一条消息拥有一个有限的存活事件的一个简单扩展。如果消息被离线存储,而到了到期时间,服务器将不再发送该消息。如果一条消息为预览就进行发送,Jabber客户端可以选择不显示该消息。“secondes”属性定义消息发送的事件。
例子:
<message from="[email protected]" to="[email protected]">
<body>There’s a letter for you sir</body>
<x xmlns="jabber:x:expire" seconds="3600"/>
</message>
绑定数据输出名字空间使用户可以通过交换一个标准的URL来实现文件传输的目电。使用jabber:x:oob的URLs交换可以包含任一消息(在一个<x/>子元素内),感觉就像email里的附件一样。多个附件可以包含在同一个消息中。
例子:
<message from="[email protected]" to="[email protected]">
<body>URL Attached.</body>
<x xmlns="jabber:x:oob">
<url>http://denmark.com/act4/letter-1.html</url>
<desc>There’s a letter for you sir</desc>
</x>
</message>
内置的花名册条目使用户可以在一个消息中包含花名册条目,这样很容易在用户之间发送联系方式。每一个花名册条目都包含在一个<x/>的一个<item/>子元素中。这个<x/>元素一般用在一个<message/>元素中,但这不是必须的。
例子:
<message to="[email protected]">
<body>
Here are some new Jabber users
to add to your contact list!
</body>
<x xmlns="jabber:x:roster">
<item jid="[email protected]" name="King">
<group>Royalty</group>
</item>
<item jid="[email protected]" name="Horatio">
<group>Friends</group>
</item>
<item jid="fortinbras@norway" name="Prince Fortinbras"/>
</x>
</message>
有符号的当前状态名字空间用来支持交换使用公共密钥(客户端使用PGP或GPG,服务端使用同样的名字空间进行加密)加密的当前状态信息。一个相关的名字空间,jabber:x:encrypted用来支持加密消息。
例子:
<presence from=’[email protected]/balcony’ to=’[email protected]/orchard’>
<show>away</show>
<status>be back later</status>
<x xmlns=’jabber:x:signed’>
iD8DBQA6kasv0xpc2/POfPkRAnz0AJ9UEYYWWSReddIKk3AYMfTFtqQDJwCfbcLd
JcSUOR0FlS+rDFjAPaSMgSM+iNaNm
</x>
</presence>
vCard格式是一个“电子商务卡的标准格式,通过使用通过互联网进行个人数据的直接交换,如同在非互联网下的环境一样”。由于XML的vCard的格式还没有标准化,Jabber.org项目在XML的vCard标准建立之前,暂时设置了这样一个临时名字文件。由于这几年在vCard的XML的官方标准的指定上没有任何进步,Jabber.org开发者专门为这个项目创建了一个项目吸引Jabber社区外其它开发者的注意。因此,最后的XML的vCard格式的最后DTD可能会在下面的URL中找到:
http://www.vcard-xml.org/
例子1(对vCard的客户端请求):
<iq type="get">
<vCard xmlns="vcard-temp"/>
</iq>
例子2(客户端收到vCard数据):
<iq type="result">
<vCard version="3.0" xmlns="vcard-temp">
vCard data goes here
</vCard>
</iq>
例子3(客户端向服务端发送vCard):
<iq type="set">
<vCard version="3.0">
vCard data goes here
</vCard>
</iq>
这一部分提供一些在Jabber协议上略有不同的观点,通过用例来阐述。下面每一个例子都展示一个Jabber用户完成一个完整的任务的消息流程,该流程包括接收和发送,如注册到一台服务器,登陆,改变当前状态,或者发送一条消息。如果时间允许,我将把这部分引申的更远。
本用例同时邪显示Jabber用户向服务器开启一个socket的连接,以及服务器的响应(如:<stream:stream>标签)。
1. Jabber用户通过开启一个从客户端到服务器端的XML流,来申请一个在服务器上的socket连接。
SEND: <stream:stream
to=’capulet.com’
xmlns=’jabber:client’
xmlns:stream=’http://etherx.jabber.org/streams’>
2. 服务器通过开启一个从服务器到客户端的XML流进行回复。
RECV: <stream:stream
from=’capulet.com’
id=’180763465’
xmlns=’jabber:client’
xmlns:stream=’http://etherx.jabber.org/streams’>
3. Jabber用户提供一个需要注册一个帐号(理论上,这需要一个不同的顺序:首先询问服务器需要什么信息,然后服务器器告知客户端需要什么样的信息;但在实际中,假定需要的信息是:用户名,资源,密码)的信息。
SEND: <iq id=’1’ type=’set’>
<query xmlns=’jabber:iq:register’>
<username>Juliet</username>
<resource>balcony</resource>
</query>
</iq>
4. 服务器响应一个空的类型为”result”的iq元素,表示注册已成功。
RECV: <iq id=’1’ type=’result’/>
1. Jabber用户询问服务器,登陆所需要提供的信息。
SEND: <iq id=’2’ type=’get’>
<query xmlns=’jabber:iq:auth’>
<username>Juliet</username>
</query>
</iq>
2. 服务器提示Jabber用户登陆所需要的信息。
RECV: <iq id=’2’ type=’result’>
<query xmlns=’jabber:iq:auth’>
<username>Juliet</username>
<password/>
<digest/>
<sequence>500<sequence/>
<token>3B905BFD</token>
<resource/>
</query>
</iq>
3. Jabber用户提供所需的信息——在本例中,是一个<hash/>元素,它是对信息进行一个零度知识认证的一个哈希。(详情请见http://docs.jabber.org/draft-proto/html/zerok.html)。
SEND: <iq id=’3’ type=’set’>
<query xmlns=’jabber:iq:auth’>
<username>Juliet</username>
<resource>balcony</resource>
<hash>77d7eacde5e56b9622d0a075cb88361b110f
b9d7</hash>
</query>
</iq>
4. 服务器响应一个空的类型为”result”的iq元素,表明登陆成功。
RECV: <iq id=’3’ type=’result’/>
5. Jabber用户发送当前状态给服务器,表明其在线。
SEND: <presence>
<status>Online</status>
</presence>
1. Jabber客户端在花名册上增加一个联系人(只是预备的操作)。
SEND: <iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item jid=’[email protected]’
Name=’remeo’/>
</query>
</iq>
2. Jabber用户发送一个对该联系人的订阅请求。
SEND: <presence to’[email protected]’ type=’subscribe’>
<status>Wherefore are thou?</status>
</presence>
3. 服务器发送一个花名单推送给用户一个新条目和一个类型为”none”的订阅(早已有了该订阅)。
RECV: <iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item jid=’[email protected]’
name=’romeo’
subscription=’none’/>
</query>
</iq>
4. 服务器发送一个类型为”result”的iq包,表示花名册推送成功(让人有点疑惑的是,这个包是从Jabber用户发送到Jabber用户的!)
RECV: <iq
from=’[email protected]/balcony’
to=’[email protected]/balcony’
type=’result’>
5. 服务器发送另一个花名单推送,这次是ask=’subscribe’属性,表示订阅的状态未定。
RECV: <iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item
ask=’subscribe’
jid=’[email protected]’
name=’romeo’
subscription=’none’/>
</query>
</iq>
6. Romeo对订阅请求的下一个响应会是什么呢?现在我们假定订阅以Romeo接受订阅请求为“结束”的。
RECV: <presence
from=’[email protected]’
to=’[email protected]’
type=’subscribed’/>
7. 服务器再次发送一个花名单推送给客户端,这次subscription=’to’,表示订阅请求被接受了(Juliet现在可以订阅到Romeo的当前状态了)。
RECV: <iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’[email protected]’
name=’romeo’
subscription=’to’/>
</query>
</iq>
SEND: <iq type=’get’>
<query xmlns=’jabber:iq:roster’/>
</iq>
RECV:<iq from=’[email protected]/balcony’ type=’result’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’[email protected]’
name=’romeo’
subscription=’both’/>
</query>
</iq>
SEND: <message to’[email protected]’>
<body>Wherefore are thou?</body>
</message>
注意:服务器会根据Jabber用户的会话信息加上一个源地址,这样接收者收到消息时,消息中已经包含了源地址。
SEND: <presence>
<status>stepped away…</status>
<show>away</show>
</presence>
登出时很容易的,只需要关闭<stream>……
SEND: </stream:stream>
RECV: </stream:stream>
本协议参考以下文献
l Jabber开发指南(http://docs.jabber.org/jpg/)
l Jabber协议――标准(http://docs.jabber.org/proto/)
l Jabber协议――草案(http://docs.jabber.org/draft-proto/)
l Romeo and Juliet
(http://tech-two.mit.edu/Shakespeare/Tragedy/romoandjuliet/full.html)
本文档提供了一个关于Jabber的XML协议的一个详细的怪数。如果你对本文档有任何问题,请通过email或Jabber的方式自由地与作者联系(Peter Saint-Andre),他的帐号时[email protected]。
This document is copyright 2001 by Peter Saint-Andre.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License (http://www.gnu.org/copyleft/fdl.html),
Version 1.1 or any later version published by the Free Software Foundation, with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. You may obtain a
copy of the GNU Free Documentation License from the Free Software Foundation by
visiting http://www.fsf.org/ or by writing to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307
USA
下面是Jabber中错误代码的一些简要描述。Jabber服务器在碰到不同的错误条件下生成这些错误代码。一般Jabber错误代码以HTTP规格的RFC 2616(http://www.ietf.org/rfc/rfc2616.txt)为基础。但Jabber没有使用所有的HTTP的错误代码,并且Jabber错误代码与HTTP错误代码相对应时,通常只有Jabber自己的含义。注意本附录只包含Jabber服务器生成的错误代码,而不包括服务器端组件如网关发到外部消息系统。
错误代码 |
描述 |
注意 |
302 |
重定向 |
尽管HTTP规定中包含八种不同代码来表示重定向,Jabber只用了其中一个(用来代替所有的重定向错误)。不过Jabber代码302是为以后的功能预留的,目前还没有用到 |
400 |
坏请求 |
Jabber代码400用来通知Jabber客户端,一个请求因为其糟糕的语法不能被识别。例如,当一个Jabber客户端发送一个的订阅请求给它自己活发送一条没有包含“to”属性的消息,Jabber代码400就会产生。 |
401 |
未授权的 |
Jabber代码401用来通知Jabber客户端它们提供的是错误的认证信息,如,在登陆一个Jabber服务器时使用一个错误的密码,或未知的用户名。 |
402 |
所需的费用 |
Jabber代码402为未来使用进行保留,目前还不用到。 |
403 |
禁止 |
Jabber代码403被Jabber服务器用来通知Jabber客户端该客户端的请求可以识别,但服务器拒绝执行。目前只用在注册过程中的密码存储失败。 |
404 |
没有找到 |
Jabber代码404用来表明Jabber服务器找不到任何与JabberID匹配的内容,该JabberID是一个Jabber客户端发送消息的目的地。如,一个用户打算向一个不存在的JabberID发送一条消息。如果接受者的Jabber服务器无法到达,将发送一个来自500级数的错误代码。 |
405 |
不允许的 |
Jabber代码405用在不允许操作被’from’地址标识的JabberID。例如,它可能产生在,一个非管理员用户试图在服务器上发送一条管理员级别的消息,或者一个用户试图发送一台Jabber服务器的时间或版本,或者发送一个不同的JabberID的vCard。 |
406 |
不被接受的 |
Jabber代码406用于服务器因为某些理由不接受一个包。例如,这个可能发生在,一个Jabber客户端试图使用jabber:iq:private在服务器上存储信息,但当前的用于存储的名字空间用”jabber:”开头(在Jabber里是一个被存的XML开头)。另一种可能产生406错误的情况是当一个Jabber客户端试图用一个空密码注册到一台Jabber服务器上。 |
407 |
必须注册 |
Jabber代码407当前不被使用 |
408 |
注册超时 |
当一个Jabber客户端不能在服务器准备好的时间内发起一个请求时,Jabber服务器生成Jabber代码408。这个代码当前只用于Jabber会话管理器使用的零度认证模式中。 |
409 |
冲突 |
略 |
500 |
服务器内部错误 |
当一台Jabber服务器遇到一种预期外的条件,该条件阻止服务器处理来自Jabber客户端的包,这是将用到Jabber代码500。现在,唯一会引发500错误代码的时间是当一个Jabber客户端试图通过服务器认证,而该认证因为某些原因没有被处理(如无法保存密码)。 |
501 |
不可执行 |
当服务器不支持Jabber客户端请求的功能,使用Jabber代码501。例如,该代码只当Jabber客户端发送一个认证请求,而该认证请求不包含服务器配置中定义的任何一种认证方式时,服务器发送Jabber代码501。这个代码还被用于,当一个Jabber客户端试图注册一个不允许注册的服务器。 |
502 |
远程服务器错误 |
当因为无法到达远程服务器导致转发一个包失败时,使用Jabber代码502。该代码发送的特殊例子包括一个远程服务器的连接的失败,无法获取远程服务器的主机名,以及远程服务器错误导致的外部时间过期。 |
503 |
服务无法获得 |
当一个Jabber客户端请求一个服务,而Jabber服务器通常由于一些临时原因无法提供该服务时,使用Jabber代码503。例如,一个Jabber客户端试图发送一条消息给另一个用户,该用户不在线,但它的服务器不提供离线存储服务,服务器将返回一个503错误代码给发送消息的JabberID。当为vcard-temp和jabber:iq:private名字空间设置信息时,出现通过xdb进行数据存储的写入错误,也使用该代码。 |
504 |
远程服务器超时 |
Jabber代码504用于下列情况:试图连接一台服务器发生超时,错误的服务器名。 |
510 |
连接失败 |
Jabber代码510目前还没有使用。 |