JabChapter 6

From WikiContent

Revision as of 14:23, 18 September 2009 by Uncopy (Talk | contribs)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search
Programming Jabber
Preface
1 - Getting started with Jabber
2 - Inside Jabber
3 - Installing the Jabber server
4 - Server Architecture and Configuration
5 - Jabber Technology Basics
6 - Jabber Namespaces
7 - User Registration and Authorization
8 - Using Messages and Presence
9 - Groupchat, : Components, and Event Models
10 - Pointers for Further Development
Appendix A
Appendix B
Colophon

Contents

Jabber Namespaces


While the building blocks of the Jabber protocol, described in Chapter 5, provide the groundwork for our solutions, for our chess rules, something is still missing.

A purity and elegance can be had with use of the three core elements, <message/>, <presence/>, and <iq/>, but a depth of meaning is missing. While the core elements define the moves we can make, it's the Jabber namespaces that provide us with the contextual set-moves that allow us to relate Jabber to the real world.

Namespaces provide a level of meaning, an environmental layer, above the basic "packet-shunting" world that would exist if our elements were to be passed back and forth bereft of context and application.

Basic activities such as user registration, authentication, roster management, and time-stamping are made possible by the application of standard Jabber namespaces to our elements. This chapter serves as a reference for all of Jabber's IQ and X namespaces. The IQ namespaces are used to qualify attachments to <iq/> elements, while the X namespaces are more ad hoc, and are used to add value, context, and information to any type of packet.


Namespace Usage


Chapter 5 frequently referred to namespaces. Jabber's namespaces are used within the message elements to qualify payloads (distinct content) within these elements. For example:


RECV: <iq id='roster_0' type='result' from='dj@yak/Work'> <query xmlns='jabber:iq:roster'> <item jid='sabine@yak' name='sabine' subscription='both'> <group>Family</group> </item> </query> </iq>


Here the jabber:iq:roster namespace is used to qualify a chunk of XML that contains roster information embedded in an <iq/> element. A payload exists as a subelement of the main element (that is, a child tag of the parent <message/>, <presence/>, or <iq/> tag) and, in XML terms, belongs to a different namespace than the main element.

The namespace of the main elements in the XML document that is streamed across the connection—<message/>, <presence/>, and <iq/> and indeed their "standard" subelements, such as <message/>'s <subject/> tag—is defined in the root tag of the XML document and in this case is jabber:client. Namespaces like jabber:client that are used to qualify such XML document body fragments are described in Section 5.3.2 in Chapter 5. While the main elements in our client connection are qualified by jabber:client, each distinct payload ("attachment" is also a good way to think of these additional chunks of XML) is qualified by one of the specific namespaces listed in this chapter.

Standard Jabber namespaces begin jabber:, with a few exceptions. It could be argued that the exceptions aren't really Jabber standard since these are the namespaces that describe things like vCards and XHTML payloads. There's nothing to stop you from defining your own namespaces to qualify any sort of XML you'd like to attach to a Jabber element. The only rule is that, if you do, it shouldn't begin with jabber:.

Further to the rule that Jabber standard namespaces begin with jabber:, the categorization can be seen as falling into two distinct spaces. The first, the iq space, contains namespaces that qualify content within <iq/>-based conversations. The second, the x space, contains namespaces that qualify extensions within all the elements (<message/>, <iq/>, and <presence/>).

</code>

The IQ Namespaces


The namespaces that qualify attachments to <iq/> elements are many and varied. After all, you could say that the raison d'etre of this request/response mechanism is to exchange structured information—and what better way to define that information than with namespaces?

This section looks briefly at each of the IQ namespaces in turn. Some of them will be covered in more detail in later chapters, as they will be used in examples that appear later in the book.


</code>

jabber:iq:agent

</code>The jabber:iq:agent namespace is used to request and return information on an agent. An agent is a service running on a Jabber server, and it has a JID. To find out what features the particular agent offers, an IQ-get can be made using this namespace:


SEND: <iq type='get' to='yak/groups'> <query xmlns='jabber:iq:agent'/> </iq>


Here, a request for features is being made of the agent with the JID yak/groups, which is the standard name for the Shared Groups service. The JID here is composed of a hostname (yak) and a resource (groups).

The response looks like this:


RECV: <iq type='result' to='dj@yak/Work' from='yak/groups'> <query xmlns='jabber:iq:agent'> <name>Jabber Server at yak</name> <url>http://yak</url> <service>jabber</service> <register/> </query> </iq>


In reality, although the agent or service itself is specified as the recipient of the query, it is often a centralized mechanism that responds on behalf of the agent if the agent itself doesn't or can't respond. (This is the mod_agents module within the JSM.) This means that the results of the query might not be as helpful as you might expect. The only detail in the response shown here that might be of some use is the <register/> tag, but that's actually misleading as it's picked up from the general registration capabilities configuration and not anything particular to what was queried.

The main reason for this is actually also the answer to a question you might have right now: "How do I know which agent JIDs I can query on a particular Jabber server?" Indeed. It's very hit and miss to pick agent JIDs at random. The jabber:iq:agents (plural) namespace defines a list of agents. Usually what happens is that a query is made using the jabber:iq:agents namespace, and then further detail is requested with the jabber:iq:agent for a particular agent. However:

  • The general information for both queries comes from the same place in

the Jabber server configuration.

  • That place is the <agents/> tag inside the JSM custom configuration, and is

deprecated in favor of the <browse/> tag. The jabber:iq:agent-based agent facility query is slowly but surely being replaced by the more generic but more powerful jabber:iq:browse mechanism (which is directly related to the <browse/> configuration area of the JSM). That said, it is still supported for compatibility reasons; many Jabber clients still use the jabber:iq:agent and jabber:iq:agents namespaces in calls to discover services on the server. See Section 6.2.5 for more details on the jabber:iq:browse mechanism.


jabber:iq:agents


Whereas the jabber:iq:agent namespace is used in a query of an individual Jabber agent, or service, the jabber:iq:agents namespace is used in a query to retrieve a list of these agents.

As mentioned in the description for the jabber:iq:agent namespace, the Jabber server configuration (in the JSM custom configuration section) in earlier releases contained an <agents/> tag, which was used to list the agents that were available on the Jabber server. The listing looked like this:


<agents> <!-- Note: this <agents/> listing is not used in 1.4.1 --> <agent jid='users.jabber.org'> <name>Jabber 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='...'> ... </agent> ... </agents>


The <agents/> listing has now been superseded by the <browse/> tag. In fact, when responding to jabber:iq:agentsandjabber:iq:browse queries, the Jabber server itself will refer to the same <browse/> listing in both cases. Here's an example of a response to a jabber:iq:agents query:


RECV: <iq type='result' to='dj@yak/laptop' from='yak' id='agents'> <query xmlns='jabber:iq:agents'> <agent jid='users.jabber.org'> <name>Jabber User Directory</name> <service>jud</service> <register/> <search/> </agent> </query> </iq>


We can see that this response pretty much reflects the information in the <agents/> configuration.

For more details on how this differs in response to a jabber:iq:browse query, see Section 6.2.5.

Further examples of jabber:iq:agents usage can be found in Section 9.3 in Chapter 9.


jabber:iq:auth


The jabber:iq:auth namespace is used to qualify a structured authentication procedure between client and server.

Details of authentication are covered in Chapter 7; however, here we will look at the simplest authentication conversation between client and server. In this example, the client sends a username and password, and the server responds by sending a "successful" response, acknowledging the user's credentials, thus creating a session for that user:


SEND: <iq type='set' id='auth0'> <query xmlns='jabber:iq:auth'> <username>sabine</username> <password>geheimnis</password> <resource>WinJab</resource> </query> </iq>

RECV: <iq type='result' id='auth0'/>



jabber:iq:autoupdate


The Update Info Request configuration description in Section 4.4.3.6 in Chapter 4 describes a mechanism for Jabber servers to query a software version information repository to find out about new versions of the server.[1] This version information repository that responds to queries is also known as the Auto-Update service.

Not only can servers request software update information, clients can too. The procedure is the same in both cases and involves the jabber:iq:autoupdate and jabber:x:autoupdate namespaces. If clients support this software update information request, it will usually be in the form of a "silent" request that it sends out at startup. The sending out of this request can often be switched on and off in the client's configuration.

The conversation starts with the requester sending a special availability packet to the information repository. Currently, there are two such public repositories: one running at jabber.org covering a wide range of Jabber software and the other running at jabber.com covering certain clients including JabberIM. This special availability packet looks like this:


SEND: <presence to='959967024@update.jabber.org/1.6.0.3'/>


This is a directed<presence/> packet because it has a to attribute. What's even more interesting is that if we break down the JID, we're left with 959967024 as the username, update.jabber.org as the hostname, and 1.6.0.3 as the resource. This doesn't mean that the availability is destined for a user called 959967024 registered on the update.jabber.org Jabber server. While most presence packets are destined for users (within the presence subscription model), this one is destined for a service.

