JEP-0XXX: Multi-User Chat+

This JEP defines a robust protocol for XMPP-based text conferencing that is a superset of JEP-0045.


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.


JEP Information

Status: Experimental
Type: Standards Track
Number: 0XXX
Version: 0.1
Last Updated: 2004-12-16
JIG: Standards JIG
Approving Body: Jabber Council
Dependencies: XMPP Core, XMPP IM, JEP-0004, JEP-0030, JEP-0068, JEP-0045, JEP-0082
Supersedes: JEP-0045
Superseded By: None
Short Name: muc+
Schema for muc: <http://jabber.org/protocol/muc/muc.xsd>
Schema for muc#admin: <http://jabber.org/protocol/muc/admin.xsd>
Schema for muc#owner: <http://jabber.org/protocol/muc/owner.xsd>
Schema for muc#user: <http://jabber.org/protocol/muc/user.xsd>

Author Information

Peter Saint-Andre

Email: stpeter@jabber.org
JID: stpeter@jabber.org

Nolan Eakins

Email: sneakin@semanticgap.com
JID: sneakin@semanticgap.com

Legal Notice

This Jabber Enhancement Proposal is copyright 1999 - 2004 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.php>. 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/>).

Discussion Venue

The preferred venue for discussion of this document is the Standards-JIG discussion list: <http://mail.jabber.org/mailman/listinfo/standards-jig>.

Relation to XMPP

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.

Conformance Terms

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.


Table of Contents

1. Introduction
2. Scope
3. Requirements
4. Terminology
4.1. General Terms
4.2. Room Types
5. Roles and Affiliations
5.1. Roles
5.1.1. Privileges
5.1.2. Changing Roles
5.2. Affiliations
5.2.1. Privileges
5.2.2. Changing Affiliations
6. Occupant Use Cases
6.1. Discovering Component Support for MUC
6.2. Discovering Client Support for MUC
6.3. Entering a Room
6.3.1. Groupchat 1.0 Protocol
6.3.2. Basic MUC Protocol
6.3.3. Presence Broadcast
6.3.4. Default Roles
6.3.5. Non-Anonymous Rooms
6.3.6. Semi-Anonymous Rooms
6.3.7. Password-Protected Rooms
6.3.8. Members-Only Rooms
6.3.9. Banned Users
6.3.10. Nickname Conflict
6.3.11. Max Users
6.3.12. Discussion History
6.3.13. Managing Discussion History
6.3.14. Room Creation
6.4. Exiting a Room
6.5. Changing Nickname
6.6. Changing Availability Status
6.7. Inviting Another User to a Room
6.8. Requesting and Reserving an Unique Room Name
6.9. Converting a One-to-One Chat Into a Conference
6.10. Modifying the Room Subject
6.11. Sending a Private Message
6.12. Sending a Message to All Occupants
6.13. Registering with a Room
6.14. Discovering Reserved Room Nickname
7. Changing Roles
7.1. Basic Role Change
7.1.1. Changing an Occupant's Role to 'none'
7.2. Requesting a Role List
7.3. Changing Multiple Roles
8. Changing Affiliations
8.1. Basic Affiliation Change
8.1.1. Changing an Occupant's Affiliation to 'outcast'
8.1.2. Changing an Occupant's Affiliation to 'member'
8.2. Requesting an Affiliation List
8.3. Changing Multiple Affiliations
9. Moderator Use Cases
10. Admin Use Cases
10.1. Approving Registration Requests
11. Owner Use Cases
11.1. Creating a Room
11.2. Subsequent Room Configuration
11.3. Destroying a Room
12. Error and Status Codes
13. Security Considerations
14. IANA Considerations
15. Jabber Registrar Considerations
15.1. Protocol Namespaces
15.2. Service Discovery Category/Type
15.3. Service Discovery Features
15.4. Well-Known Service Discovery Nodes
15.5. Field Standardization
15.5.1. muc#register FORM_TYPE
15.5.2. muc#roomconfig FORM_TYPE
15.5.3. muc#roominfo FORM_TYPE
16. Business Rules
16.1. Room JIDs
16.2. Message
16.3. Presence
16.4. IQ
17. Implementation Notes
17.1. Services
17.1.1. Allowable Traffic
17.2. Clients
17.2.1. IRC Command Mapping
18. XML Schemas
18.1. http://jabber.org/protocol/muc
18.2. http://jabber.org/protocol/muc#user
18.3. http://jabber.org/protocol/muc#admin
18.4. http://jabber.org/protocol/muc#owner
19. Acknowledgements
Notes
Revision History


1. Introduction

Multi-User Chat [1] defines a usable protocol for text conferencing. While good it creates more complexity than is necessary, and it stepped too far into the details of implementation from the terminology used and use cases it described. This JEP is practically the same as Multi-User Chat [2], except that it simplifies the presentation of Multi-User Chat [3] by giving it a refactoring making it more powerful as a protocol. Some use cases have been condensed making it easier for implementors to implement, while also allowing greater versatility through some simple changes and additions.

This JEP aims to allow a client that implements Multi-User Chat [4] to work with a MUC+ service without any changes. The defined protocol is basically a superset of what JEP-0045 defined. Thus the same schemas and namespaces that JEP-0045 defined are used with some minor changes and additions.

This JEP has condensed, changed, or added to JEP-0045 in the following ways:

2. Scope

This JEP addresses common requirements related to configuration of, participation in, and administration of individual text-based conference rooms. All of the requirements addressed herein apply at the level of the individual room and are "common" in the sense that they have been widely discussed within the Jabber community or are familiar from existing text-based conference environments outside of Jabber (e.g., Internet Relay Chat as defined in RFC 1459 [5]).

This JEP explicitly does not address the following:

This limited scope is not meant to disparage such topics, which are of inherent interest; however, it is meant to focus the discussion in this JEP and to present a comprehensible proposal that can be implemented by Jabber client and component developers alike. Future JEPs may of course address the topics mentioned above.

3. Requirements

This JEP must address the minimal functionality provided by existing multi-user chat services in Jabber. For the sake of backward-compatibility, this JEP uses the original "groupchat 1.0" protocol for this baseline functionality, with the result that:

The additional features and functionality addressed in this JEP include the following:

  1. "native" conversation logging (no bot required)
  2. enabling users to request membership in a room
  3. enabling occupants to view an occupant's full JID in a non-anonymous room
  4. enabling moderators to view an occupant's full JID in a semi-anonymous room
  5. allowing only moderators to change the room subject
  6. enabling moderators to kick participants and visitors from the room
  7. enabling moderators to grant and revoke voice (i.e., the privilege to speak) in a moderated room
  8. enabling admins to grant and revoke moderator privileges
  9. enabling admins to ban users from the room
  10. enabling admins to grant and revoke membership privileges
  11. enabling owners to limit the number of occupants
  12. enabling owners to specify other owners
  13. enabling owners to grant and revoke administrative privileges
  14. enabling owners to destroy the room

In addition, this JEP provides protocol elements for supporting the following room types:

  1. public or hidden
  2. persistent or temporary
  3. password-protected or unsecured
  4. members-only or open
  5. moderated or unmoderated
  6. non-anonymous or semi-anonymous

4. Terminology

4.1 General Terms

Affiliation — a long-lived association or connection with a room; the possible affiliations are "owner", "admin", "member", and "outcast" (naturally it is also possible to have no affiliation); affiliation is orthogonal to role. An affiliation lasts across a user's visits to a room.

Ban — to remove a user from a room such that the user is not allowed to re-enter the room (until and unless the ban has been removed). A banned user has an affiliation of "outcast".

Bare JID — the user@host by which a user is identified outside the context of any existing session or resource; contrast with Full JID and Room JID.

Full JID — the user@host/resource by which an online user is identified outside the context of a room; contrast with Bare JID and Room JID.

GC — the minimal "groupchat 1.0" protocol [6] currently in use for text-based conferencing in Jabber.

History — a limited number of message stanzas sent to a new occupant to provide the context of current discussion.

Invitation — a special message sent from one user to another asking the recipient to join a room.

IRC — Internet Relay Chat.

Kick — to temporarily remove a participant or visitor from a room; the user is allowed to re-enter the room at any time. A kicked user has a role of "none".

Logging — storage of discussions that occur within a room for future retrieval inside or outside the context of the room.

Member — a user who is on the "whitelist" for a members-only room or who is registered with an open room. A member has an affiliation of "member".

Moderator — a room role that is usually associated with room admins but that may be granted to non-admins; is allowed to kick users, grant and revoke voice, etc. A moderator has an affiliation of "moderator".

MUC — the multi-user chat protocol for text-based conferencing documented in Multi-User Chat [7]; occasionally refered to as "the original MUC".

MUC+ — the multi-user chat protocol for text-based conferencing documented in this JEP that is a superset of MUC.

Occupant — any Jabber user who is in a room (this is an "abstract class" and does not correspond to any specific role).

Outcast — a user who has been banned from a room. An outcast has an affiliation of "outcast".

Participant — an occupant who does not have administrative privileges; in a moderated room, a participant is further defined as having voice (in contrast to a visitor). A participant has a role of "participant".

Private Message — a message sent from one occupant directly to another's room JID (not to the room itself for broadcasting to all occupants).

Role — a temporary position or privilege level within a room, orthogonal to a user's long-lived affiliation with the room; the possible roles are "moderator", "participant", and "visitor" (it is also possible to have no defined role). A role lasts only for the duration of an occupant's visit to a room.

