This JEP defines a protocol for exchanging user avatars in Jabber/XMPP.
WARNING: This Standards-Track JEP is Experimental. Publication as a Jabber Enhancement Proposal does not imply approval of this proposal by the Jabber Software Foundation. Implementation of the protocol described herein is encouraged in exploratory implementations, but production systems should not deploy implementations of this protocol until it advances to a status of Draft.
Status: Experimental
Type: Standards Track
Number: 0084
Version: 0.5
Last Updated: 2005-03-28
JIG: Standards JIG
Approving Body: Jabber Council
Dependencies: XMPP Core, JEP-0030, JEP-0060
Supersedes: JEP-0008
Superseded By: None
Short Name: avatar
Email: temas@jabber.org
JID: temas@jabber.org
Email: pgmillard@jabber.org
JID: pgmillard@jabber.org
Email: julian@jabber.org
JID: julian@jabber.org
Email: stpeter@jabber.org
JID: stpeter@jabber.org
This Jabber Enhancement Proposal is copyright 1999 - 2005 by the Jabber Software Foundation (JSF) and is in full conformance with the JSF's Intellectual Property Rights Policy <http://www.jabber.org/jsf/ipr-policy.shtml>. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at <http://www.opencontent.org/openpub/>).
The preferred venue for discussion of this document is the Standards-JIG discussion list: <http://mail.jabber.org/mailman/listinfo/standards-jig>.
The Extensible Messaging and Presence Protocol (XMPP) is defined in the XMPP Core (RFC 3920) and XMPP IM (RFC 3921) specifications contributed by the Jabber Software Foundation to the Internet Standards Process, which is managed by the Internet Engineering Task Force in accordance with RFC 2026. Any protocols defined in this JEP have been developed outside the Internet Standards Process and are to be understood as extensions to XMPP rather than as an evolution, development, or modification of XMPP itself.
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
Many communication applications now allow for the association of a small image or buddy icon (avatar) with a user of that application. The avatar is not intended to be a defining portrait of the user, but rather a simple expression of the user's appearance, mood, status, and the like. This proposal outlines a way to incorporate avatars into the current Jabber platform by layering this functionality on top of Publish-Subscribe [1] (pubsub).
Pubsub was chosen as the base layer for avatars because of the need to publish a large amount of data to any number of users. Pubsub provides a straightforward mechanism for any user to subscribe to the avatar source and receive notifications from the publisher. The protocol defined herein uses two pubsub nodes: one node for "metadata" about the avatar state (called the "metadata node") and one for the avatar data itself (called the "data node"). This separation of metadata from data conserves bandwidth and enables both the publisher and the subscriber to cache the avatar data. (For example, a user might toggle between two or three avatars, in which case the user's contacts can display a locally cached version of the images without having to retrieve the full image each time.)
Finally, this JEP also allows storage of avatar data at an HTTP URL (see RFC 2068 [2]). This can be helpful as a fallback mechanism if a pubsub-aware data repository is not available. It also makes it possible for avatar images to be hosted on public websites (e.g., an end-user-oriented community site) and retrieved from that site rather than handled directly by the publishing client in any fashion.
This JEP addresses the following use cases for avatar publishers:
This JEP addresses the following use cases for avatar consumers:
In order to publish notifications related to its avatar, the avatar publisher MUST first create a node for its avatar metadata:
<iq type='set' from='juliet@capulet.com/chamber' to='pubsub.shakespeare.lit' id='create1'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <create node='avatar/info/juliet@capulet.com'/> <configure/> </pubsub> </iq>
<iq type='result' from='pubsub.shakespeare.lit' to='juliet@capulet.com/chamber' id='create1'/>
The avatar publisher SHOULD also publish information about its metadata node to its XMPP server via the "disco publish" protocol specified in Service Discovery [3], so that consumers of its avatar data can discover the metadata node even when the publisher is offline.
<iq type='set' from='juliet@capulet.com/chamber' id='dset1'> <query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/avatar'> <item jid='pubsub.shakespeare.lit' node='avatar/info/juliet@capulet.com' action='update'/> </query> </iq>
There are two allowable sources from which consumers retrieve avatar data:
If a data node is used, obviously the publisher MUST create a data node in addition to the already-created metadata node:
<iq type='set' from='juliet@capulet.com/chamber' to='pubsub.shakespeare.lit' id='create2'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <create node='avatar/data/juliet@capulet.com'/> <configure/> </pubsub> </iq>
<iq type='result' from='pubsub.shakespeare.lit' to='juliet@capulet.com/chamber' id='create2'/>
Before updating the avatar metadata node, the publisher MUST make sure that the avatar data is available at the data node or at an HTTP URL. When publishing the avatar data to the data node, the publisher MUST ensure that the value of the item 'id' attribute is the SHA1 (RFC 3174 [4]) hash of the image data (this can be used by the consumer to determine if a cached copy is still valid).
<iq type='set' from='juliet@capulet.com/chamber' to='pubsub.shakespeare.lit' id='publish1'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <publish node='avatar/data/juliet@capulet.com'> <item id='109f4b3c50d7b0df729d299bc6f8e9ef9066971f'> <avatar xmlns='http://jabber.org/protocol/avatar' type='image/png'> qANQR1DBwU4DX7jmYZnncm... </avatar> </item> </publish> </pubsub> </iq>
<iq type='result' from='pubsub.shakespeare.lit' to='juliet@capulet.com/chamber' id='publish1'/>
Whenever the publisher wishes to change its current avatar, it MUST update the metadata node, ensuring that the value of the avatar 'id' attribute is the SHA1 hash of the image data.
The following example shows metadata that specifies a pubsub data node:
<iq type='set' from='juliet@capulet.com/chamber' to='pubsub.shakespeare.lit' id='publish2'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <publish node='avatar/info/juliet@capulet.com'> <item id='current'> <avatar xmlns='http://jabber.org/protocol/avatar' jid='pubsub.shakespeare.lit' node='avatar/data/juliet@capulet.com' type='image/png' id='109f4b3c50d7b0df729d299bc6f8e9ef9066971f'/> </item> </publish> </pubsub> </iq>
Subscribers to the avatar would then receive an update from the metadata node:
<message to='romeo@montague.net' from='pubsub.shakespeare.lit'> <x xmlns='http://jabber.org/protocol/pubsub#event'> <items node='avatar/info/juliet@capulet.com'> <item id='current'> <avatar xmlns='http://jabber.org/protocol/avatar' jid='pubsub.shakespeare.lit' node='avatar/data/juliet@capulet.com' type='image/png' id='109f4b3c50d7b0df729d299bc6f8e9ef9066971f'/> </item> </items> </x> </message>
Alternatively, the metadata can specify an HTTP URL:
<iq type='set' from='juliet@capulet.com/chamber' to='pubsub.shakespeare.lit' id='publish2'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <publish node='avatar/info/juliet@capulet.com'> <item id='current'> <avatar xmlns='http://jabber.org/protocol/avatar' url='http://www.jabbercentral.org/avatars/happy.png' id='109f4b3c50d7b0df729d299bc6f8e9ef9066971f'/> </item> </publish> </pubsub> </iq>
Subscribers to the avatar would then receive an update from the metadata node:
<message to='romeo@montague.net' from='pubsub.shakespeare.lit'> <x xmlns='http://jabber.org/protocol/pubsub#event'> <items node='avatar/info/juliet@capulet.com'> <item id='current'> <avatar xmlns='http://jabber.org/protocol/avatar' url='http://www.jabbercentral.org/avatars/happy.png' id='109f4b3c50d7b0df729d299bc6f8e9ef9066971f'/> </item> </items> </x> </message>
In order to temporarily disable any avatar images, the publishing entity MUST send an empty <avatar/> element to the metadata node:
<iq type='set' from='juliet@capulet.com/chamber' to='pubsub.shakespeare.lit' id='publish3'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <publish node='avatar/info/juliet@capulet.com'> <item id='current'> <avatar xmlns='http://jabber.org/protocol/avatar'/> </item> </publish> </pubsub> </iq>
Other clients can see if avatar support is available by sending a Service Discovery items request to the other client and looking for the avatar item. The request MUST be sent to the bare JID (<user@host>) of the other user, further specified by a disco node of "http://jabber.org/protocol/avatar". (Sending the request to the bare JID enables one to discover whether an offline user has published disco information regarding avatars.)
<iq type='get' from='romeo@montague.net/orchard' to='juliet@capulet.com' id='items1'> <query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/avatar'/> </iq>
The result contains an item with the JID of the pubsub service where the publisher's avatar metadata (but not the avatar data itself) is published, along with the specific node for that metadata:
<iq type='result' from='juliet@capulet.com' to='romeo@montague.net/orchard' id='items1'> <query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/avatar'> <item jid='pubsub.shakespeare.lit' node='avatar/info/juliet@capulet.com'/> </query> </iq>
The consumer application SHOULD then send a disco#info request to the node in order to determine its identity.
In order to receive notifications of changes to the publisher's avatar, a consumer MUST subscribe to the metadata node maintained by the publisher.
<iq type='set' from='romeo@montague.net/orchard' to='pubsub.shakespeare.lit' id='sub1'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <subscribe node='avatar/info/juliet@capulet.com' jid='romeo@montague.net'/> </pubsub> </iq>
<iq type='result' from='pubsub.shakespeare.lit' to='romeo@montague.net/orchard' id='sub1'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <entity node='avatar/info/juliet@capulet.com' jid='romeo@montague.net' affiliation='none' subscription='subscribed'/> </pubsub> </iq>
The consumer will now receive notifications published to the metadata node by the avatar publisher.
Alternatively, the consumer MAY retrieve the current avatar metadata from the pubsub service:
<iq type='get' from='romeo@montague.net/orchard' to='pubsub.shakespeare.lit' id='ps-items1'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <items node='avatar/info/juliet@capulet.com' max_items='1'/> </pubsub> </iq>
<iq type='result' from='pubsub.shakespeare.lit' to='romeo@montague.net/orchard'' id='ps-items1'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <items node='avatar/info/juliet@capulet.com'> <item> <avatar xmlns='http://jabber.org/protocol/avatar' jid='pubsub.shakespeare.lit' node='avatar/data/juliet@capulet.com' type='image/png' id='a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'/> </item> </items> </pubsub> </iq>
If the <avatar/> element sent to the metadata node possesses a 'jid' attribute (optionally supplemented by a 'node' attribute), the avatar data is hosted at a pubsub service. Therefore, in order to retrieve the avatar image data, the requesting entity MUST send a request to the specified JID or JID+node, including an 'id' attribute that matches the value provided in the metadata result.
<iq type='get' from='romeo@montague.net/orchard' to='pubsub.shakespeare.lit' id='ps-items2'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <items node='avatar/data/juliet@capulet.com'> <item id='a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'/> </items> </pubsub> </iq>
The result contains the avatar image data:
<iq type='result' from='pubsub.shakespeare.lit' id='ps-items2'> <pubsub xmlns='http://jabber.org/protocol/pubsub'> <items node='avatar/data/juliet@capulet.com'> <item id='a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'> <avatar xmlns='http://jabber.org/protocol/avatar' type='image/png'> qANQR1DBwU4DX7jmYZnncm... </avatar> </item> </items> </pubsub> </iq>
If the <avatar/> element sent to the metadata node possesses a 'url' attribute, the avatar data is hosted at an HTTP URL. Therefore, in order to retrieve the avatar image data, the requesting entity MUST send an HTTP request to the specified URL.
The <avatar> element is the root and only element qualified by the 'http://jabber.org/protocol/avatar' namespace. It has three forms, as described below.
When the <avatar/> element is empty but possesses no attributes, avatar publishing has been disabled:
<avatar xmlns='http://jabber.org/protocol/avatar'/>
When the <avatar/> element is empty and possesses attributes, the element specifies metadata about an avatar image. There are two cases:
In both cases, the element MUST possess an 'id' attribute whose value is the SHA1 sum of the image data (note: this is also the value that MUST be used as the ItemID of the pubsub item). In addition, the element MUST NOT contain character data.
When the metadata specifies a pubsub data node, the element MUST possess the following attributes:
In addition, the element MAY possess the following attribute:
Here is an example:
<avatar xmlns='http://jabber.org/protocol/avatar' jid='pubsub.shakespeare.lit' node='avatar/data/juliet@capulet.com' type='image/png' id='109f4b3c50d7b0df729d299bc6f8e9ef9066971f'/>
When the metadata specifies an HTTP URL, the element MUST possess the following attributes:
Here is an example:
<avatar xmlns='http://jabber.org/protocol/avatar' url='http://www.jabbercentral.org/avatars/happy.png' id='109f4b3c50d7b0df729d299bc6f8e9ef9066971f'/>
Note: Naturally, the 'type' attribute is unnecessary in metadata about HTTP URLs, since it can be determined via HTTP.
The final format of the avatar data node is the carrier of the data:
<avatar xmlns='http://jabber.org/protocol/avatar' type='image/png'> BASE 64 DATA </avatar>
This is the main carrier of the image data. The type SHOULD be one of the following MIME types registered with the Internet Assigned Numbers Authority (IANA) [5]:
Support for image/png is REQUIRED, support for image/jpeg and image/gif are RECOMMENDED, and all other formats are OPTIONAL.
Other formats MAY be used, but interoperability may be compromised at that point.
The character data of the <avatar/> MUST be image data encoded as Base64 as specified in Section 3 of RFC 3548 [6]. If the character data for the image data is present, the 'type' attribute MUST be included.
Certain restrictions are placed upon the image. First, the image height and width MUST be between thirty-two (32) and sixty-four (64) pixels. The suggested size is sixty-four (64) pixels high and sixty-four (64) pixels wide. Images SHOULD be square, but this is not required. Finally, images MUST use less than eight (8) kilobytes of data.
There are no security features or concerns related to this proposal.
This JEP makes use of IANA-registered MIME types, but requires no interaction with the Internet Assigned Numbers Authority (IANA) [7].
The Jabber Registrar [8] shall include 'http://jabber.org/protocol/avatar' in its registry of protocol namespaces.
<?xml version='1.0' encoding='UTF-8'?> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' targetNamespace='http://jabber.org/protocol/avatar' xmlns='http://jabber.org/protocol/avatar' elementFormDefault='qualified'> <xs:element name='avatar'> <xs:complexType> <xs:simpleContent> <xs:extension base='xs:string'> <xs:attribute name='id' type='xs:string' use='optional'/> <xs:attribute name='jid' type='xs:string' use='optional'/> <xs:attribute name='node' type='xs:string' use='optional'/> <xs:attribute name='type' type='xs:string' use='optional'/> <xs:attribute name='url' type='xs:string' use='optional'/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> </xs:schema>
1. JEP-0060: Publish-Subscribe <http://www.jabber.org/jeps/jep-0060.html>.
2. RFC 2068: Hypertext Transport Protocol -- HTTP/1.1 <http://www.ietf.org/rfc/rfc2068.txt>.
3. JEP-0030: Service Discovery <http://www.jabber.org/jeps/jep-0030.html>.
4. RFC 3174: US Secure Hash Algorithm 1 (SHA1) <http://www.ietf.org/rfc/rfc3174.txt>.
5. The Internet Assigned Numbers Authority (IANA) is the central coordinator for the assignment of unique parameter values for Internet protocols, such as port numbers and URI schemes. For further information, see <http://www.iana.org/>.
6. RFC 3548: The Base16, Base32, and Base64 Data Encodings <http://www.ietf.org/rfc/rfc3548.txt>.
7. The Internet Assigned Numbers Authority (IANA) is the central coordinator for the assignment of unique parameter values for Internet protocols, such as port numbers and URI schemes. For further information, see <http://www.iana.org/>.
8. The Jabber Registrar maintains a list of reserved Jabber protocol namespaces as well as registries of parameters used in the context of protocols approved by the Jabber Software Foundation. For further information, see <http://www.jabber.org/registrar/>.
END