The service is running with the identification update.jabber.org—a component connected to the jabberd server backbone running at jabber.org. Therefore, the <presence/> packet will be routed to that service. Unlike the JSM, the update.jabber.org service has no concept of users or sessions. Instead, it receives the complete <presence/> packet, disassembles the JID in the destination address, and interprets component parts as it sees fit.

The service uses the username portion of the JID to identify the piece of software for which new version information is being requested. In our example, this is 959967024. This value actually represents the JIM client and is the key to the client database kept on http://www.jabbercentral.org. Using a unique client database key to represent the piece of software allows the client's name to be changed without causing problems in the retrieval of version information by the Auto Update service.

The version information stored in the repository is compared to the current version of the requesting piece of software; in this case, our JIM Version 1.6.0.3. If a new version isn't available, nothing will happen. Because the initial part of the request was a <presence/> packet, no official response is expected (unlike a situation in which the initial part of the request was an IQ-get).

If there is, however, information stored in the repository about newer versions of the software, the query is replied to using a <message/> element, with a jabber:x:autoupdate attachment.


RECV: <message to='qmacro@jabber.org/Work' from='959967024@update.jabber.org'> <subject>Upgrade available for Jabber Instant Messenger</subject> <body> There is an update available for Jabber Instant Messenger. If your client supports the iq:autoupdate namespace, then you should see something in the client that will list the available files. If not, then go to http://www.jabbercentral.com and grab the new version. </body> <x xmlns='jabber:x:autoupdate'>959967024@update.jabber.org</x> </message>


The reply contains some text (in the <subject/> and <body/> tags) that could be displayed to the user.

Furthermore, the autoupdate attachment—an <x/> subelement qualified by the jabber:x:autoupdate namespace—contains information on where further information can be obtained in a programmatic way.[2]

This "programmatic way" involves sending an empty IQ-get, with the query part qualified by the jabber:iq:autoupdate namespace, to the address given in the jabber:x:autoupdate<message/> attachment:


SEND: <iq type='get' id='id_3' to='959967024@update.jabber.org'> <query xmlns='jabber:iq:autoupdate'/> </iq>


We're back on familiar ground; the Auto Update service responds to the request by sending version information for that piece of software:


RECV: <iq type='result' to='qmacro@jabber.org/Work' from='959967024@update.jabber.org' id='id_3'> <query xmlns='jabber:iq:autoupdate'> <release priority='optional'> <url>http://www.jabber.com/download/jabbersetup.exe</url> <version>1.7.0.14</version> <desc/> </release> </query> </iq>


The response contains information about the latest software release that prompted the version request. The release is either required or optional (as in this example). The tags within the jabber:iq:autoupdate-qualified query are fairly self-explanatory; note that the version description is empty in this example.


jabber:iq:browse


The jabber:iq:browse namespace is relatively new and could almost be seen as a departure from the traditional namespaces found elsewhere in Jabber. While namespaces such as jabber:iq:agents and jabber:iq:register define very strict content using specific tag names, jabber:iq:browse allows a more free-form containment of information. Both forms of tight and loose namespaces have a place in Jabber.

The real world contains countless types and classifications of information far more than you could ever reasonably cover with a finite collection of namespaces. And even if you did, that coverage would be out of date as soon as it was completed. The Jabber concept of browsing, introduced in Chapter 2, is an approach to being able to classify and exchange information of all kinds without the definitions being previously cast in stone.

More or less any hierarchical information can be represented in the jabber:iq:browse namespace. It can be seen as an open-ended way of describing structures in an almost ad hoc way. That said, the namespace comes with some general rules and some predefined classifications.

Information represented and described in a jabber:iq:browse extension is subject to classification. This classification is in two levels: categories and subtypes. The category is used to define the general area or type of information being represented. The subtype gives a more specific definition of that category. Table 6-1 shows a list of initial categories.


jabber:iq:browse categories -
Category Description
application Applications addressable via a JID can be described in this category. Initial suggestions for such application subtypes include calendar (calendar/schedule services), whiteboard (collaborative whiteboard tools), and game (multiplayer games).
conference Used to describe elements in the conferencing (talk between three or more entities) world, such as private and public rooms. Subtypes of this category include private (private chat rooms), irc (IRC rooms), and url (for web-based conferences).
headline Stock-ticker-style notification systems can be described using this category. Subtypes already defined include rss, logger, and notice.
item A category placeholder, to effect hierarchies and lists in a jabber:iq:browse structure. You can fall back to this category for representation of pretty much any type of information in a navigable drill-down fashion.
keyword IRC-style utilities that are invoked from a chat-input command line; so-called keyword services such as dictionary lookups (subtype dictionary), DNS resolution (subtype dns), and FAQ answers (subtype faq) have their category in the jabber:iq:browse world.
render Translation services such as English to French (subtype en2fr) or spelling tools (subtype spell) are defined in this category.
service Maps to traditional Jabber services, such as IM transports and gateways to other systems, user directories, and so on. Typical subtypes within this category are irc (IRC gateway), aim (AIM transport), and jud (Jabber User Directory).
user Various addressable elements of users, such as their clients (subtype client), inbox mechanisms (subtype inbox), and so on, find themselves in this category.

The categories listed in Table 6-1 are not exhaustive; the jabber:iq:browse namespace and the browsing idea were introduced with Version 1.4 of the Jabber server and are still evolving. The same goes for the category subtypes.

Any particular browsable entity can be described using the combination of the category and subtype, for example, user/client, in much the same way that Multipurpose Internet Mail Extensions (MIME) types are, for example, image/png. The category describes generally what the entity is, and the subtype further classifies the description. Following the MIME system further, we can define our own subtypes on the fly and specify them with an x- prefix, such as user/x-schedule.

Indeed, the browsing description model of category/subtype follows the MIME model; in places the category is often referred to in Jabber documentation as the JID-type. The JID is critical to browsing; it is a required attribute of all entities described in a jabber:iq:browse-based hierarchy. The JID is the key to navigating the hierarchy structure.

Earlier in this section we saw the results of making a query in the jabber:iq:agents namespace to retrieve information on the services available on a Jabber server. Now let's have a look at a similar query using the jabber:iq:browse namespace:


SEND: <iq type='get' to='yak'> <query xmlns='jabber:iq:browse'/> </iq>

RECV: <iq type='result' to='dj@yak/home' from='yak'> <service name='Jabber Server' type='jabber' xmlns='jabber:iq:browse' jid='yak'> <conference name='yak Conferencing' type='public' jid='conference.yak'/> <service name='yak User Directory' type='jud' jid='jud.yak'> <ns>jabber:iq:search</ns> <ns>jabber:iq:register</ns> </service> <service name='User Directory (Browsable)' type='jud' jid='jud.merlix/users'/> </service> </iq>


Notice how the information returned forms a hierarchy. The outermost item in the browse results represents the Jabber server as a whole (with the JID yak) and contains subitems that are services of that Jabber server (the yak Conferencing service, and the two forms of the JUD). Notice also the JID-types. Looking at the tag names and the type attributes, we see that the result represents a service/jabber entity, which itself contains a conference/public and two service/jud entities.

How many levels of hierarchy can we expect to receive (as a browsing information consumer) or provide (as a browsing information provider) in any given situation? It really depends on the application situation and the balance you want to achieve between shallow hierarchy responses and many IQ calls for navigational descent (light extensions but more traffic) and deeper hierarchy responses and few IQ calls for navigational descent (heavier extensions but less traffic).


Descending the browse hierarchy from an LDAP reflector


As an example, let's look at how we might perform a hierarchy descent in the navigation of Lightweight Directory Access Protocol (LDAP) information provided by a custom LDAP reflector in a jabber:iq:browse context.[3] Each time, the link to the next level is via the item's JID, which is the target of the browse query.

First, we send an initial query:


SEND: <iq type="get" id="browser_JCOM_15" to="ldap.yak"> <query xmlns="jabber:iq:browse"></query> </iq>


In answer to the initial query to what is effectively the LDAP root represented by the JID of the LDAP component itself (ldap.yak, no username prefix), the initial hierarchy level containing People and Groups is returned, wrapped in a pseudoroot:


RECV: <iq type='result' to='dj@yak/winjab' from='ldap.yak' id='browser_JCOM_15'> <query xmlns='jabber:iq:browse'> <item name='root entry' xmlns='jabber:iq:browse' jid='ldap.yak'> <item name='ou=People' jid='ou=People@ldap.yak'/> <item name='ou=Groups' jid='ou=Groups@ldap.yak'/> </item> </query> </iq>


We see the items presented to us and choose to descend the path marked Groups; our second browse request is made to the JID that represents that item, ou=Groups@ldap.yak:


SEND: <iq type="get" id="browser_JCOM_17" to="ou=People@ldap.yak"> <query xmlns="jabber:iq:browse"></query> </iq>