Room — a virtual space that Jabber users figuratively enter in order to participate in real-time, text-based conferencing with more than one other user.

Room Administrator — a user empowered by the room owner to perform administrative functions such as banning users; however, is not allowed to change defining room features. An admin has an affiliation of "admin".

Room ID — the node identifier portion of a Room JID, which may be opaque and thus lack meaning for human users (see Business Rules for syntax); contrast with Room Name.

Room JID — the <room@service/nick> by which an occupant is identified within the context of a room; contrast with Bare JID and Full JID.

Room Name — a user-friendly, natural-language name for a room, configured by the room owner and presented in Service Discovery queries; contrast with Room ID.

Room Nickname — the resource identifier portion of a Room JID (see Business Rules for syntax).

Room Owner — the Jabber user who created the room, or a Jabber user who has been designated by the room creator as someone with owner privileges (if allowed); is allowed to change defining room features as well as perform all administrative functions. An owner has an affiliation of "owner".

Room Roster — a Jabber client's representation of the occupants in a room.

Server — a Jabber server that may or may not have associated with it a text-based conferencing service.

Service — a host that offers text-based conferencing capabilities; often but not necessarily a sub-domain of a Jabber server (e.g., conference.jabber.org).

Subject — a temporary discussion topic within a room.

Visit — a user's "session" in a room, beginning when the user enters the room (i.e., becomes an occupant) and ending when the user exits the room.

Visitor — in a moderated room, an occupant who does not have voice (in contrast to a participant). A visitor has a role of "visitor".

Voice — in a moderated room, the privilege to send messages to all occupants.

4.2 Room Types

Fully-Anonymous Room — a room in which the full JIDs or bare JIDs of occupants cannot be discovered by anyone, including room admins and room owners; such rooms are NOT RECOMMENDED or explicitly supported by MUC, but are possible using this protocol; contrast with Non-Anonymous Room and Semi-Anonymous Room.

Hidden Room — a room that cannot be found by any user through normal means such as searching and service discovery; antonym: Public Room.

Members-Only Room — a room that a user cannot enter without being affiliated with room as a 'member'; antonym: Open Room.

Moderated Room — a room in which only those with "voice" may send messages to all occupants; antonym: Unmoderated Room.

Non-Anonymous Room — a room in which occupants' full JIDs are exposed to all occupants, although they may choose any desired room nickname; contrast with Semi-Anonymous Room and Fully-Anonymous Room.

Open Room — a room that anyone may enter unless their affiliation is 'outcast'; antonym: Members-Only Room.

Password-Protected Room — a room that a user cannot enter without first providing the correct password; antonym: Unsecured Room.

Persistent Room — a room that is not destroyed if the last occupant exits; antonym: Temporary Room.

Public Room — a room that can be found by any user through normal means such as searching and service discovery); antonym: Hidden Room.

Semi-Anonymous Room — a room in which occupants' full JIDs can be discovered by room admins only; contrast with Fully-Anonymous Room and Non-Anonymous Room.

Temporary Room — a room that is destroyed if the last occupant exits; antonym: Persistent Room.

Unmoderated Room — a room in which any occupant is allowed to send messages to all occupants; antonym: Moderated Room.

Unsecured Room — a room that anyone is allowed to enter without first providing the correct password; antonym: Password-Protected Room.

5. Roles and Affiliations

There are two dimensions along which we can measure a user's connection with or position in a room. One is the user's long-lived affiliation with a room — e.g., a user's status as an owner or an outcast. The other is a user's role while an occupant of a room — e.g., an occupant's position as a moderator with the ability to kick visitors and participants. These two dimensions are orthogonal to each other, since an affiliation lasts across visits, while a role lasts only for the duration of a visit. In addition, there is no one-to-one correspondence between roles and affiliations; for example, someone who is not affiliated with a room may be a (temporary) moderator, and a member may be a participant or a visitor in a moderated room. These concepts are explained more fully below.

5.1 Roles

There are four defined roles that an occupant MAY have:

  1. Moderator
  2. Participant
  3. Visitor
  4. None (the absence of a role)

These roles are temporary in that they do not persist across a user's visits to the room and MAY change during the course of an occupant's visit to the room. In addition, there is no one-to-one mapping between these roles and a user's affiliation with the room (e.g., a member could be a participant or a visitor).

A moderator is the most powerful occupant within the context of the room, and can to some extent manage other occupants' roles in the room. A participant has fewer privileges than a moderator, although he or she always has the right to speak. A visitor is a more restricted role within the context of a moderated room, since visitors are not allowed to send messages to all occupants.

Roles are granted, revoked, and maintained based on the occupant's room nickname or full JID rather than bare JID. The privileges associated with these roles, as well as the actions that trigger changes in roles, are defined below.

Information about roles MUST be sent in all presence stanzas generated or reflected by the room and thus sent to occupants.

5.1.1 Privileges

For the most part, roles exist in a hierarchy. For instance, a participant can do anything a visitor can do, and a moderator can do anything a participant can do. Each role has privileges not possessed by the next-lowest role; these privileges are specified in the following table as defaults (naturally an implementation MAY provide configuration options that override these defaults).

Table 1: Privileges Associated With Roles

Privilege None Visitor Participant Moderator
Present in Room No Yes Yes Yes
Receive Messages No Yes Yes Yes
Change Availability Status No Yes Yes Yes
Change Room Nickname No Yes* Yes Yes
Send Private Messages No Yes* Yes Yes
Invite Other Users No Yes* Yes* Yes
Send Messages to All No No** Yes Yes
Modify Subject No No Yes* Yes
Kick Participants and Visitors No No No Yes
Change a role to 'participant' No No No Yes
Change a role to 'visitor' No No No Yes***

* Default; configuration settings MAY further restrict this privilege.

** An implementation MAY use 'participant' as the default for occupants in unmoderated rooms.

*** A moderator MUST NOT be able to revoke voice privileges from an admin or owner.

5.1.2 Changing Roles

The ways in which an occupant's role changes are well-defined. Sometimes the change results from the occupant's own action (e.g., entering or exiting the room), whereas sometimes the change results from an action taken by a moderator, admin, or owner. If an occupant's role changes, a compliant component implementation MUST change the occupant's role to reflect the change and communicate that to all occupants. Role changes and their triggering actions are specified in the following table.

Table 2: Role State Chart

> None Visitor Participant Moderator
None Enter moderated room Enter unmoderated room Admin grants moderator privileges
Visitor Exit room or be kicked by a moderator Moderator grants voice Admin grants moderator privileges
Participant Exit room or be kicked by a moderator Moderator revokes voice Admin grants moderator privileges
Moderator Exit room Admin changes role to visitor Admin changes role to participant or revokes moderator privileges **

* A moderator MUST NOT be able to revoke moderator privileges from an occupant who is equal to or above the moderator in the hierarchy of affiliations.

5.2 Affiliations

There are five defined affiliations that a user MAY have in relation to a room:

  1. Owner
  2. Admin
  3. Member
  4. Outcast
  5. None (the absence of an affiliation)

These affiliations are long-lived in that they persist across a user's visits to the room and are not affected by happenings in the room. In addition, there is no one-to-one mapping between these affiliations and an occupant's role within the room. Affiliations are granted, revoked, and maintained based on the user's bare JID.

If a user without a defined affiliation enters a room, the user's affiliation is defined as "none"; however, this affiliation does not persist across visits.

Owners and admins are by definition immune from certain actions. Specifically, an owner or admin cannot be kicked from a room and cannot be banned from a room. An admin MUST first lose his or her affiliation (i.e., have an affiliation of "none" or "member") before such actions could be performed on them.

The member affiliation provides a way for a room owner or admin to specify a "whitelist" of users who are allowed to enter a members-only room. When a member enters a members-only room, his or her affiliation does not change, no matter what his or her role is. The member affiliation also provides a way for users to effectively register with an open room and thus be lastingly associated with that room in some way (one result may be that the user's nickname is reserved in the room).

An outcast is a user who has been banned from a room and who is not allowed to enter the room.

Information about affiliations MUST be sent in all presence stanzas generated or reflected by the room and sent to occupants.

5.2.1 Privileges

For the most part, affiliations exist in a hierarchy. For instance, an owner can do anything an admin can do, and an admin can do anything a member can do. Each affiliation has privileges not possessed by the next-lowest affiliation; these privileges are specified in the following table.

Table 3: Privileges Associated With Affiliations

Privilege Outcast None Member Admin Owner
Enter Open Room No Yes** Yes Yes Yes
Register with an Open Room No Yes n/a n/a n/a
Enter Members-Only Room No No Yes* Yes Yes
Ban Members and Unaffiliated Users No No No Yes Yes
Change an affiliation to/from 'member' No No No Yes Yes
Change a role to/from 'moderator' No No No Yes** Yes**
Change an affiliation to/from 'admin' No No No No Yes
Change an affiliation to/from 'owner' No No No No Yes
Change Room Definition No No No No Yes
Destroy Room No No No No Yes

* As a default, an unaffiliated user enters a moderated room as a visitor, and enters an open room as a participant. A member enters a room as a participant. An admin or owner enters a room as a moderator.

** An admin or owner MUST NOT be able to revoke moderation privileges from another admin or owner.

5.2.2 Changing Affiliations

The ways in which a user's affiliation changes are well-defined. Sometimes the change results from the user's own action (e.g., registering as a member of the room), whereas sometimes the change results from an action taken by an admin or owner. If a user's affiliation changes, a compliant component implementation MUST change the user's affiliation to reflect the change and communicate that to all occupants. Affiliation changes and their triggering actions are specified in the following table.

Table 4: Affiliation State Chart

-> Outcast None Member Admin Owner
Outcast Admin or owner removes ban Admin or owner changes affiliation to "member" Owner changes affiliation to "admin" Owner changes affiliation to "owner"
None Admin or owner applies ban Admin or owner changes affiliation to "member", or user registers as member (if allowed) Owner changes affiliation to "admin" Owner changes affiliation to "owner"
Member Admin or owner applies ban Admin or owner changes affiliation to "none" Owner changes affiliation to "admin" Owner changes affiliation to "owner"
Admin Owner applies ban Owner changes affiliation to "none" Owner changes affiliation to "member" Owner changes affiliation to "owner"
Owner Owner applies ban Owner changes affiliation to "none" Owner changes affiliation to "member" Owner changes affiliation to "admin"

6. Occupant Use Cases

The main actor in a multi-user chat environment is the occupant, who can be said to be located "in" a multi-user chat room and to participate in the discussions held in that room (for the purposes of this JEP, participants and visitors are considered to be "mere" occupants, since they possess no administrative privileges). As will become clear, the protocol elements proposed in this JEP to fulfill the occupant use cases fall into three categories:

  1. existing "groupchat 1.0" protocol for minimal functionality

  2. straightforward applications of the "groupchat 1.0" protocol, for example to handle some of the errors related to new room types

  3. new protocol elements to handle functionality not covered by "groupchat 1.0" (room invites, room passwords, extended presence related to room roles and affiliations); these are contained in the new 'http://jabber.org/protocol/muc#user' namespace

Note: All client-generated examples herein are presented from the perspective of the service, with the result that all stanzas received by a service contain a 'from' attribute corresponding to the sender's full JID as added by a normal Jabber router or session manager. In addition, normal IQ result stanzas sent upon successful completion of a request are not shown. Most of the examples in this document use the scenario of the witches' meeting held in a dark cave at the beginning of Act IV, Scene I of Shakespeare's Macbeth. The characters are as follows:

Table 5: Dramatis Personae

Room Nickname Full JID Affiliation
firstwitch crone1@shakespeare.lit/desktop Owner
secondwitch wiccarocks@shakespeare.lit/laptop Admin
thirdwitch hag66@shakespeare.lit/pda None

6.1 Discovering Component Support for MUC

Before entering a room, a Jabber user may want to discover if the room complies with the Multi-User Chat protocol.

A compliant implementation MUST support Service Discovery [8].

Example 1. User Queries Chat Service for MUC Support via Disco

<iq from='hag66@shakespeare.lit/pda'
    id='disco1'
    to='macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
    

The service MUST return its identity and the features it supports:

Example 2. Service Returns Disco Info Results

<iq from='macbeth.shakespeare.lit'
    id='disco1'
    to='hag66@shakespeare.lit/pda'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    <identity
        category='conference'
        name='Macbeth Chat Service'
        type='text'/>
    <feature var='http://jabber.org/protocol/muc'/>
    <feature var='http://jabber.org/protocol/muc#plus'/>
  </query>
</iq>
    

Notes: because MUC+ is a superset of MUC and aims to allow older clients to work with a MUC+ service, both features MUST be returned. Whereas MUC is a superset of the old "Groupchat 1.0" protocol, a MUC service SHOULD NOT return a <feature var='gc-1.0'/> entry in a disco#info result.

The disco protocol also enables a user to query a service for a list of associated items, which in the case of a chat service would mainly consist of the specific chat rooms hosted by the service.

Example 3. User Queries Chat Service for Associated Items

<iq from='hag66@shakespeare.lit/pda'
    id='disco2'
    to='macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
    

Example 4. Service Returns Disco Item Results

<iq from='macbeth.shakespeare.lit'
    id='disco2'
    to='hag66@shakespeare.lit/pda'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#items'>
    <item jid='heath@macbeth.shakespeare.lit'
          name='A Lonely Heath'/>
    <item jid='darkcave@macbeth.shakespeare.lit'
          name='A Dark Cave'/>
    <item jid='forres@macbeth.shakespeare.lit'
          name='The Palace'/>
    <item jid='inverness@macbeth.shakespeare.lit'
          name='Macbeth&apos;s Castle'/>
  </query>
</iq>
    

Using disco, a user may also query a specific chat room for more detailed information:

Example 5. User Queries for Information about a Specific Chat Room

<iq from='hag66@shakespeare.lit/pda'
    id='disco3'
    to='darkcave@macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
    

The room MUST return its identity and SHOULD return the features it supports:

Example 6. Room Returns Disco Info Results

<iq from='darkcave@macbeth.shakespeare.lit'
    id='disco3'
    to='hag66@shakespeare.lit/pda'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    <identity
        category='conference'
        name='A Dark Cave'
        type='text'/>
    <feature var='http://jabber.org/protocol/muc'/>
    <feature var='http://jabber.org/protocol/muc#plus'/>
    <feature var='muc_passwordprotected'/>
    <feature var='muc_hidden'/>
    <feature var='muc_temporary'/>
    <feature var='muc_open'/>
    <feature var='muc_unmoderated'/>
    <feature var='muc_nonanonymous'/>
  </query>
</iq>
    

Notes: Because MUC+ is a superset of MUC and aims to allow older clients to work with a MUC+ service both 'http://jabber.org/protocol/muc' and 'http://jabber.org/protocol/muc#plus' MUST be returned. Since MUC is a superset of the old "Groupchat 1.0" protocol, a MUC room SHOULD NOT return a <feature var='gc-1.0'/> entry in a disco#info result. The room SHOULD return the materially-relevant features it supports, such as password protection and room moderation (these are listed fully in the feature var registry maintained by the Jabber Registrar; see also the registry submission in this document).

A chatroom MAY return more detailed information in its disco#info response using Service Discovery Extensions [9]. Such information might include a more verbose description of the room, the current room subject, and the current number of occupants in the room:

Example 7. Room Returns Extended Disco Info Results

<iq from='darkcave@macbeth.shakespeare.lit'
    id='disco3a'
    to='hag66@shakespeare.lit/pda'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    <identity
        category='conference'
        name='A Dark Cave'
        type='text'/>
    <feature var='http://jabber.org/protocol/muc'/>
    <feature var='http://jabber.org/protocol/muc#plus'/>
    <feature var='muc_passwordprotected'/>
    <feature var='muc_hidden'/>
    <feature var='muc_temporary'/>
    <feature var='muc_open'/>
    <feature var='muc_unmoderated'/>
    <feature var='muc_nonanonymous'/>
    <x xmlns='jabber:x:data' type='result'>
      <field var='FORM_TYPE' type='hidden'>
        <value>http://jabber.org/protocol/muc#roominfo</value>
      </field>
      <field var='muc#roominfo_description' label='Description'>
        <value>The place for all good witches!</value>
      </field>
      <field var='muc#roominfo_subject' label='Subject'>
        <value>Spells</value>
      </field>
      <field var='muc#roominfo_occupants' label='Number of occupants'>
        <value>3</value>
      </field>
      <field var='muc#roominfo_lang' label='Language of discussion'>
        <value>en</value>
      </field>
    </x>
  </query>
</iq>
    

Note: The foregoing extended service discovery fields for the 'http://jabber.org/protocol/muc#roominfo' FORM_TYPE may be supplemented in the future via the mechanisms described in the Field Standardization section of this document.

Finally, a user may also query a specific chat room for its associated items:

Example 8. User Queries for Items Associated with a Specific Chat Room

<iq from='hag66@shakespeare.lit/pda'
    id='disco4'
    to='darkcave@macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
    

An implementation MAY return a list of existing occupants if that information is publicly available, or return no list at all if this information is kept private.

Example 9. Room Returns Disco Item Results (Items are Public)

<iq from='darkcave@macbeth.shakespeare.lit'
    id='disco4'
    to='hag66@shakespeare.lit/pda'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#items'>
    <item jid='darkcave@macbeth.shakespeare.lit/firstwitch'/>
    <item jid='darkcave@macbeth.shakespeare.lit/secondwitch'/>
  </query>
</iq>
    

Note that these <item/> elements are in the disco#items namespace, not the muc namespace. This means that they cannot possess 'affiliation' or 'role' attributes, for example.

Example 10. Room Returns Empty Disco Item Results (Items are Private)

<iq from='darkcave@macbeth.shakespeare.lit'
    id='disco4'
    to='hag66@shakespeare.lit/pda'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
    

If an entity attempts to send a disco request to an address of the form <room@service/nick>, a compliant component SHOULD return the request to the entity and specify a <bad-request/> error condition.

6.2 Discovering Client Support for MUC

A Jabber user may want to discover if one of the user's contacts supports the Multi-User Chat protocol. This is done using Service Discovery.

Example 11. User Queries Contact regarding MUC Support

<iq from='hag66@shakespeare.lit/pda'
    id='disco5'
    to='wiccarocks@shakespeare.lit/laptop'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
    

The client SHOULD return its identity and the features it supports:

Example 12. Contact Returns Disco Info Results

<iq from='wiccarocks@shakespeare.lit/laptop'
    id='disco5'
    to='hag66@shakespeare.lit/pda'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    <identity
        category='client'
        type='pc'/>
    <feature var='http://jabber.org/protocol/muc'/>
  </query>
</iq>
    

A user may also query a contact regarding which rooms the contact is in. This is done by querying the contact's full JID (user@host/resource) while specifying the well-known Service Discovery node 'http://jabber.org/protocol/muc#rooms':

Example 13. User Queries Contact for Current Rooms

<iq from='hag66@shakespeare.lit/pda'
    id='rooms1'
    to='wiccarocks@shakespeare.lit/laptop'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#items'
         node='http://jabber.org/protocol/muc#rooms'/>
</iq>
    

Example 14. Contact Returns Room Query Results

<iq from='wiccarocks@shakespeare.lit/laptop'
    id='rooms1'
    to='hag66@shakespeare.lit/pda'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#items'
         node='http://jabber.org/protocol/muc#rooms'/>
    <item jid='darkcave@macbeth.shakespeare.lit'/>
    <item jid='characters@conference.shakespeare.lit'/>
  </query>
</iq>
    

Optionally, the contact MAY include its room nick as the value of the 'name' attribute:

    ...
    <item jid='darkcave@macbeth.shakespeare.lit'
          name='secondwitch'/>
    ...
    

6.3 Entering a Room

6.3.1 Groupchat 1.0 Protocol

In order to participate in the discussions held in a multi-user chat room, a Jabber user MUST first become an occupant by entering the room. In the old "groupchat 1.0" protocol, this is done by sending presence to room@service/nick, where "room" is the room ID, "service" is the hostname of the chat service, and "nick" is the user's desired nickname within the room:

Example 15. Jabber User Seeks to Enter a Room (Groupchat 1.0)

<presence
    from='hag66@shakespeare.lit/pda'
    to='darkcave@macbeth.shakespeare.lit/thirdwitch'/>
      

In this example, a user with a full JID of "hag66@shakespeare.lit/pda" has requested to enter the room "darkcave" on the "macbeth.shakespeare.lit" chat service with a room nickname of "thirdwitch".

If the user does not specify a room nickname, the service SHOULD return a <jid-malformed/> error:

Example 16. Jabber User Seeks to Enter a Room (Groupchat 1.0)

<presence
    from='darkcave@macbeth.shakespeare.lit'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <error code='400' type='modify'>
    <jid-malformed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</presence>
      

6.3.2 Basic MUC Protocol

Compliant multi-user chat services MUST accept the foregoing as a request to enter a room from any Jabber client that knows either the "groupchat 1.0" (GC) protocol or the multi-user chat (MUC) protocol; however, MUC-compliant clients SHOULD signal their ability to speak the MUC protocol by including in the initial presence stanza an empty <x/> element scoped by the 'http://jabber.org/protocol/muc' namespace (note the absence of the '#user' fragment):

Example 17. Jabber User Seeks to Enter a Room (Multi-User Chat)

<presence
    from='hag66@shakespeare.lit/pda'
    to='darkcave@macbeth.shakespeare.lit/thirdwitch'>
  <x xmlns='http://jabber.org/protocol/muc'/>
</presence>
      

6.3.3 Presence Broadcast

If the service is able to add the user to the room, it MUST send presence from all the existing occupants' room JIDs to the new occupant's full JID, including extended presence information about roles in an <x/> element scoped by the 'http://jabber.org/protocol/muc#user' namespace and containing an <item/> child with the 'role' attribute set to a value of "moderator", "participant", "visitor", or "none" and with the 'affiliation' attribute set to a value of "owner", "admin", "member", or "none" as appropriate:

Example 18. Service Sends Presence from Existing Occupants to New Occupant

<presence
    from='darkcave@macbeth.shakespeare.lit/firstwitch'
    to='hag66@shakespeare.lit/pda'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='owner' role='moderator'/>
  </x>
</presence>
<presence
    from='darkcave@macbeth.shakespeare.lit/secondwitch'
    to='hag66@shakespeare.lit/pda'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='admin' role='moderator'/>
  </x>
</presence>
      

In this example, the user from the previous example has entered the room, by which time two other people had already entered the room: a user with a room nickname of "firstwitch" (who is the room owner) and a user with a room nickname of "secondwitch" (who is a room admin).

The service MUST also send presence from the new occupant's room JID to the full JIDs of all the occupants (including the new occupant):

Example 19. Service Sends New Occupant's Presence to All Occupants

<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='crone1@shakespeare.lit/desktop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member' role='participant'/>
  </x>
</presence>
<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='wiccarocks@shakespeare.lit/laptop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member' role='participant'/>
  </x>
</presence>
<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='hag66@shakespeare.lit/pda'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member' role='participant'/>
  </x>
</presence>
      

In this example, initial room presence is being sent from the new occupant (thirdwitch) to all occupants, including the new occupant.

The order of the presence stanzas sent to the new occupant is important. The service MUST first send the complete list of the existing occupants to the new occupant and only then send the new occupant's own presence to the new occupant. This helps the client know when it has received the complete "room roster".

6.3.4 Default Roles

The following table summarizes the initial default roles that a service should set based on the user's affiliation (there is no role associated with the "outcast" affiliation, since such users are never allowed to enter the room).

Table 6: Initial Role Based on Affiliation

Room Type None Member Admin Owner
Moderated Visitor Participant Moderator Moderator
Unmoderated Participant Participant Moderator Moderator
Members-Only n/a Participant Moderator Moderator
Open Participant Participant Moderator Moderator

6.3.5 Non-Anonymous Rooms

If the room is non-anonymous, the service MUST send the new occupant's full JID to all occupants using extended presence information in an <x/> element scoped by the 'http://jabber.org/protocol/muc#user' namespace and containing an <item/> child with a 'jid' attribute specifying the occupant's full JID:

Example 20. Service Sends Full JID to All Occupants

<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='crone1@shakespeare.lit/desktop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='none'
          jid='hag66@shakespeare.lit/pda'
          role='participant'/>
  </x>
</presence>
.
.
.
      

If the user is entering a room that is non-anonymous (i.e., which informs all occupants of each occupant's full JID as shown above), the service SHOULD allow the user to enter the room but MAY warn the user that the room is not anonymous; this is done by sending a message of type "groupchat" to the new occupant containing an <x/> child with a <status/> element that has the 'code' attribute set to a value of "100":

Example 21. Service Warns New Occupant of Lack of Anonymity

<message
    from='darkcave@macbeth.shakespeare.lit'
    to='hag66@shakespeare.lit/pda'
    type='groupchat'>
  <body>This room is not anonymous.</body>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <status code='100'/>
  </x>
</message>
      

The inclusion of the status code assists clients in presenting their own notification messages (e.g., information appropriate to the user's locality).

6.3.6 Semi-Anonymous Rooms

If the room is semi-anonymous, the service MUST send the new occupant's full JID in the format shown above only to those occupants with a role of "moderator".

(Note: all subsequent examples include the 'jid' attribute for each <item/> element, even though this information is not sent to non-moderators in semi-anonymous rooms.)

6.3.7 Password-Protected Rooms

If the room requires a password and the user did not supply one, the service MUST deny access to the room and inform the user that they are unauthorized; this is done by returning a presence stanza of type "error" specifying a <not-authorized/> error:

Example 22. Service Denies Access Because No Password Provided

<presence
    from='darkcave@macbeth.shakespeare.lit'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <error code='401' type='auth'>
    <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</presence>
      

Passwords SHOULD be supplied with the presence stanza sent when entering the room, contained within an <x/> element scoped by the 'http://jabber.org/protocol/muc' namespace and containing a <password/> child. Passwords are to be sent as cleartext; no other authentication methods are supported at this time, and any such authentication or authorization methods shall be defined in a separate specification.

Example 23. User Provides Password On Entering a Room

<presence
    from='hag66@shakespeare.lit/pda'
    to='darkcave@macbeth.shakespeare.lit/thirdwitch'>
  <x xmlns='http://jabber.org/protocol/muc'>
    <password>cauldron</password>
  </x>
</presence>
      

6.3.8 Members-Only Rooms

If the room is members-only but the user's affiliation is not 'member', the service MUST deny access to the room and inform the user that they are not allowed to enter the room; this is done by returning a presence stanza of type "error" specifying a <registration-required/> error condition:

Example 24. Service Denies Access Because User Is Not a Member

<presence
    from='darkcave@macbeth.shakespeare.lit'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <error code='407' type='auth'>
    <registration-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</presence>
      

6.3.9 Banned Users

If the user has been banned from the room (i.e., has an affiliation of "outcast"), the service MUST deny access to the room and inform the user of the fact that he or she is banned; this is done by returning a presence stanza of type "error" specifying a <forbidden/> error condition:

Example 25. Service Denies Access Because User is Banned

<presence
    from='darkcave@macbeth.shakespeare.lit'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <error code='403' type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</presence>
      

6.3.10 Nickname Conflict

If the room already contains an occupant with the nickname desired by the user seeking to enter the room (or if the nickname is reserved by a member), the service MUST deny access to the room and inform the user of the conflict; this is done by returning a presence stanza of type "error" specifying a <conflict/> error condition:

Example 26. Service Denies Access Because of Nick Conflict

<presence
    from='darkcave@macbeth.shakespeare.lit'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <error code='409' type='cancel'>
    <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</presence>
      

6.3.11 Max Users

If the room has reached its maximum number of users, the service SHOULD deny access to the room and inform the user of the restriction; this is done by returning a presence stanza of type "error" specifying a <resource-constraint/> error condition:

Example 27. Service Informs User that Room Occupant Limit Has Been Reached

<presence
    from='darkcave@macbeth.shakespeare.lit'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <error code='500' type='wait'>
    <resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</presence>
      

Once the number of occupants goes below the maximum number, the service SHOULD go ahead and add the user to the room.

6.3.12 Discussion History

After sending initial presence as shown above, a room MAY send discussion history to the new occupant. Whether such history is sent, and how many messages comprise the history, shall be determined by the chat service implementation or specific deployment.

Example 28. Delivery of Discussion History

<message
    from='darkcave@macbeth.shakespeare.lit/firstwitch'
    to='hecate@shakespeare.lit/broom'
    type='groupchat'>
  <body>Thrice the brinded cat hath mew'd.</body>
  <x xmlns='jabber:x:delay'
     from='crone1@shakespeare.lit/desktop'
     stamp='20021013T23:58:37'/>
</message>

<message
    from='darkcave@macbeth.shakespeare.lit/secondwitch'
    to='hecate@shakespeare.lit/broom'
    type='groupchat'>
  <body>Thrice and once the hedge-pig whined.</body>
  <x xmlns='jabber:x:delay'
     from='wiccarocks@shakespeare.lit/laptop'
     stamp='20021013T23:58:43'/>
</message>

<message
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='hecate@shakespeare.lit/broom'
    type='groupchat'>
  <body>Harpier cries 'Tis time, 'tis time.</body>
  <x xmlns='jabber:x:delay'
     from='hag66@shakespeare.lit/pda'
     stamp='20021013T23:58:49'/>
</message>
      

Discussion history messages SHOULD be stamped with extended information in the 'jabber:x:delay' namespace (see Delayed Delivery [10]) to indicate that they are sent with delayed delivery. The 'from' attribute SHOULD be the JID of the original sender in non-anonymous rooms, but MUST NOT be in semi-anonymous rooms (the 'from' attribute SHOULD be set to the room JID in semi-anonymous rooms).

6.3.13 Managing Discussion History

A user MAY want to manage the amount of discussion history provided on entering a room (perhaps because the user is on a low-bandwidth connection or is using a small-footprint client). This MUST be accomplished by including a <history/> child in the initial presence stanza sent when joining the room. There are four allowable attributes for this element:

Table 7: History Management Attributes

Attribute Datatype Meaning
maxchars int Limit the total number of characters in the history to "X".
maxstanzas int Limit the total number of messages in the history to "X".
seconds int Send only the messages received in the last "X" seconds.
since dateTime Send only the messages received since the dateTime specified (which MUST conform to Jabber Date and Time Profiles [11]).

The service MUST send the smallest amount of traffic that meets any combination of the above criteria, taking into account service-level and room-level defaults. The service MUST send complete message stanzas only (i.e., it MUST not literally truncate the history at a certain number of characters, but MUST send the largest number of complete stanzas that results in a number of characters less than or equal to the 'maxchars' value specified). If the client wishes to receive no history, it MUST set the 'maxcharts' attribute to a value of "0" (zero).

The following examples illustrate the use of this protocol.

Example 29. User Requests Limit on Number of Messages in History

<presence
    from='hag66@shakespeare.lit/pda'
    to='darkcave@macbeth.shakespeare.lit/thirdwitch'>
  <x xmlns='http://jabber.org/protocol/muc'>
    <history maxstanzas='20'/>
  </x>
</presence>
      

Example 30. User Requests History in Last 3 Minutes

<presence
    from='hag66@shakespeare.lit/pda'
    to='darkcave@macbeth.shakespeare.lit/thirdwitch'>
  <x xmlns='http://jabber.org/protocol/muc'>
    <history seconds='180'/>
  </x>
</presence>
      

Example 31. User Requests All History Since the Beginning of the Unix Era

<presence
    from='hag66@shakespeare.lit/pda'
    to='darkcave@macbeth.shakespeare.lit/thirdwitch'>
  <x xmlns='http://jabber.org/protocol/muc'>
    <history since='1970-01-01T00:00Z'/>
  </x>
</presence>
      

Obviously the service SHOULD NOT return all messages sent in the room since the beginning of the Unix era, and SHOULD appropriately limit the amount of history sent to the user based on service or room defaults.

Example 32. User Requests No History

<presence
    from='hag66@shakespeare.lit/pda'
    to='darkcave@macbeth.shakespeare.lit/thirdwitch'>
  <x xmlns='http://jabber.org/protocol/muc'>
    <history maxchars='0'/>
  </x>
</presence>
      

6.3.14 Room Creation

If the room does not already exist when the user seeks to enter it, the service MAY be responsible for creating it; however, this is OPTIONAL, since an implementation or deployment MAY choose to restrict the privilege of creating rooms. See "Owner Use Cases" for details.

If a user attempts to enter a room that does not exist or to enter a room while it is "locked" (i.e., before the room creator provides an initial configuration and therefore before the room officially exists), the service MUST refuse entry and return a <item-not-found/> error to the user:

Example 33. Service Denies Access Because Room Does Not Exist

<presence
    from='darkcave@macbeth.shakespeare.lit'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <error code='404' type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</presence>
      

6.4 Exiting a Room

In order to exit a multi-user chat room, an occupant sends a presence stanza of type "unavailable" to the room@service/nick it is currently using in the room.

Example 34. Occupant Exits a Room

<presence
    from='hag66@shakespeare.lit/pda'
    to='darkcave@macbeth.shakespeare.lit/thirdwitch'
    type='unavailable'/>
    

The service MUST then send presence stanzas of type "unavailable" from the departing occupant's room JID to the full JIDs of the departing occupant and of the remaining occupants:

Example 35. Service Sends Presence Related to Departure of Occupant

<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='hag66@shakespeare.lit/pda'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member' role='none'/>
  </x>
</presence>
<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='crone1@shakespeare.lit/desktop'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member' role='none'/>
  </x>
</presence>
<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='wiccarocks@shakespeare.lit/laptop'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member' role='none'/>
  </x>
</presence>
    

Presence stanzas of type "unavailable" reflected by the room MUST contain extended presence information about roles and affiliations, and MAY also contain normal <show/> and <status/> information (this last enables occupants to provide custom exit messages if desired).

Normal presence stanza generation rules apply as defined in XMPP IM, so that if the user sends a general unavailable presence stanza, the user's server will broadcast that stanza to the room@service/nick to which the user's client has sent directed presence.

If the room is not persistent and this occupant is the last to exit, the service is responsible for destroying the room.

6.5 Changing Nickname

A common feature of multi-user chat rooms is the ability for an occupant to change his or her nickname within the room. In Jabber this is done by sending updated presence information to the room, specifically by sending presence to a new room JID in the same room (changing only the resource identifier in the room JID).

Example 36. Occupant Changes Nickname

<presence
    from='hag66@shakespeare.lit/pda'
    to='darkcave@macbeth.shakespeare.lit/oldhag'/>
    

The service then sends two presence packets to the full JID of each occupant (including the occupant who is changing his or her room nickname), one of type "unavailable" for the old nickname and one indicating availability for the new nickname. The unavailable presence MUST contain the new nickname and an appropriate status code (namely 303) as extended presence information in an <x/> element scoped by the 'http://jabber.org/protocol/muc#user' namespace so that Jabber clients are able to provide relevant hints to occupants regarding the nickname change if desired.

Example 37. Service Updates Nick

<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='crone1@shakespeare.lit/desktop'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member'
          jid='hag66@shakespeare.lit/pda'
          nick='oldhag'
          role='participant'/>
    <status code='303'/>
  </x>
</presence>
<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='wiccarocks@shakespeare.lit/laptop'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member'
          jid='hag66@shakespeare.lit/pda'
          nick='oldhag'
          role='participant'/>
    <status code='303'/>
  </x>
</presence>
<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='hag66@shakespeare.lit/pda'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member'
          jid='hag66@shakespeare.lit/pda'
          nick='oldhag'
          role='participant'/>
    <status code='303'/>
  </x>
</presence>

<presence
    from='darkcave@macbeth.shakespeare.lit/oldhag'
    to='crone1@shakespeare.lit/desktop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member'
          jid='hag66@shakespeare.lit/pda'
          role='participant'/>
  </x>
</presence>
<presence
    from='darkcave@macbeth.shakespeare.lit/oldhag'
    to='wiccarocks@shakespeare.lit/laptop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member'
          jid='hag66@shakespeare.lit/pda'
          role='participant'/>
  </x>
</presence>
<presence
    from='darkcave@macbeth.shakespeare.lit/oldhag'
    to='hag66@shakespeare.lit/pda'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member'
          jid='hag66@shakespeare.lit/pda'
          role='participant'/>
  </x>
</presence>
    

If the user attempts to change his or her room nickname to a room nickname that is already in use by another occupant (or that is reserved by someone affiliated with the room, e.g., a member or owner), the service MUST deny the nickname change request and inform the user of the conflict; this is done by returning a presence stanza of type "error" specifying a <conflict/> error condition:

Example 38. Service Denies Nickname Change Because of Nick Conflict

<presence
    from='darkcave@macbeth.shakespeare.lit'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <error code='409' type='cancel'>
    <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</presence>
    

6.6 Changing Availability Status

In multi-user chat systems such as IRC, one common use for changing one's room nickname is to indicate a change in one's availability (e.g., changing one's room nickname to "thirdwitch|away"). In Jabber, availability is of course noted by a change in presence (specifically the <show/> and <status/> elements), which can provide important context within a chatroom. An occupant changes availability status within the room by sending the updated presence to room@service/nick.

Example 39. Occupant Changes Availability Status

<presence
    from='wiccarocks@shakespeare.lit/laptop'
    to='darkcave@macbeth.shakespeare.lit/oldhag'>
  <show>xa</show>
  <status>gone where the goblins go</status>
</presence>
    

The service then sends a presence packet from the occupant changing his or her presence to the full JID of each occupant, including extended presence information about the occupant's role and full JID to those with privileges to view such information:

Example 40. Service Passes Along Changed Presence to All Occupants

<presence
    from='darkcave@macbeth.shakespeare.lit/secondwitch'
    to='crone1@shakespeare.lit/desktop'>
  <show>xa</show>
  <status>gone where the goblins go</status>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='admin'
          jid='wiccarocks@shakespeare.lit/laptop'
          role='moderator'/>
  </x>
</presence>
.
.
.
    

6.7 Inviting Another User to a Room

It can be useful to invite another user to a room in which one is an occupant. Several different mechanisms have been suggested in the past to do this. The protocol most commonly used is for the inviting occupant to send a message directly to the invitee, containing extended content in the jabber:x:conference namespace. The server (not the chat service) adds a 'from' address to the invite message, which is delivered like any other message. This undocumented protocol, which is not part of "groupchat 1.0", is as follows:

Example 41. Occupant Sends an Invitation (Existing Protocol)

<message
    from='crone1@shakespeare.lit/desktop'
    to='hecate@shakespeare.lit'>
  <body>You have been invited to darkcave@macbeth.</body>
    <x jid='room@service' xmlns='jabber:x:conference'/>
</message>
    

While the current protocol meets the needs of existing implementations, it could not work within the context of a members-only room, since the service needs to keep track of who is registered as a member. Because we would like to support members-only rooms, it seems desirable for an occupant to send the invitation to the room itself and have the room keep track of the invitations (if the room is members-only) or simply forward the invitation to the invitee.

Therefore the old undocumented protocol SHOULD be officially discouraged (it cannot be deprecated since it was never approved) and a MUC-compliant client MUST instead send XML of the following form to the room itself (the reason is OPTIONAL and the message MUST NOT possess a 'type' attribute; the service MAY ignore or reject invites that possess a 'type' attribute):

Example 42. Occupant Sends an Invitation by Way of Room (Multi-User Chat)

<message
    from='crone1@shakespeare.lit/desktop'
    to='darkcave@macbeth.shakespeare.lit'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <invite to='hecate@shakespeare.lit'>
      <reason>
        Hey Hecate, this is the place for all good witches!
      </reason>
    </invite>
  </x>
</message>
    

The occupant may also invite more than one person at a time:

Example 43. Occupant Sends an Invitation by Way of Room (Multi-User Chat)

<message
    from='crone1@shakespeare.lit/desktop'
    to='darkcave@macbeth.shakespeare.lit'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <invite to='hecate@shakespeare.lit'>
      <reason>
        Hey Hecate, this is the place for all good witches!
      </reason>
    </invite>
    <invite to='hag66@shakespeare.lit'>
      <reason>
        Hey Hag66, this is the place for all good witches!
      </reason>
    </invite>
  </x>
</message>
    

The room itself MUST then add a 'from' address to the <invite/> element equal to the bare JID (or, optionally, the room JID) of the inviter and send the invitation to the invitee captured in the 'to' address (the service SHOULD include the jabber:x:conference information for backward compatibility and MAY if desired include a message body explaining the invitation or containing the reason; in addition, the room SHOULD add the password if the room is password-protected). If the invitee included multiple invites, the room MUST send an invitation to each one seperately:

Example 44. Room Sends Invitation to Invitee on Behalf of Inviter

<message
    from='darkcave@macbeth.shakespeare.lit'
    to='hecate@shakespeare.lit'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <invite from='crone1@shakespeare.lit'>
      <reason>
        Hey Hecate, this is the place for all good witches!
      </reason>
    </invite>
    <password>cauldron</password>
  </x>
  <x jid='room@service' xmlns='jabber:x:conference'>
    Hey Hecate, this is the place for all good witches!
  </x>
</message>
    

If the room is members-only, the service SHOULD also set the invitee's affiliation to 'member'. (Note that invitation privileges in members-only rooms SHOULD be restricted to room admins; if a member without privileges to change an affiliation to 'member' attempts to invite another user, the service SHOULD return a <forbidden/> error to the occupant; for details, see the Changing Affiliations section.

If the inviter supplies a non-existent JID, the room SHOULD return a <item-not-found/> error to the inviter.

The invitee MAY choose to formally decline (as opposed to ignore) the invitation; and this is something that the sender may want to be informed about. In order to decline the invitation, the invitee MUST send a message of the following form to the room itself:

Example 45. Invitee Declines Invitation

<message
    from='hecate@shakespeare.lit/broom'
    to='darkcave@macbeth.shakespeare.lit'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <decline to='crone1@shakespeare.lit'>
      <reason>
        Sorry, I'm too busy right now.
      </reason>
    </decline>
  </x>
</message>
    

Example 46. Room Informs Inviter that Invitation Was Declined

<message
    from='darkcave@macbeth.shakespeare.lit'
    to='crone1@shakespeare.lit/desktop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <decline from='hecate@shakespeare.lit'>
      <reason>
        Sorry, I'm too busy right now.
      </reason>
    </decline>
  </x>
</message>
    

It may be wondered why the invitee does not send the decline message directly to the inviter. The main reason is that certain implementations MAY choose to base invitations on room JIDs rather than bare JIDs (so that, for example, an occupant could invite someone from one room to another without knowing that person's bare JID), in which case the service MUST handle both the invites and declines.

6.8 Requesting and Reserving an Unique Room Name

A MUC+ service MUST allow entities to request and reserve unique rooms. This facilitates converting a one-to-one chat into a multi-user chat. It may also be handy for other things as well.

To request an unique room, a client sends an <iq/> with its <query/> scoped by the 'http://jabber.org/protocol/muc' namespace that includes an <unique-room/> element. The returned <iq/> is practically the same except that the <unique-room/> element includes the room's name and has an 'expires' attribute set to the time that the reservation expires which MUST follow Jabber Date and Time Profiles [12]:

Example 47. Requests an Unique Room

<iq to="macbeth.shakespeare.lit"
    from="crone1@shakespeare.lit/desktop"
    type="get"
    id="unique">
  <query xmlns="http://jabber.org/protocol/muc">
    <unique-room/>
  </query>
</iq>

<iq to="crone1@shakespeare.lit/desktop"
    from="crone1@shakespeare.lit/desktop"
    type="result"
    id="unique">
  <query xmlns="http://jabber.org/protocol/muc">
    <unique-room expires="2005-01-01T12:00Z">unique_1</unique-room>
  </query>
</iq>
    

It is not specified in this JEP the form of the room name, except that it MUST NOT be an existing room. It could be a UUID, hash of the requestor's JID, or something else. The expiration time is RECOMMENDED to be no more than five minutes, but this SHOULD be configurable.

The service MAY also limit the number of unique rooms a single entity can reserve at any one time. In such a case the service MUST return a <resource-constraint/> error:

Example 48. Error on Reserving to Many Unique Rooms

<iq to="crone1@shakespeare.lit/desktop"
    from="crone1@shakespeare.lit/desktop"
    type="error"
    id="unique">
  <error code='500' type='cancel'>
    <resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If someone other than the requestor tries to create the reserved room, the service MUST deny the request with a <not-allowed/> error:

Example 49. Entity Attempts To Create a Room That's Reserved

<presence to="unique_1@macbeth.shakespeare.lit/hag66"
          from="hag66@shakespeare.lit">
  <x xmlns="http://jabber.org/protocol/muc"/>
</presence>

<presence from="unique_1@macbeth.shakespeare.lit"
          to="hag66@shakespeare.lit"
	  type="error">
  <error code="405" type="cancel">
     <not-allowed xmlns="urn:ietf:params:xml:ns:xmpp-stanzas/>
  </error>
</presence>
    

6.9 Converting a One-to-One Chat Into a Conference

Sometimes it is desirable to convert a one-to-one chat into a multi-user conference. This can be done by using the <continue/> child element. The process flow is shown in the following examples.

First, two users begin a one-to-one chat.

Example 50. A One-to-One Chat

<message
    from='crone1@shakespeare.lit/desktop'
    to='wiccarocks@shakespeare.lit/laptop'
    type='chat'>
  <body>Thrice the brinded cat hath mew'd.</body>
</message>

<message
    from='wiccarocks@shakespeare.lit/laptop'
    to='crone1@shakespeare.lit/desktop'
    type='chat'>
  <body>Thrice and once the hedge-pig whined.</body>
</message>
    

Now the first person decides to include a third person in the discussion, so she (or, more precisely, her client) does the following:

  1. Requests an unique room that will be reserved (the previous use case)
  2. Creates the new room by including the <continue/> child element in the presence
  3. Optionally sends history of the one-to-one chat to the room
  4. Sends an invitation to the second person, third person, and whoever else including a <continue/> flag.

Example 51. Continuing the Discussion I: User Creates Room

<presence
    from='crone1@shakespeare.lit/desktop'
    to='unique_1@macbeth.shakespeare.lit/firstwitch'>
  <x xmlns='http://jabber.org/protocol/muc'>
    <continue/>
  </x>
</presence>

<presence
    from='unique_1@macbeth.shakespeare.lit/firstwitch'
    to='crone1@shakespeare.lit/desktop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='owner' role='moderator'/>
  </x>
</presence>
    

The continue element signals to the service that the owner wishes to continue an existing one-to-one chat.  This allows the service to provision the room accordingly.  The service MAY have a different default configuration for continued conversations than other newly created rooms.  The service SHOULD immediately unlock the room, apply the instant room defaults, and not require any configuration.  It is RECOMMENDED that the service configure the room as non-persistent, non-anonymous, private, and members only.

Once the room is created, the first person MAY send the one-to-one chat to the room:

Example 52. Continuing the Discussion II: Owner Sends History to Room

<message
    from='crone1@shakespeare.lit/desktop'
    to='unique_1@macbeth.shakespeare.lit'
    type='groupchat'>
  <body>Thrice the brinded cat hath mew'd.</body>
  <x xmlns='jabber:x:delay'
     from='crone1@shakespeare.lit/desktop'
     stamp='20040929T01:54:37'/>
</message>

<message
    from='crone1@shakespeare.lit/desktop'
    to='unique_1@macbeth.shakespeare.lit'
    type='groupchat'>
  <body>Thrice and once the hedge-pig whined.</body>
  <x xmlns='jabber:x:delay'
     from='wiccarocks@shakespeare.lit/laptop'
     stamp='20040929T01:55:21'/>
</message>
    

Note: Use of the Delayed Delivery protocol enables the room creator to specify the datetime of each message from the one-to-one chat history (via the 'stamp' attribute), as well as JID of the original sender of each message (via the 'from' attribute). The room creator SHOULD send the complete one-to-one chat history before inviting additional users to the room, and SHOULD also send as history any messages appearing in the one-to-one chat interface after joining the room and before the second person joins the room; if the one-to-one history is especially large, the sending client may want to send the history over a few seconds rather than all at once (to avoid triggering rate limits). The service SHOULD NOT add its own delay elements (as described in the under Discussion History) to prior chat history messages received from the room owner.

The service MUST NOT accept messages of type groupchat containing delayed delivery elements from any occupant other than the room owner, or in any rooms which were not created with the <continue/> element, or after any users other than the initial owner have joined the room. The service MUST respond with a <bad-request/> stanza error to such messages and MUST NOT broadcast the message to room occupants.

Once the discussion history has been set, the first occupant can then invite others:

Example 53. Continuing the Discussion III: Owner Sends Invitations, Including Continue Flag

<message
    from='crone1@shakespeare.lit/desktop'
    to='unique_1@macbeth.shakespeare.lit'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <invite to='wiccarocks@shakespeare.lit/laptop'>
      <reason>This coven needs both wiccarocks and hag66.</reason>
    </invite>
    <invite to='hag66@shakespeare.lit'>
      <reason>This coven needs both wiccarocks and hag66.</reason>
    </invite>
    <continue/>
  </x>
</message>
    

The invitations are delivered to the invitees:

Example 54. Invitations Delivered

<message
    from='unique_1@macbeth.shakespeare.lit'>
    to='wiccarocks@shakespeare.lit/laptop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <invite from='crone1@shakespeare.lit'>
      <reason>This coven needs both wiccarocks and hag66.</reason>
      <continue/>
    </invite>
  </x>
</message>

<message
    from='unique_1@macbeth.shakespeare.lit'>
    to='hag66@shakespeare.lit'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <invite from='crone1@shakespeare.lit'>
      <reason>This coven needs both wiccarocks and hag66.</reason>
      <continue/>
    </invite>
  </x>
</message>
    

Note: Since the inviter's client knows the full JID of the person with whom the inviter was having a one-to-one chat, it SHOULD include the full JID (rather than the bare JID) in the invitation.

When the client being used by <wiccarocks@shakespeare.lit/laptop> receives the invitation, it SHOULD (subject to user preferences) auto-join the room and seamlessly convert the existing one-to-one chat window into a multi-user conferencing window:

Example 55. Invitee Accepts Invitation, Joins Room, and Receives Presence and History

<presence
    from='wiccarocks@shakespeare.lit/laptop'
    to='unique_1@macbeth.shakespeare.lit/secondwitch'>
  <x xmlns='http://jabber.org/protocol/muc'/>
</presence>

<presence
    from='unique_1@macbeth.shakespeare.lit/firstwitch'
    to='wiccarocks@shakespeare.lit/laptop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='owner' role='moderator'/>
  </x>
</presence>

<presence
    from='unique_1@macbeth.shakespeare.lit/secondwitch'
    to='wiccarocks@shakespeare.lit/laptop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member' role='participant'/>
  </x>
</presence>

<message
    from='unique_1@macbeth.shakespeare.lit'
    to='wiccarocks@shakespeare.lit/laptop'
    type='groupchat'>
  <body>Thrice the brinded cat hath mew'd.</body>
  <x xmlns='jabber:x:delay'
     from='crone1@shakespeare.lit/desktop'
     stamp='20040929T01:54:37'/>
</message>

<message
    from='unique_1@macbeth.shakespeare.lit'
    to='wiccarocks@shakespeare.lit/laptop'
    type='groupchat'>
  <body>Thrice and once the hedge-pig whined.</body>
  <x xmlns='jabber:x:delay'
     from='wiccarocks@shakespeare.lit/laptop'
     stamp='20040929T01:55:21'/>
</message>
    

Note: The fact that the messages come from the room itself rather than room@service/nick is a clue to the receiving client that these messages are prior chat history, since any message from a room occupant will have a 'from' address equal to the sender's room JID.

6.10 Modifying the Room Subject

A common feature of multi-user chat rooms is the ability to change the subject within the room. As a default, only users with a role of "moderator" SHOULD be allowed to change the subject in a room (although this SHOULD be configurable, with the result a mere participant or even visitor may be allowed to change the subject if desired). The subject is changed by sending a message of type "groupchat" to the room@service, containing no body but a <subject/> that specifies the new subject:

Example 56. Moderator Changes Subject

<message
    from='wiccarocks@shakespeare.lit/laptop'
    to='darkcave@macbeth.shakespeare.lit'
    type='groupchat'>
  <subject>Fire Burn and Cauldron Bubble!</subject>
</message>
    

If a compliant service receives such a message, it MUST reflect the message to all other occupants with a 'from' address equal to the room JID that corresponds to the sender of the subject change:

Example 57. Service Informs All Occupants of Subject Change

<message
    from='darkcave@macbeth.shakespeare.lit/secondwitch'
    to='crone1@shakespeare.lit/desktop'
    type='groupchat'>
  <subject>Fire Burn and Cauldron Bubble!</subject>
</message>
.
.
.
    

In addition, the room SHOULD include the last subject change in the discussion history sent when a new occupant joins the room.

A compliant client that receives such a message MAY choose to display an in-room message; the body of such in-room messages SHOULD NOT be generated by the sending client or the service, so as to ensure correct localization (however, the sending client or service MAY generate the body if desired). The in-room message could be something like the following:

* secondwitch has changed the subject to: Fire Burn and Cauldron Bubble!
    

If someone without appropriate privileges attempts to change the room subject, the service MUST return a message of type "error" specifying a <forbidden/> error condition:

Example 58. Service Returns Error Related to Unauthorized Subject Change

<message
    from='darkcave@macbeth.shakespeare.lit'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <subject>Fire Burn and Cauldron Bubble!</subject>
  <error code='403' type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</message>
    

6.11 Sending a Private Message

Since each occupant has a unique room JID, an occupant MAY send a "private message" to a selected occupant via the service by sending a message to the occupant's room JID. The message type SHOULD be "chat" and MUST NOT be "groupchat", but MAY be left unspecified (i.e., a normal message). This privilege SHOULD be allowed to any occupant (even a visitor in a moderated room).

Example 59. Occupant Sends Private Message

<message
    from='wiccarocks@shakespeare.lit/laptop'
    to='darkcave@macbeth.shakespeare.lit/firstwitch'
    type='chat'>
  <body>I'll give thee a wind.</body>
</message>
    

The service is responsible for changing the 'from' address to the sender's room JID and delivering the message to the intended recipient's full JID.

Example 60. Recipient Receives the Private Message

<message
    from='darkcave@macbeth.shakespeare.lit/secondwitch'
    to='crone1@shakespeare.lit/desktop'
    type='chat'>
  <body>I'll give thee a wind.</body>
</message>
    

If the sender attempts to send a private message of type "groupchat" to a particular occupant, the service MUST refuse to deliver the message and return a <bad-request/> error to the sender:

Example 61. Occupant Attempts to Send a Message of Type "Groupchat" to a Particular Occupant

<message
    from='wiccarocks@shakespeare.lit/laptop'
    to='darkcave@macbeth.shakespeare.lit/firstwitch'
    type='groupchat'>
  <body>I'll give thee a wind.</body>
</message>

<message
    from='darkcave@macbeth.shakespeare.lit'
    to='wiccarocks@shakespeare.lit/laptop'
    type='error'>
  <body>I'll give thee a wind.</body>
  <error code='400' type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</message>
    

If the sender attempts to send a private message to a room JID that does not exist, the service MUST return a <item-not-found/> error to the sender.

If the sender is not an occupant of the room in which the intended recipient is visiting, the service MUST return a <not-acceptable/> error to the sender.

6.12 Sending a Message to All Occupants

An occupant sends a message to all other occupants in the room by sending a message of type "groupchat" to the room itself (a service MAY ignore or reject messages that do not have a type of "groupchat"). In a moderated room, this privilege is restricted to occupants with a role of participant or higher. In an unmoderated room, any occupant sends a message to all other occupants by directing the message to the room itself and setting the 'type' attribute to a value of "groupchat".

Example 62. Occupant Sends a Message to All Occupants

<message
    from='hag66@shakespeare.lit/pda'
    to='darkcave@macbeth.shakespeare.lit'
    type='groupchat'>
  <body>Harpier cries: 'tis time, 'tis time.</body>
</message>
    

If the sender has voice in the room (this is the default except in moderated rooms), the service MUST change the 'from' attribute to the sender's room JID and reflect the message out to the full JID of each occupant.

Example 63. Service Reflects Message to All Occupants

<message
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='crone1@shakespeare.lit/desktop'
    type='groupchat'>
  <body>Harpier cries: 'tis time, 'tis time.</body>
</message>
<message
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='wiccarocks@shakespeare.lit/laptop'
    type='groupchat'>
  <body>Harpier cries: 'tis time, 'tis time.</body>
</message>
<message
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='hag66@shakespeare.lit/pda'
    type='groupchat'>
  <body>Harpier cries: 'tis time, 'tis time.</body>
</message>
    

If the sender is a visitor (i.e., does not have voice in a moderated room), the service MAY return a <forbidden/> error to the sender and MUST NOT reflect the message to all occupants. If the sender is not an occupant of the room, the service SHOULD return a <not-acceptable/> error to the sender and SHOULD NOT reflect the message to all occupants; however, an implementation MAY allow users with certain privileges (e.g., a room owner, room admin, or service-level admin) to send messages to the room even if that user is not an occupant.

6.13 Registering with a Room

An implementation MAY allow an unaffiliated user (in a moderated room, probably a participant) to register with a room and thus become a member of the room (conversely, an implementation MAY restrict this privilege and allow only room admins to add new members). If allowed, this functionality SHOULD be implemented by enabling a user to send a request for registration requirements to the room in the 'jabber:iq:register' namespace as described in In-Band Registration [13]:

Example 64. User Requests Registration Requirements

<iq from='hag66@shakespeare.lit/pda'
    id='reg1'
    to='darkcave@macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='jabber:iq:register'/>
</iq>
    

If the user requesting registration requirements is not allowed to register with the room (e.g., because that privilege has been restricted), the room MUST return a <not-allowed/> error to the user. If the user is already registered, the room MUST reply with an IQ stanza of type "result" that contains an empty <register/> element as described in JEP-0077. If the room does not exist, the service MUST return a <item-not-found/> error.

Otherwise, the room MUST then return a form to the user in the 'jabber:x:data' namespace. The specific information required to register is not specified in this JEP and MAY vary by implementation or deployment. The following can be taken as a fairly typical example:

Example 65. Service Returns Registration Form

<iq from='darkcave@macbeth.shakespeare.lit'
    id='reg1'
    to='hag66@shakespeare.lit/pda'
    type='result'>
  <query xmlns='jabber:iq:register'>
    <instructions>
      To register on the web, visit http://shakespeare.lit/
    </instructions>
    <x xmlns='jabber:x:data' type='form'>
      <title>Dark Cave Registration</title>
      <instructions>
        Please provide the following information
        to register with this room.
      </instructions>
      <field
          type='hidden'
          var='FORM_TYPE'>
        <value>http://jabber.org/protocol/muc#register</value>
      </field>
      <field
          label='First Name'
          type='text-single'
          var='muc#register_first'>
        <required/>
      </field>
      <field
          label='Last Name'
          type='text-single'
          var='muc#register_last'>
        <required/>
      </field>
      <field
          label='Desired Nickname'
          type='text-single'
          var='muc#register_roomnick'>
        <required/>
      </field>
      <field
          label='Your URL'
          type='text-single'
          var='muc#register_url'/>
      <field
          label='Email Address'
          type='text-single'
          var='muc#register_email'/>
      <field
          label='FAQ Entry'
          type='text-multi'
          var='muc#register_faqentry'/>
    </x>
  </query>
</iq>
    

The user SHOULD then submit the form:

Example 66. User Submits Registration Form

<iq from='hag66@shakespeare.lit/pda'
    id='reg2'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='jabber:iq:register'>
    <x xmlns='jabber:x:data' type='submit'>
      <field var='FORM_TYPE'>
        <value>http://jabber.org/protocol/muc#register</value>
      </field>
      <field var='muc#register_first'>
        <value>Brunhilde</value>
      </field>
      <field var='muc#register_last'>
        <value>Entwhistle-Throckmorton</value>
      </field>
      <field var='muc#register_roomnick'>
        <value>thirdwitch</value>
      </field>
      <field var='muc#register_url'>
        <value>http://witchesonline/~hag66/</value>
      </field>
      <field var='muc#register_email'>
        <value>hag66@witchesonline</value>
      </field>
      <field var='muc#register_faqentry'>
        <value>Just another witch.</value>
      </field>
    </x>
  </query>
</iq>
    

If the desired room nickname is already reserved for that room, the room MUST return a <conflict/> error to the user:

Example 67. Room Returns Conflict Error to User

<iq from='darkcave@macbeth.shakespeare.lit'
    id='reg2'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <error code='409' type='cancel'>
    <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the room or service does not support registration, it MUST return a <service-unavailable/> error to the user:

Example 68. Room Returns Service Unavailable Error to User

<iq from='darkcave@macbeth.shakespeare.lit'
    id='reg2'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <error code='503' type='cancel'>
    <service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

If the user did not include a valid data form does, the room MUST return a <bad-request/> error to the user:

Example 69. Room Returns Service Bad Request Error to User

<iq from='darkcave@macbeth.shakespeare.lit'
    id='reg2'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <error code='400' type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

Otherwise, the room MUST inform the user of successful registration:

Example 70. Room Informs User of Successful Registration

<iq from='darkcave@macbeth.shakespeare.lit'
    id='reg2'
    to='hag66@shakespeare.lit/pda'
    type='result'/>
    

After the user successfully submits the form, the service MAY request that the submission be approved by a room admin/owner (see Approving Registration Requests) or MAY immediately change the user's affiliation from "none" to "member". If the service changes the user's affiliation and the user is in the room, it MUST send updated presence from this individual to all occupants, indicating the change in affiliation by including an <x/> element scoped by the 'http://jabber.org/protocol/muc#user' namespace and containing an <item/> child with the 'affiliation' attribute set to a value of "member".

Example 71. Service Sends Notice of Membership to All Occupants

<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='crone1@shakespeare.lit/desktop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='member'
          jid='hag66@shakespeare.lit/pda'
          role='participant'/>
  </x>
</presence>
.
.
.
    

If a user has registered with a room, the room MAY choose to restrict the user to use of the registered nickname only in that room. If it does so, it SHOULD return a "Not Acceptable" (406) error to the user if the user attempts to join the room with a room nick other than the user's registered room nick.

6.14 Discovering Reserved Room Nickname

A user MAY have a reserved room nickname, for example through explicit room registration or database integration. In such cases it may be desirable for the user to discover the reserved nickname before attempting to enter the room (e.g., because the user has forgotten his or her reserved nickname). This is done by sending a Service Discovery information request to the room JID while specifying a Service Discovery node of "x-roomuser-item".

Example 72. User Requests Reserved Nickname

<iq from='hag66@shakespeare.lit/pda'
    id='getnick1'
    to='darkcave@macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#info'
         node='x-roomuser-item'/>
</iq>
    

It is OPTIONAL for a multi-user chat service to support the foregoing service discovery node. If it does and the user has a registered nickname, it MUST return the nickname to the user as value of the 'name' attribute of a Service Discovery <identity/> element (for which the category/type SHOULD be "conference/member"):

Example 73. Room Returns Nickname

<iq from='darkcave@macbeth.shakespeare.lit'
    id='getnick1'
    to='hag66@shakespeare.lit/pda'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#info'
         node='x-roomuser-item'>
    <identity
        category='conference'
        name='thirdwitch'
        type='text'/>
  </query>
</iq>
    

If the user does not have a registered nickname, the room MUST return a service discovery <query/> element that is empty (in accordance with JEP-0030).

If the room or service does not support the foregoing service discovery node, it MUST return a "Feature Not Implemented" (502) error to the user.

Even if a user has registered one room nickname, the service SHOULD allow the user to specify a different nickname on entering the room (e.g., in order to join from different client resources), although the service MAY choose to "lock down" nicknames and therefore deny entry to the user, including a "Not Acceptable" (406) error. The service MUST NOT return an error to the user if his or her client performs the foregoing request after having already joined the room.

If another user attempts to join the room with a nickname reserved by the first user, the service MUST deny entry to the second user and return a <conflict/> error.

7. Changing Roles