The LDAP reflector component receives the IQ packet addressed to the JID ou=People@ldap.yak and interprets the username part of the JID (ou=People) as an LDAP RDN (relative distinguished name, a form of key within an LDAP structure that's further qualified by a common suffix), which returns the appropriate information from the next level in the LDAP hierarchy, the countries:


RECV: <iq type='result' to='dj@yak/winjab' from='ou=People@ldap.yak' id='browser_JCOM_17'> <item name='ou=People' xmlns='jabber:iq:browse' jid='ou=People@ldap.yak'> <item name='ou=UK' jid='ou=UK,ou=People@ldap.yak'/> <item name='ou=France' jid='ou=France,ou=People@ldap.yak'/> <item name='ou=Germany' jid='ou=Germany,ou=People@ldap.yak'/> </item> </iq>


The descent continues, via the JID ou=UK,ou=People@ldap.yak, which was specified as the unique identifier for that item (the country UK):


SEND: <iq type="get" id="browser_JCOM_18" to="ou=UK,ou=People@ldap.yak"> <query xmlns="jabber:iq:browse"></query> </iq>


which continues:


RECV: <iq type='result' to='dj@yak/winjab' from='ou=UK,ou=People@ldap.yak' id='browser_JCOM_18'> <item name='ou=UK,ou=People' xmlns='jabber:iq:browse' jid='ou=UK,ou=People@ldap.yak'> <user name='cn=JanetAbrams' jid='JanetAbrams@yak'/> <user name='cn=PaulAnthill' jid='PaulAnthill@yak'/> ... </item> </iq>


The section of the actual LDAP hierarchy browsed is shown in Figure 6-1.


The example in the LDAP hierarchy browsed


-</code> Browse data isn't just something that can be retrieved; like presence, it can be pushed to an entity when required. In the same way that an alert in the form of a <message/> element might arrive at a client unannounced, so might browse information also appear. This is referred to as live browsing, as the information that is pushed is effectively live.

The Conferencing service uses this mechanism to push information on room participants to a new joiner. As the browse information is enveloped in an IQ element, it makes the most sense to use a type='set' (it might help to consider the parallel with the Hypertext Transfer Protocol (HTTP) verb POST as introduced in Chapter 2) to push this information. And this is what happens, as seen in this excerpt from information sent to a client as a conference room is joined:[4]


RECV: <iq type='set' to='qmacro@jabber.org/winjab' from='jdev@conference.jabber.org'> <conference xmlns='jabber:iq:browse' name='Development Room' type='public'> <user name='piers' jid='jdev@conference.jabber.org/445d4b864bd6...'/> <user name='pgmillard' jid='jdev@conference.jabber.org/1cffcbf43c75...'/> <user name='reatmon' jid='jdev@conference.jabber.org/b3f3c19859de...'/> ... </conference> </iq>


As well as the LDAP browser recipe in Section 10.3 in Chapter 10, an example of a simple jabber:iq:browse implementation can be found in Section 9.3 in Chapter 9.


jabber:iq:conference


The Conferencing service provides facilities for entities to join rooms and chat with each other. The entry negotiations that take place between a room (via the service) and a potential participant are made using the jabber:iq:conference namespace. With this namespace, information on rooms can be requested, and attempts to enter rooms can be made.


{{Warning|The jabber:iq:conference namespace is currently in a state of flux, as more conferencing features (such as being able to eject users from rooms) are requested and added into the definition. Because of this, the examples that follow are deliberately innocuous. The keyassist recipe in Section 9.1 in Chapter 9 describes and uses the older, but stable, conferencing protocol called "Groupchat."

</code>


The jabber:iq:conference namespace at work


Here we see a typical sequence of IQ elements that ensue in the entry negotiations for the jdev room hosted by the Conferencing service on jabber.org's Jabber server. Information on the jdev room is requested:


SEND: <iq type="get" id="c2" to="jdev@conference.jabber.org"> <query xmlns="jabber:iq:conference"/> </iq>


<note>The JID to which the IQ-get was sent—jdev@conference.jabber.org—works in a similar way to the LDAP reflector earlier in Section 6.2.5.1. There's no real distinction between conferencing service usernames in the same way that there's a distinction in the JSM service, but that part of the JID is used to identify each room hosted by that service. In other words, jdev isn't a "real" user in the JSM sense.

</code> The conferencing service replies with the relevant information:


RECV: <iq type='result' id='c2' to='qmacro@jabber.org/hailsham' from='jdev@conference.jabber.org'> <query xmlns='jabber:iq:conference'> <name>Development Room</name> <nick/> </query> </iq>


We see that the "friendly" name of the jdev room is "Development Room" and that we need to specify a nickname in order to gain entry. There are no other requirements (such as a secret password) that would have been identified inside an extra <secret/> tag in the results.

We choose a nickname, and send this back in an IQ-set. However, before doing this, we must send our presence to the room to invoke the Availability Tracker, which is described in Section 5.4.2.4 in Chapter 5.


SEND: <presence to="jdev@conference.jabber.org"/>

SEND: <iq to="jdev@conference.jabber.org" type="set" id="c3"> <query xmlns="jabber:iq:conference"> <nick>qmacro</nick> </query> </iq>


The Conferencing service acknowledges our entry to the room with our chosen nickname, having assigned us an anonymous handle in the <id/> tag:


RECV: <iq to='qmacro@jabber.org/winjab' type='result' id='c3' from='jdev@conference.jabber.org'> <query xmlns='jabber:iq:conference'> <nick>qmacro</nick> <name>Development Room</name> <id>jdev@conference.jabber.org/650e81de0fcc...</id> </query> </iq>


Closely linked with the jabber:iq:conference namespace is the jabber:iq:browse namespace, which is also used as a conduit for room-specific information and activity; see Section 6.2.5.

More information on joining and interacting with conference rooms can be found in Section 9.1 in Chapter 9.


jabber:iq:gateway


The jabber:iq:gateway namespace is used to envelope a utility mechanism for converting external system identifiers (usernames and so on) to JID equivalents. The requirement for this grew out of the transport services to other IM systems (AIM, Yahoo!, and so on), which have their own formats for user identification.

First, we know whether a service offers this utility from the namespace list that is returned if we browse that service. The next section shows how this might be done with the AIM Transport service.


Discovering and using the AIM Transport's jabber:iq:gateway utility

By browsing a service, we can tell whether it supports the jabber:iq:gateway utility:


SEND: <iq type="get" id="aim1" to='aim.jabber.org'> <query xmlns="jabber:iq:browse"/> </iq>

RECV: <iq type='result' id='aim1' to='qmacro@jabber.org/winjab' from='aim.jabber.org'> <service xmlns='jabber:iq:browse' type='jabber' jid='aim.jabber.org' name='AIM Transport'> <ns>jabber:iq:register</ns> <ns>jabber:iq:gateway</ns> </service> </iq>


We can now avail ourselves of this utility, to convert an AIM screen name test ScreenName to the equivalent JID to be used (in relation to the AIM Transport service) in a Jabber context:


SEND: <iq type='get' to='aim.jabber.org' id='conv5'> <query xmlns='jabber:iq:gateway'/> </iq>

RECV: <iq type='result' to='qmacro@jabber.org/hailsham' id='conv5' from='aim.jabber.org'> <query xmlns='jabber:iq:gateway'> <desc>Enter the user's screen name</desc> <prompt/> </query> </iq>


We can reply, with an IQ-set, with our screen name:


SEND: <iq type='set' to='aim.jabber.org' id='conf6'> <query xmlns='jabber:iq:gateway'> <prompt>test ScreenName</prompt> </query> </iq>


and receive the result of the transport-specific JID conversion:


RECV: <iq type='result' to='qmacro@jabber.org/Work' id='conf6' from='aim.jabber.org'> <query xmlns='jabber:iq:gateway'> <prompt>testScreenName@aim.jabber.org</prompt> </query> </iq>



jabber:iq:last


Like jabber:iq:time and jabber:iq:version, the jabber:iq:last namespace allows a simple query on uptime, idletime, or last disconnect information to be made on clients and servers.

Elapsed time information, in seconds, is returned in response to queries in the jabber:iq:last namespace. If the query is made of a server element (the Jabber server itself or a component connected to that server), then the information returned represents the time since that element started, that is, the uptime:


SEND: <iq type='get' to='yak'> <query xmlns='jabber:iq:last'></query> </iq>

RECV: <iq type='result' to='dj@yak/Work' from='yak'> <query xmlns='jabber:iq:last' seconds='2339811'/> </iq>


Not all components support the jabber:iq:last namespace; then again, in many cases, the components—certainly those that are connected with the library load mechanism (see Chapter 4)—will have the same uptime as the Jabber server they're connected to. In other cases, for TCP sockets connected components that can be attached while the Jabber server is running, the uptime may be less.[5]

When a client disconnects, the last (un)availability information in the closing <presence/> element is stored for that user, along with the current time:


SEND: <presence type='unavailable'> <status>Gone home for the evening!</status> </presence>


Making a jabber:iq:last-based query on a user's JID will return the information that was stored from the <status/> tag as well as the number of seconds representing the elapsed time since that disconnection (as a difference between the time the query was made and the time stored for that user):



SEND: <iq type='get' to='dj@yak' id='lastq'> <query xmlns='jabber:iq:last'/> </iq>

RECV: <iq type='result' to='sabine@yak/Work' id='lastq' from='dj@yak'> <query xmlns='jabber:iq:last' seconds='4521'> Gone home for the evening! </query> </iq>


Notice that the JID of the user being queried is dj@yak and not dj@yak/Work. This, of course, is because the user was still disconnected. The query was addressed to the user with no resource specified and was answered on behalf of the user by the server (by the mod_last module—the same module that looks after storing this information). In a disconnected context, a resource is not appropriate for a user's JID (in the JSM); it is found only in a connected context.

The jabber:iq:last is also designed to support a similar client-targeted query (to be responded to by a client), this time requesting information on how long it has been since the user of that client was active (sent a message, changed her presence, and so on). In contrast to the previous jabber:iq:last query type, this query is designed to be made to a connected user:


SEND: <iq type="get" to="dj@yak/Work"> <query xmlns='jabber:iq:last'/> </iq>

RECV: <iq type='result' from='dj@yak/Work'> <query xmlns='jabber:iq:last' seconds="19'/> </iq>


Here we see that the user is using a client that supports this type of jabber:iq:last query and was last active 19 seconds ago.


jabber:iq:oob


We've already seen a form of the oob—"Out-Of-Band"—namespace in action, in the imaginary conversation in Chapter 1, where jabber:x:oob was used to pass information about a third-party file location, in the form of a Uniform Resource Locator (URL). The word "band" here refers to the bandwidth, or connection, between the client and the server. The point of an out-of-band connection is that it's independent of that client-to-server connection (it typically is a connection from one client directly to another), and so doesn't impact the traffic or bandwidth on that connection. This makes sense when you consider that out-of-band connections are typically used for exchanging large volumes of data, such as binary files.

The jabber:iq:oob namespace is used for pretty much the same thing, except that its usage describes a very simple handshake between two Jabber clients to exchange a file between themselves. (Yes, real peer-to-peer for the purists.) The exchange is made using HTTP. Typically, the client sending the file will start listening for HTTP requests only at the beginning of the transfer process and stop listening at the end of the transfer process. The handshake is used to coordinate the process.


<note>It's worth pointing out here that HTTP-based peer-to-peer transfers are at the mercy of firewalls, Network Address Translation (NAT) mechanisms, and so on. There is some work underway to build a proxy mechanism—the Proxy Accept Socket Service (PASS). Details can be found at http://foundation.jabber.org/jeps/jep-0003.html.

</code> The sender initiates the process by making the file available via HTTP on a specific (nonstandard) port and notifying the recipient of the URL:


SEND: <iq type='set' to='sabine@yak/winjab' id='file_2'> <query xmlns='jabber:iq:oob'> <url>http://192.168.0.7:5600/meetingnotes.txt</url> <desc>Meeting Notes</desc> </query> </iq>


The recipient retrieves the file and notifies the sender when the transfer is complete:


RECV: <iq type='result' to='dj@yak/Work' id='file_2' from='sabine@yak/winjab'/>



jabber:iq:private


The jabber:iq:private namespace is traditionally a way of storing user-defined data that should be kept private. Persistency across sessions is achieved by storing the data in the user's records on the server. The data is, of course, formatted in XML.


{{Warning|Private data stored by a user is accessible only to that user. Remember, however, that the private data is stored on the server. Unencrypted. If you're paranoid, encrypt it before storing it.

</code> A typical use of the jabber:iq:private namespace is shown in Example 6-1. The JIM client stores countless user preferences on a per-user basis using this namespace. Once a user has connected and authenticated with a Jabber server, those user preferences are retrieved and used by the client to customize the settings.


JIM retrieves user preferences stored in a jabber:iq:private namespace

SEND: <iq id="jabberim:prefs3860" type="get"> <query xmlns="jabber:iq:private"> <jabberIM xmlns="jabberim:prefs"/> </query> </iq>

RECV: <iq id='jabberim:prefs3860' type='result' from='dj@yak/Work'> <query xmlns='jabber:iq:private'> <jabberim xmlns='jabberim:prefs' UseAutoAway='true' AwayTime='5' XATime='30' AwayStatus='Away (auto)' XAStatus='Ext. Away (auto)' WizardShown='false' ... > </jabberim> </query> </iq>


In this example, you can see that a private namespace is used to qualify the particular chunk of stored data, jabberim:prefs. Also of interest is the difference between the tags—<jabberIM/> in the retrieval request and <jabberim/> in the response. Again we see evidence of an XML usage convention previously seen (for example, in the Jabber server component configuration stanzas; see Chapter 4 for more details). The namespace itself, not the enclosing tag name, is critical. If the preferences were originally stored using a tag name of <jabberim/>, then that's how they will be stored and returned.

To add (or change) private data, use the namespace in an IQ-set context:


SEND: <iq id="private-s3" type="set"> <query xmlns="jabber:iq:private"> <reminders xmlns="cal:events"> <event date='20010617'>Father's Day</event> </reminders> </query> </iq>


Due to the way the jabber:iq:private storage mechanism is currently implemented, you can interact with only one private namespace-qualified chunk. In other words, a private store request like this:


SEND: <iq id="private-s4" type="set"> <query xmlns="jabber:iq:private"> <reminders xmlns="cal:events"> <event date='20010617'>Father's Day</event> </reminders> <favorites xmlns='url:favorites'> <fav url='http://dev.jabber.org'>Jabber DevZone</fav> <fav url='http://www.scripting.com'>Scripting News</fav> </favorites> </query> </iq>


would result in the storage of only the cal:events chunk. The url:favorites chunk would be ignored.



Storing public data


In the 1.4.1 release of the Jabber server, the JSM module mod_xml that services the jabber:iq:private namespace has been extended to allow this server-side storage to encompass nonprivate (i.e., publicly accessible) user data. The namespace in this case is, fittingly, notjabber:iq:private. It can be anything you wish, provided that it doesn't encroach on the standard Jabber namespace names—jabber:* and vcard-temp are not allowed. However, anything else goes. The reason for the vcard-temp namespace name is that there is an emerging but nevertheless not-yet-established standard for vCard data. Until that standard is established, the Jabber server developers have decided to handle this format in a temporary way.

The idea of publicly accessible data is just that; you can make information available to your fellow Jabber users (share URLs, contact lists, and so on). Of course, this sharing is only one way; you write and others can only read. But how do they find out what you've made available for them to read? The namespaces of any data stored publicly (i.e., any namespace except for jabber:iq:private) are returned by the Jabber server acting on behalf of the user in response to a jabber:iq:browse request to that user's JID. That is, the JID without a specified resource; otherwise, it would be passed on by the server to be handled by the client connection with that resource.

Let's have a look at this in action. We'll also have a peek at how the storage of the public and private information is structured in the user's spool file on the server to understand how this works. The location of the spool files is defined in the xdb component instances configuration—see Section 4.5 in Chapter 4. In addition to the Father's Day event that was stored privately in the previous example, we can also set some favorite URLs in a publicly accessible namespace and receive an acknowledgment of successful storage from the server:


SEND: <iq type='set' id='setfavs'> <query xmlns='dj:public:favorites'> <item url='http://dev.jabber.org'>Jabber DevZone</item> <item url='http://www.scripting.com'>Scripting News</item> </query> </iq>

RECV: <iq type='result' from='dj@yak/Work' to='a1@yak/Work' id='setfavs'/>


Now, the relevant section of dj@yak's spool file on the server looks something like that shown in Example 6-2.


Section of user's spool storage showing public and private data

...

<foo xmlns='jabber:xdb:nslist' xdbns='jabber:xdb:nslist'> <ns type='private'>cal:events</ns> <ns>dj:public:favorites</ns> </foo>

<reminders xmlns='cal:events' j_private_flag='1' xdbns='cal:events'> <event date='20010617'>Father's Day</event> </reminders>

<query xmlns='dj:public:favorites' xdbns='dj:public:favorites'> <item url='http://dev.jabber.org'>Jabber DevZone</item> <item url='http://www.scripting.com'>Scripting News</item> </query>

...


There are a few things to note in this example:

  • The jabber:xdb:nslist namespace maintains a list of

namespaces containing information stored for private and public reference.

  • The private namespaces are marked in this list

with a type='private' attribute.

  • There is an additional flag

(j_private_flag="1') that is held as an attribute of each of the privately stored fragments.

  • Otherwise the information is stored

exactly as it was set (additional xdbns attributes related to the xdb storage mechanisms notwithstanding). The namespaces (<ns/> tags) in the jabber:xdb:nslist-qualified list are returned in any browse request to that user:


SEND: <iq type='get' to='dj@yak'> <query xmlns='jabber:iq:browse'/> </iq>

RECV: <iq type='result' to='sabine@yak/Work' from='dj@yak'> <user name='DJ Adams' xmlns='jabber:iq:browse' jid='dj@yak'> <ns>dj:public:favorites</ns> </user> </iq>


and can be subsequently retrieved by anyone:


SEND: <iq type='get' to='dj@yak'> <query xmlns='dj:public:favorites'/> </iq>

RECV: <iq type='result' to='sabine@yak/Work' from='dj@yak'> <query xmlns='dj:public:favorites'> <item url='http://dev.jabber.org'>Jabber DevZone</item> <item url='http://www.scripting.com'>Scripting News</item> </query> </iq>


Publicly stored data can contain multiple fragments qualified by different namespaces, such as:


SEND: <iq type='set'> <query xmlns='my:resume'> <education xmlns='resume:education'> <degree type='BA'>Classics</degree> </education> <employment xmlns='work:clients'> <client from='2001'>Author, O'Reilly & Associates, Inc.</client> <client from='1999'>Deluxe Video Services</client> <client from='1996'>Andersen Consulting</client> ... </employment> </query> </iq>


However, the retrieval resolution is still limited to all of the fragments defined by the top-level namespace (my:resume in this case).


jabber:iq:register


As the name suggests, the jabber:iq:register namespace is used to conduct registration exchanges between the client and server. The most obvious example of this is to create (register) a new user on the Jabber server. We cover user registration, including changes to user details such as passwords, in Chapter 7, so here we'll look at how to use the namespace to add or change an entry in the JUD.

First we request the fields for registration with an IQ-get:


SEND: <iq type='get' to='jud.yak' id='jud-2'> <query xmlns='jabber:iq:register'/> </iq>

RECV: <iq type='result' to='dj@yak/Work' from='jud.yak' id='jud-2'> <query xmlns='jabber:iq:register'> <instructions> Complete the form to submit your searchable attributes in the Jabber User Directory </instructions> <name/> <first/> <last/> <nick/> <email/> </query> </iq>


and then send an IQ-set to set our information:


SEND: <iq type='set' to='jud.yak' id='jud-3'> <query xmlns='jabber:iq:register'> <name>DJ Adams</name> <first>DJ</first> <last>Adams</last> <nick>qmacro</nick> <email>dj.adams@pobox.com</email> </query> </iq>

RECV: <iq type='result' to='dj@yak/Work' from='jud.yak'/>


<note>This idiom—making a request to a service to return the fields appropriate for completion—is common in Jabber and is worth bearing in mind if you're intending to build a Jabber client. The nature of the form field requests means that the client application has to be flexible and accommodating, to bend itself around the dynamic server.

The recipe in Section 10.1 in Chapter 10 is an example of creating forms dynamically.

</code> Services offering a registration mechanism are identifiable in the list returned from a jabber:iq:agents or a jabber:iq:browse query, as shown in Example 6-3.


An agents or browse query reveals registration mechanisms

RECV: <iq to='dj@yak/Work' type='result' from='yak'> <query xmlns='jabber:iq:agents'> <agent jid='jud.yak'> <name>yak JUD (0.4)</name> <service>jud</service> <search/> <register/> </agent> ... </query> </iq>

     ...

RECV: <iq type='result' to='dj@yak/Work' from='yak'> <service xmlns='jabber:iq:browse' type='jabber' jid='yak' name='Jabber Server'> <service type='jud' jid='jud.yak' name='yak JUD (0.4)'> <ns>jabber:iq:search</ns> <ns>jabber:iq:register</ns> </service> ... </service> </iq>


There are a couple of extra elements that are fairly common across different implementations of the jabber:iq:register namespace:


<remove/>
When sent with an IQ-set request, the <remove/> tag
requests that the registration be canceled, revoked, or reversed.
<registered/>
When received in an IQ-result, the <registered/> tag
signifies that registration has already been made with the service,
and any further registration IQ-sets will serve to modify the current
registration details. The jabber:iq:register namespace also
defines a special <key/> tag. This is a simple
antispoofing mechanism that a piece of software responding to an IQ in
this namespace can use to verify the sender of that IQ. This
<key/> tag can also be used in the
jabber:iq:search namespace. See the following section for
details on how this mechanism is used.


The <key/> tag


The <key/> tag is used in registration and search sequences to add a simple form of security between the service and the entity requesting the service. It enables the service, the responder, to verify that the requester from whom it has just received an IQ-set is the same requester that had sent an IQ-get earlier.

This security mechanism predates the server-to-server dialback mechanism, described in Chapter 4. Since the advent of dialback, the relevance of the <key/> tag usage has been reduced.

If a component wants to determine who ought to be allowed to partake of its registration or search services, it would make sense to make the determination when responding to an initial IQ-get, the "can I do this, and what do I have to do?" request. If the request is to be denied, the component can send back an IQ-error, say, with an error 405 "Not Allowed" (see Table 5-3).

If, however, the component determines that the requester should be allowed to use the service (with an IQ-set), it can send back an IQ-result containing a <key/> tag along with the rest of the instructions and fields. The <key/> tag contains a random string, such as a message digest of the requester's JID combined with a secret phrase. When the requester is ready to make the IQ-set, the "OK, I'd like to use this service, and here's the data" request, the <key/> tag must be included, with the contents intact. On receipt of the IQ-set, the component doesn't have to determine whether the requester is allowed to use the service, it just has to regenerate the string using the same algorithm as before and compare it with what the requester sent.

Example 6-4 shows the <key/> tag in action, based upon the same registration sequence shown earlier in this section.


The <key/> tag in action

SEND: <iq type='get' to='jud.yak' id='jud-2'> <query xmlns='jabber:iq:register'/> </iq>

RECV: <iq type='result' to='dj@yak/Work' from='jud.yak' id='jud-2'> <query xmlns='jabber:iq:register'> <instructions> Complete the form to submit your searchable attributes in the Jabber User Directory </instructions> <key>cff28e89afa94e734aabfb11ec1099780450d80e</key> <name/> <first/> <last/> <nick/> <email/> </query> </iq>

SEND: <iq type='set' to='jud.yak' id='jud-3'> <query xmlns='jabber:iq:register'> <key>cff28e89afa94e734aabfb11ec1099780450d80e</key> <name>DJ Adams</name> <first>DJ</first> <last>Adams</last> <nick>qmacro</nick> <email>dj.adams@pobox.com</email> </query> </iq>

RECV: <iq type='result' to='dj@yak/Work' from='jud.yak'/>


Another example of registration using the jabber:iq:register namespace is shown in Section 9.3 in Chapter 9.


jabber:iq:roster


In Section 5.4.2.3 in Chapter 5, we looked at the presence subscription mechanism used to coordinate and record information about the relationships between users and how they exchange availability information. This mechanism revolves around certain types of <presence/> elements and storage of information in the users' rosters.

The roster structure is managed within the jabber:iq:roster namespace. Clients make roster requests when they connect to the Jabber server, to pull down the roster that is stored server-side. They also update the roster to add, change, or remove entries. However, roster updates aren't limited to just the client; there are certain attributes within each roster item that are maintained by the server, in response to presence subscription activity.

The roster in Example 6-5 contains five items. Three are friends, grouped together using <group>Friends</group>, which is used by clients to build the roster item display in a structured (hierarchical) way.


A typical roster

<query xmlns='jabber:iq:roster'> <item jid='shiels@jabber.org' subscription='both' name='Robert'> <group>Friends</group> </item> <item jid='piers@jabber.org' subscription='both' name='piers'> <group>Friends</group> </item> <item jid='sabine@pipetree.com' subscription='to' name='Sabine'> <group>Friends</group> </item> <item jid='jim@company-a.com' subscription='from' name='Jim'> <group>Work</group> </item> <item jid='jim@company-b.com' subscription='none' ask='subscribe' name='John'> <group>Work</group> </item> </query>


The subscription attribute is used to store the presence subscription state between the roster owner and the particular item that holds that attribute. With two of the friends, Robert and Piers, the roster owner is subscribed to each of their presences, and each of them is subscribed to the presence of the roster owner. This is denoted by the both value in the subscription attribute, which means that the presence subscription flows both ways. Where the subscription attribute has the value to (as in Sabine's case) or from (Jim's case), the subscription flows in only one direction. Here, the roster owner is subscribed to Sabine's presence (but Sabine is not subscribed to the roster owner's presence), and Jim is subscribed to the roster owner's presence (i.e., the roster owner has a presence subscription from Jim).[6]

Where the value of the subscription attribute is none (as in John's case), neither party has a subscription to the other. In this case, a further attribute, ask, may be used to reflect that a presence subscription request is in progress.[7]

The ask attribute can have one of two values:


subscribe
Denotes that a request to subscribe to a user's presence has been made
unsubscribe
Denotes that a request to unsubscribe from a user's presence has been
made In both cases, these requests are sent using a
<presence/> element with an appropriate value for the
type attribute.

The server is responsible for maintaining the subscription and ask attributes; the client may maintain all the other elements. If an item is updated by the server—for example, as a result of a correspondent accepting a previous subscription request—the server will push the updated item to the client (all clients, if the user is connected multiple times with different resources) with an IQ-set:


SEND: <iq type='set'> <query xmlns='jabber:iq:roster'> <item jid='john@company-b.com' subscription='to' name='John'/> </query> </iq>


Here, John has accepted the roster owner's subscription request by sending the following:


<presence to='dj@yak/Work' type='subscribed'/>


The server will update the roster item accordingly by removing the ask='subscribe' and setting the value of the subscription attribute to to.


jabber:iq:search


The jabber:iq:search is closely related to the jabber:iq:register namespace, in that the dance steps are pretty much the same. As with jabber:iq:register, you can discover which entities (usually server components) support search features from the results of an agents or browse query, as shown in Example 6-3.

Also, as with the jabber:iq:register namespace, the fields to be used in the interaction are first retrieved with an IQ-get qualified by the jabber:iq:search namespace. Here we see an example of that with the JUD running on the jabber.org server:


SEND: <iq type='get' to='users.jabber.org' id='800'> <query xmlns='jabber:iq:search'/> </iq>

RECV: <iq type='result' from='users.jabber.org' to='qmacro@jabber.org/laptop' id='800'> <query xmlns='jabber:iq:search'> <instructions> Fill in a field to search for any matching Jabber User </instructions> <first/> <last/> <nick/> <email/> </query> </iq>


To continue the similarity theme, an IQ-set is used to submit the search, sending back a value (or values) in the fields like this:

<email>pipetree.com</email>.
The only exciting feature of the jabber:iq:search

namespace is perhaps the way it can return results in response to an IQ-set. This depends on the component and how the feature is implemented.

While the JUD component will return all results in one IQ element:


RECV: <iq type='result' from='users.jabber.org' to='qmacro@jabber.org/laptop'> <query xmlns='jabber:iq:search'> <item jid='qmacro@jabber.org'> <name>DJ Adams</name> <first>DJ</first> <last>Adams</last> <nick>qmacro</nick> <email>dj@pipetree.com</email> </item> <item jid='piers@jabber.org'> <name>Piers Harding</name> <first>Piers</first> <last>Harding</last> <nick>pxh</nick> <email>piers@pipetree.com</email> </item> ... </query> </iq>


the component providing transport services to the ICQ IM system returns the results item by item:


RECV: <iq type='set' from='icq.jabber.org' id='icqs8' to='qmacro@jabber.org/laptop'> <query xmlns='jabber:iq:search'> <item jid='4711471@icq.jabber.org'> <given>DJ</given> <family>Adams</family> <nick>qmacro</nick> <email>dj@pipetree.com</email> </item> </query> </iq>

RECV: <iq type='set' from='icq.jabber.org' id='icqs8' to='qmacro@jabber.org/laptop'> <query xmlns='jabber:iq:search'> <item jid='1234567@icq.jabber.org'> <given>Piers</given> <family>Harding</family> <nick>pxh</nick> <email>piers@pipetree.com</email> </item> </query> </iq>


The component signals the end of the search results with an empty IQ-result element:


RECV: <iq type='result' from='icq.jabber.org' id='icqs8' to='qmacro@jabber.org/laptop'> <query xmlns='jabber:iq:search'/> </iq>


The anti-spoofing mechanism in the form of the <key/> tag, described in the earlier section titled "The <key/> tag," can also be used in conversations qualified by the jabber:iq:search namespace.


jabber:iq:time


The jabber:iq:time namespace qualifies an IQ-based conversation to make or respond to a query on time information.

To query the time at a particular entity, an IQ-get request like this is sent:


SEND: <iq type='get' id='time_19' to='conference.yak'> <query xmlns='jabber:iq:time'/> </iq>


Three pieces of information—the time in UTC (coordinated universal time) format, the local time zone, and a nice display version of the local time—are returned in response to such a query:


RECV: <iq type='result' id='time_19' to='sabine@yak/Work' from='conference.yak'> <query xmlns='jabber:iq:time'> <utc>20010520T08:55:38</utc> <tz>GMT</tz> <display>Sun May 20 09:55:38 2001</display> </query> </iq>


The format of the <tz/> and <display> tags is not fixed. While this is what the Conferencing service returns, a response from the JIM client would give "GMT Standard Time" and "20/05/01 09:55:38," respectively.


<note>If you consider that certain components can be connected to the Jabber backbone but be running on different hosts in different time zones, communicating over TCP socket connections (as described in Section 4.16 in Chapter 4), this may be more useful than you initially think.

</code>


Specifying clients as query targets


Many of these namespaces qualify queries that make just as much sense sent to a Jabber client as sent to a Jabber server or service. However, if you don't compose the recipient JID correctly, you could end up with an unexpected response.

Let's say you want to query the local time on Piers' client, which is connected to the Jabber server at jabber.org:


SEND: <iq type='get' id='time_21' to='piers@jabber.org'> <query xmlns='jabber:iq:time'/> </iq>


You could get a response similar to this:


RECV: <iq type='error' id='time_21' from='piers@jabber.org' to='qmacro@jabber.org/home'> <query xmlns='jabber:iq:time'/> <error code='503'>Service Unavailable</error> </iq>


Why? This query isn't addressed to a particular client or session. While <message/> elements can be addressed to a user JID in the form username@hostname and will be sent to the "primary" session according to presence priority, the recipients of <iq/> elements must be specified exactly. As we want to find out the time at Piers' client, which has the associated resource desktop, we must specify that resource in the JID:


SEND: <iq type='get' id='time_21' to='piers@jabber.org/desktop'> <query xmlns='jabber:iq:time'/> </iq>


This will give us the response we're looking for:


RECV: <iq type='result' id='time_21' to='qmacro@jabber/home' from='piers@jabber.org/desktop'> <query xmlns='jabber:iq:time'/> <utc>20010520T11:25:58</utc> <tz>CET</tz> <display>Sun May 20 13:25:58 2001</display> </query> </iq>



jabber:iq:version


Similar to the jabber:iq:time namespace, the jabber:iq:version namespace is used to make and respond to queries regarding the version of the particular piece of software being addressed. The query is formulated like this:


SEND: <iq type='get' id='ver-a' to=JID> <query xmlns='jabber:iq:version'/> </iq>


Responses depend on the entity being queried. Here are responses from three different entities:

  • A client (sjabber):
  • RECV: <iq type='result'

to='dj@yak/Work' from='sabine@yak/sjabber'> <query xmlns='jabber:iq:version'> <name>sjabber</name> <version>0.4</version> <os>linux</os> </query> </iq>

  • The Jabber server itself (well, the JSM):
  • RECV: <iq

type='result' to='dj@yak/Work' from='sabine@yak/sjabber'> <query xmlns='jabber:iq:version'> <name>jsm</name> <version>1.4.1</version> <os>linux 2.2.12-45SAP</os> </query> </iq>

  • And the JUD component:
  • RECV: <iq type='result'

to='dj@yak/Work' from='sabine@yak/sjabber'> <query xmlns='jabber:iq:version'> <name>jud</name> <version>0.4</version> <os>linux 2.2.12-45SAP</os> </query> </iq>

The jabber:iq:version namespace is used in the recipe in Section 9.3 in Chapter 9.



The X Namespaces


While the IQ namespaces are used in exchanging structured information in semiformalized conversations, the X namespaces are more ad hoc extensions that add value, context, and information to any type of packet.


jabber:x:autoupdate


The jabber:x:autoupdate namespace is used to carry information on where new version information can be found. Details and an example of this namespace's usage can be found in the description for the IQ version, jabber:iq:autoupdate, in Section 6.2.4.


jabber:x:conference


Just as jabber:x:autoupdate is related to its big brother, jabber:iq:autoupdate, so too is the jabber:x:conference namespace related to jabber:iq:conference. The <x/> version of the IQ-conference namespace is used to convey information about a conferencing room, usually attached to a message:


SEND: <message id='2113' to='robert@company-a.com'> <subject>Design Meeting</subject> <body>Robert - you're supposed to be at the meeting now!</body> <x xmlns='jabber:x:conference' jid='meeting1@meetings.company-a.com'/> </message>


If supported by the receiving client, this will be interpreted as an invitation to the room and the procedure for joining the room (in this case, identified with the JID meeting1@conf.company-a.com) can be automatically initiated:


SEND: <iq type='get' id='c4' to='meeting1@meetings.company-a.com'> <query xmlns='jabber:iq:conference'/> </iq>



jabber:x:delay


Messages are sometimes sent to entities that aren't available at that particular moment. If they are stored offline, they are timestamped, in the jabber:x:delay namespace, so that when they are finally received, the recipient can use this information to determine when they were originally sent:


RECV: <message to='sabine@yak/Work' from='yak'> <subject>Weekend at last!</subject> <body>Don't forget Father's Day on Sunday!</body> <x xmlns='jabber:x:delay' from='yak/announce/motd' stamp='20010615T09:00:01'>Announced</x> </message>


In this Message-Of-The-Day (MOTD) announcement, we see that, as well as the stamp attribute showing that the announcement was sent out on the Friday morning before Father's Day, a short text description, "Announced", is included.

The namespace is also used by the xdb component to timestamp various fragments of data stored in the user's records on the server. Here, we see that Sabine updated her user registration details (using a jabber:iq:register query during her session) at the beginning of March:


<query xmlns='jabber:iq:register' xdbns='jabber:iq:register'> <name>S. Reitz-Adams</name> <email>sabine@reitz-adams.org</email> <x xmlns='jabber:x:delay' stamp='20010302T12:15:42'>updated</x> </query>



jabber:x:encrypted


You can use the relatively new jabber:x:encrypted namespace to implement message-level security. It allows the attachment of encrypted data Public Key Infrastructure (PKI) techniques, meaning that the data is encrypted using the message sender's private key and decrypted by the recipient using the sender's public key.


SEND: <message to='john@company-a.com' id='m221'> <body>Top Secret!</body> <x xmlns='jabber:x:encrypted'> lxG/K9tFGgtk9yUNRTWUMwtI2ty27s6M0VzwWQBCr6Irwu1CiHTG9o pSfX4ff3Yusa4Ah7ippuD9qcl/KgX4HEBJtt4Dt9SPb86jmaGN1gdd dxqxeTFvFat3mwO/DvU8CKULwMi7ejgn/ib0WhSM2cfsJEIUP=TsL6 9HUY7eVvzKKe5CvMNnE/4UAQ4lDfbqqXVSdCO8swLaG1los1zGP8io lZXjlaz75YwVVYucrFw7EXKa/wTGVjAPnkWBwv/AYx5poIyjqWQt6q kLZmk5YA44PxAGveOHhVDxUuRW8MTtMUqEENYZDwfugOEGCBWol8=X BaPqH5t4fS24OiqO2sJVJjIbORrBD0kYU2xhwcM3KSS/ffBAHEjoQ+ WvxdFEtjYuzBtyI2a672oZvyA6IqIjpovvYtKFnP7ghKgpY3J9xhYg KKrWRIciH5rj3Imy2d87cCd8os5nWYkt8p1ZkebRoGPkIlvy0iL7m8 </x> </message>


The Jabber server itself does not currently provide any mechanisms for key management or exchange; the namespace is for the time being purely a marked container to hold encrypted data.


jabber:x:envelope


The jabber:x:envelope namespace describes more complex message-addressing details than the simple from and to attributes in the <message/> elements.

The first area in which this namespace is used is in server-side filtering, a service provided by the JSM's mod_filter module. For example, when a user sets a filter rule to forward all messages to someone else while he's not around:[8]


<rule name='absent'> <show>xa</show> <forward>john@company-b.com</forward> </rule>


a message such as this:


<message id='284' to='janet@company-b.com'> <body>Can you give me the sales figures for last quarter?</body> </message>


will be passed on to john@company-b.com in this form:


<message id='284' to='janet@company-b.com'> <body>Can you give me the sales figures for last quarter?</body> <x xmlns='jabber:x:envelope'> <forwardedby jid='janet@company-b.com'> <from jid='mark@company-b.com'> <cc jid='john@company-b.com'> </x> </message>


to add context information on where the message has come from.


jabber:x:event


Message events allow clients and servers alike to add information about the receipt and handling of messages at various stages of delivery. There are currently four types of events supported in this namespace:


Composing
The composing event, represented by the <composing/>
tag within the <x/> extension qualified by the
jabber:x:event namespace, can be set by clients and signifies
that the user is composing a reply to the message just sent.
Delivered
When a message is received by a client, it can set the
<delivered/> flag to signify that the message has been
received.
Displayed
The displayed event is used to indicate that the message sent has been
displayed to the user. This event is set, using the
<displayed/> tag, by clients.
Offline
When a message recipient is not connected, the JSM module
mod_offline will store the message and send it to the recipient
when she is next available. This offline storage event can be set by
the server, using the <offline/> tag, to notify the
sender that the message has been stored offline. The
<composing/>, <delivered/>, and
<displayed/> events are client events and are
appropriate to be set only by the client. The
<offline/> event is a server event and appropriate to
be set only by the server. In all cases, the events are set only if
the message originator requests that they are. Adding a
jabber:x:event extension to a message like this:


SEND: <message to='sabine@yak' id='M31'> <subject>Where are you?</subject> <body>Let me know when you get back.</body> <x xmlns='jabber:x:event'> <displayed/> <offline/> </x> </message>


is the way to request that we get notified:

  • If and when the message is stored offline by the server in the

eventuality that Sabine is not connected

  • When the message is eventually displayed to Sabine The former event will be set by the

server; the latter by Sabine's client.

Setting an event is similar to requesting one and uses the jabber:x:event namespace. Here is what we would receive if the server did store our message to Sabine offline:


RECV: <message to='dj@yak/Work' id='M31' from='sabine@yak'> <x xmlns='jabber:x:event'> <offline/> <id>M31</id> </x> </message>


That is, the <offline/> tag is sent back to the originator, along with an <id/> tag that contains the id of the message that was stored offline. Example 6-6 shows the receipt of a chat message and the <composing/> event being raised as Sabine starts to type her reply.


Raising and canceling the <composing/> event DJ sends a quick chat message to Sabine and requests that his client be notified when she starts typing her response:


RECV: <message to='sabine@yak/Work' from='dj@yak/home' id='122' type='chat'> <body>hey, want a coffee?</body> <thread>ABAF6FC6521546A2B65B19EA391CB72A</thread> <x xmlns='jabber:x:event'> <composing/> </x> </message>


Sabine starts to type, which fires the <composing/> event:


SEND: <message from='sabine@yak/Work' to='dj@yak/home'> <x xmlns='jabber:x:event'> <composing/> <id>122</id> </x> </message>


Sabine is distracted, and her client decides she's abandoned the reply and sends a cancellation of the <composing/> event, containing only the message id included when the event was originally raised:


SEND: <message from='sabine@yak/Work' to='dj@yak/home'> <x xmlns='jabber:x:event'> <id>122</id> </x> </message>



jabber:x:expire


The jabber:x:expire is a simple namespace to add a "use by" or "read by" stamp to a message. If you wish to send a message and impose a finite lifetime upon it, attach an expiry extension thus:


SEND: <message to='piers@pipetree.com' id='M24'> <subject>Twinkies!</subject> <body> I've got some fresh Twinkies here, stop by for one before they all disappear! </body> <x xmlns='jabber:x:expire' seconds='1800'/> </message>


If Piers was not connected when the message was sent, the mod_offline module would hold the message ready for when he reconnects. But before storing it, an extra attribute (stored) is added with the current time.

Example 6-7 shows what the relevant section of Piers' spool file would look like.


Storage of an offline message with the jabber:x:expire extension

<foo xmlns='jabber:x:offline' xdbns='jabber:x:offline'> <message to='piers@pipetree.com' id='M24' from='dj@pipetree.com/kitchen'> <subject>Twinkies!</subject> <body> I've got some fresh Twinkies here, stop by for one before they all disappear! </body> <x xmlns='jabber:x:expire' seconds='600' stored='993038415'/> <x xmlns='jabber:x:delay' from='dj@pipetree.com' stamp='20010620T12:00:15'> Offline Storage </x> </message> </foo>


When Piers reconnects, mod_offline retrieves the message and compares the current time with the value in the stored attribute. If the difference exceeds the desired lifetime of the message, as specified in the seconds attribute, the message is discarded. Otherwise, the seconds attribute value is reduced to reflect the amount of time the message sat in storage, the stored attribute is removed, and the message is sent to Piers.

Furthermore, if Piers' client supports it, a further check of the message's lifetime can be made before display, in case the message was stored in an inbox-style mechanism. (With Piers' luck, he probably missed out on the Twinkies.)


jabber:x:oob


We've already seen the jabber:x:oob in action earlier in the book. It is used in a similar way to its big brother, the jabber:iq:oob namespace. Attaching URLs to messages, typically done by mechanisms that deliver news- and alert-style headines, is done like this:


SEND: <message type='headline' to='qmacro@jabber.org/laptop' id='h12'> <subject>Jabber Foundation Public Conference</subject> <x xmlns='jabber:x:oob'> <url> http://www.jabbercentral.com/news/view.php?news_id=989358658 </url> <desc> Tomorrow, May 9th, a meeting regarding the Jabber Foundation will be held. </desc> </x> </message>


Multiple attachments can be made to a message, using multiple <x/> tags qualified by this namespace.

The RSS Delivery Mechanism, described in Section 9.3 in Chapter 9, and the Headline Viewer, described in Section 9.4, also in Chapter 9, both use the jabber:x:oob namespace.


jabber:x:roster


The jabber:x:roster namespace is related to its big brother, jabber:iq:roster; it is used to carry roster information as message attachments. This makes it straightforward for users to exchange contact information between themselves:


SEND: <message id='M91' to='shiels@jabber.org'> <body>Hi Robert - this is that fool I was telling you about...</body> <x xmlns='jabber:x:roster'> <item jid='qmacro@jabber.org' name='DJ Adams'> <group>Fools</group> </item> </x> </message>


Note that it is inappropriate to send the subscription-related attributes (subscription and ask, described in Section 6.2.12). Instead, it is up to the recipient to negotiate his own presence subscription arrangements with the contact or contacts (more than one item can be sent in such an attachment) listed.


jabber:x:signed


The jabber:x:signed namespace is related to the jabber:x:encrypted namespace and is used to stamp <presence/> and <message/> elements with a PKI-based signature, thus providing reliable identification of the packet originator.

In generating the signature block, some relevant data must be used to pass into the signing algorithm so that an electronic signature is produced. In the case of <presence/> elements, the contents of the <status/> tag are used, and in the case of <message/> elements, the contents of the <body/> tag are used.

The presence of a jabber:x:signed signature in a <presence/> packet is intended to signify that the client sending the packet supports such PKI infrastucture and, for example, is able to decrypt messages encrypted in the jabber:x:encrypted namespace.

Here's a <presence/> packet containing a signature; the data "All present and correct" is what is fed into the algorithm:


SEND: <presence from='piers@jabber.org' to='qmacro@pipetree.com'> <status>All present and correct</status> <x xmlns='jabber:x:signed'> p/B8CuePDUvAAHPuacDb2OYjAHTGn4BbqChrhxwH8ZTKJxL 9nUNH58OF=tl0VMDcSYizG5HFh </x> </presence>



The X::IQ Relationship


As has been noted, some of the X namespaces—autoupdate, conference, roster, and oob—have cousins in the IQ space. If you're still confused about which to use where, there's a rule of thumb about context: the IQ namespaces generally are used to qualify a conversation that revolves around whatever the namespace represents, while the X namespaces apply more to one-off, ad hoc, information-laden messages.

For example, the jabber:iq:conference namespace qualifies much of the content of a conversation between a user and the conferencing service regarding entry to a specific room. The jabber:x:conference namespace is used to provide context and meaning to a pointer to a room.

Likewise, the jabber:x:oob namespace qualifies a pointer to some piece of information that is out of band, whereas the jabber:iq:oob namespace provides context to a negotiation that leads to the usage of that external bandwidth.


Miscellaneous Namespaces


In addition to the standard Jabber namespaces that begin jabber:iq: and jabber:x:, a couple of others are used often and are worthy of our attention.

They're both outside the jabber: namespace because they don't originate within Jabber. The vCard format, represented by the vcard-temp namespace, is an emerging Internet standard used in many different environments, not just within Jabber. XHTML is a World Wide Web Consortium (W3C) standard that Jabber has adopted to carry rich text in messages and is represented in Jabber with the http://www.w3.org/1999/xhtml namespace.


The vcard-temp Namespace


The vcard-temp namespace represents the vCard format. It's a format used to provide information about an entity—a person, company, or even, in Jabber's case, a piece of software—in the form of a virtual business card.

The idea behind the vCard format, which is an emerging but as yet incomplete standard, is that it can be used to hold information about something in a formalized and parcel-like way. vCards can be attached to email messages and extracted from user directories and address books. The fact that the format is not yet a standard is reflected in the "temporary" namespace (vcard-temp) used to qualify vCard exchanges.


<note>Jabber uses the vCard format to hold details about various parts of the Jabber server; each component can have a vCard, as seen in Section 4.3 in Chapter 4. Each Jabber user can have a vCard, too.

</code> Retrievals of vCards, and updates, are made using IQs containing extensions qualified by the vcard-temp namespace. To request a vCard, send an IQ-get to the holder of the vCard you want, like this:


SEND: <iq type='get' to='qmacro@jabber.org' id='73'> <vcard xmlns='vcard-temp'/> </iq>


Rather than the usual tag name of query, vCard <iq/> extensions have the name vcard (this is sometimes seen in all caps or as vCard).

In response to this request, the vCard belonging to qmacro will be returned as shown in Example 6-8.


A response returning qmacro's vCard

RECV: <iq id='73' to='dj@gnu.mine.nu/home' type='result' from='qmacro@jabber.org'> <vCard xmlns='vcard-temp' version='3.0'> <BDAY/> <ORG> <ORGNAME/> <ORGUNIT/> </ORG> <TITLE/> <ROLE/> <TEL> <VOICE/> <HOME/> </TEL> <TEL> <fax/> <HOME/> </TEL> <TEL> <MSG/> <HOME/> </TEL> <ADR> <HOME/> <EXTADD/> <STREET/> <LOCALITY/> <REGION/> <PCODE/> <COUNTRY/> </ADR> <FN>DJ Adams</FN> <TEL> <VOICE/> <WORK/> </TEL> <TEL> <fax/> <WORK/> </TEL> <TEL> <MSG/> <WORK/> </TEL> <N> <GIVEN>DJ</GIVEN> <FAMILY>Adams</FAMILY> <MIDDLE/> </N> <ADR> <WORK/> <EXTADD/> <STREET/> <LOCALITY/> <REGION/> <PCODE/> <COUNTRY/> </ADR> <EMAIL>dj.adams@gmx.net <INTERNET/> <PREF/> </EMAIL> <NICKNAME>qmacro</NICKNAME> <URL>http://www.pipetree.com/~dj/</URL> </vCard> </iq>


Obviously, qmacro has not added values for all of the fields that the vCard format defines. Nevertheless, the response gives us a good idea of what sort of information can be stored.

There are different versions of the vCard format, as it matures. The version attribute shown in the response in Example 6-8 signifies which version the vCarddata returned conforms to. It's an optional attribute, and not all vCard requests will return responses that include such an attribute.

In fact, it's not the only thing that's optional. Requesting the vCard belonging to a Conferencing component called conf.gnu.mine.nu, for example, will elicit the result shown in Example 6-9. Here, the vCard information consists of just three fields: the full name of the component (<FN/>), the component's description (<DESC/>), and a URL (<URL/>). Not all entities will have vCards containing all the vCard elements, as this example shows. (If the vCard data for the Conferencing component looks familiar, that's because it is—we've seen how vCards for components are maintained, in the jabber.xml configuration. See Section 4.10.3 in Chapter 4 for details.)


Requesting a Conferencing component's vCard

SEND: <iq type='get' id='vc11' to='conf.gnu.mine.nu'> <vcard xmlns='vcard-temp'/> </iq>

RECV: <iq type='result' id='vc11' from='conf.gnu.mine.nu' to='qmacro@jabber.org/home'> <vCard xmlns='vcard-temp'> <FN>gnu Chat</FN> <DESC>Conferencing Component</DESC> <URL>http://www.gnu.mine.nu/</URL> </vCard> </iq>


Notice also that the response shown in Example 6-8 seems to have come from qmacro himself—the value in the <iq> element's from attribute seems to suggest that. In fact, qmacro was never aware of the request. What actually happens, when a request is made to retrieve a vCard belonging to a Jabber user, is that the JSM responds to the request; it jumps in on behalf of the user registered with it to answer the request. This means that Jabber user vCards can be retrieved whether or not the user is connected and available at the time of the request.

This is in contrast to component vCards; it is the components themselves who must respond to requests for vCards (in fact, to requests for anything addressed to them). If a component is not connected, the request will fail, in that an IQ-error (502, "Server Connect Failed") will be returned as the jabberd hub was unable to pass the request on.

That a user vCard can be retrieved independently of the user's availability highlights the fact that user vCards are stored on the Jabber server. The information is stored along with the rest of the user-specific information (such as private data and pending messages stored offline) in the user's spool file, in a similar way to how public and private data is stored, as shown in Example 6-2.

To maintain vCard information, an IQ-set is required:


<iq id='76' type='set'> <vCard xmlns='vcard-temp' version='3.0'> <BDAY>1966-09-03</BDAY> <ORG> <ORGNAME>Merlix</ORGNAME> <ORGUNIT/> </ORG> <TITLE>Tea boy</TITLE> <ROLE>Making the tea</ROLE> ... </vCard> </iq>


Not all of the vCard elements are shown to keep the example short, but don't assume that individual elements of a vCard can be maintained by sending only those elements back. The whole vCard must be sent in an IQ-set request for the vCard to be maintained. Whatever is received by the JSM is taken to be absolute, not relative, and replaces anything that was already stored in the spool.

Note that it's the maintainer's responsibility to specify a version attribute if one is required or desired.


The XHTML Namespace


As already shown in Section 5.4.1.2 in Chapter 5, the XHTML namespace, http://www.w3.org/1999/xhtml, is used to qualify an optional message tag <html/>, which can be used to carry a rich-text version of the message's <body/> contents.

Definitive information on the XHTML standard can be found at http://www.w3.org/1999/xhtml. As mentioned in Section 5.4.1.2 in Chapter 5, this namespace qualifies tags within <message/> elements that are optional. Jabber clients do not have to support rich-text formatting. If they do, a number of XHTML elements are required, and a number are optional. The protocol documentation section on Jabber's central documentation site at http://docs.jabber.org has full details.

Personal tools