JEP-0045: Multi-User Chat

This JEP defines a robust protocol for XMPP-based text conferencing.


NOTICE: The protocol defined herein is a Draft Standard of the Jabber Software Foundation. Implementations are encouraged and the protocol is appropriate for deployment in production systems, but some changes to the protocol are possible before it becomes a Final Standard.


JEP Information

Status: Draft
Type: Standards Track
Number: 0045
Version: 1.16
Last Updated: 2004-06-30
JIG: Standards JIG
Approving Body: Jabber Council
Dependencies: XMPP Core, XMPP IM, JEP-0004, JEP-0030, JEP-0068, JEP-0082
Supersedes: None
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

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 and XMPP IM 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. Discussion History
6.3.12. Managing Discussion History
6.3.13. 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. Occupant Modification of the Room Subject
6.9. Sending a Private Message
6.10. Sending a Message to All Occupants
6.11. Registering with a Room
6.12. Discovering Reserved Room Nickname
7. Moderator Use Cases
7.1. Modifying the Room Subject
7.2. Kicking a Visitor or Participant from a Room
7.3. Granting Voice to a Visitor
7.4. Revoking Voice from a Participant
7.5. Modifying the Voice List
8. Admin Use Cases
8.1. Banning a User
8.2. Modifying the Ban List
8.3. Granting Membership
8.4. Revoking Membership
8.5. Modifying the Member List
8.6. Granting Moderator Privileges
8.7. Revoking Moderator Privileges
8.8. Modifying the Moderator List
9. Owner Use Cases
9.1. Creating a Room
9.2. Subsequent Room Configuration
9.3. Granting Ownership Privileges
9.4. Revoking Ownership Privileges
9.5. Modifying the Owner List
9.6. Granting Administrative Privileges
9.7. Revoking Administrative Privileges
9.8. Modifying the Admin List
9.9. Destroying a Room
10. Error and Status Codes
11. Security Considerations
12. IANA Considerations
13. Jabber Registrar Considerations
13.1. Protocol Namespaces
13.2. Service Discovery Category/Type
13.3. Service Discovery Features
13.4. Field Standardization
13.4.1. muc#user FORM_TYPE
13.4.2. muc#owner FORM_TYPE
13.4.3. muc#roominfo FORM_TYPE
14. Business Rules
14.1. Room JIDs
14.2. Message
14.3. Presence
14.4. IQ
15. Implementation Notes
15.1. Services
15.2. Clients
15.2.1. IRC Command Mapping
16. XML Schemas
16.1. http://jabber.org/protocol/muc
16.2. http://jabber.org/protocol/muc#user
16.3. http://jabber.org/protocol/muc#admin
16.4. http://jabber.org/protocol/muc#owner
17. Acknowledgements
Notes
Revision History


1. Introduction

It has long been recognized that the Jabber community needs a more robust protocol for text-based conferencing. This JEP defines extensions that enable Jabber systems to offer a much wider range of functionality, while still enabling older Jabber clients to access the minimal feature-set provided by the existing "groupchat 1.0" protocol. The extensions are implemented using protocol elements that fall into the 'http://jabber.org/protocol/muc' namespace and associated functionality areas (denoted by #owner, #admin, and #user fragments on the main namespace URI where appropriate).

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 [1]). This JEP explicitly does not address the following: relationships between rooms (e.g., hierarchies of rooms); management of multi-user chat services (e.g., managing permissions across an entire service or registering a global room nickname); moderation of individual messages; security and encryption at the level of a room or service; advanced features such as attaching files to a room, integrating whiteboards, and interfacing with audio chat services; or interaction between Jabber and foreign chat systems (e.g., gateways to IRC or to legacy IM systems). 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, and to manage the voice list
  8. enabling admins to grant and revoke moderator privileges, and to manage the moderator list
  9. enabling admins to ban users from the room, and to manage the ban list
  10. enabling admins to grant and revoke membership privileges, and to manage the member list for a members-only room
  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, and to manage the admin list
  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 [2] 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 this JEP.

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 through searching, browsing, etc.; antonym: Public Room.

Members-Only Room -- a room that a user cannot enter without being on the member list; 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 without being on the member list; 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 through searching, browsing, etc.); 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 can 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 can 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
Grant Voice No No No Yes
Revoke Voice No No No Yes***

* Default; configuration settings MAY further restrict this privilege.

** An implementation MAY grant voice by default to visitors 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 No Enter moderated room Enter unmoderated room Admin grants moderator privileges
Visitor Exit room or be kicked by a moderator No Moderator grants voice Admin grants moderator privileges
Participant Exit room or be kicked by a moderator Moderator revokes voice No Admin grants moderator privileges
Moderator Exit room n/a * Admin revokes moderator privileges ** No

* A moderator cannot be directly changed to a role of visitor; he or she MUST first be changed to a role of participant and then have voice revoked.

** 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 can 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
Edit Member List No No No Yes Yes
Edit Moderator List No No No Yes** Yes**
Edit Admin List No No No No Yes
Edit Owner List 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 No Admin or owner removes ban n/a n/a n/a
None Admin or owner applies ban No Admin adds user to member list, or user registers as member (if allowed) Owner adds user to admin list Owner adds user to owner list
Member Admin or owner applies ban Admin or owner removes from member list No Owner adds user to admin list Owner adds user to owner list
Admin n/a n/a Owner removes user from admin list No Owner adds user to owner list
Owner n/a n/a n/a Owner removes user from owner list No

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 [3].

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'/>
  </query>
</iq>
    

Note: because 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='muc_passwordprotected'/>
    <feature var='muc_hidden'/>
    <feature var='muc_temporary'/>
    <feature var='muc_open'/>
    <feature var='muc_unmoderated'/>
    <feature var='muc_nonanonymous'/>
  </query>
</iq>
    

Note: because 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 [4]. 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='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 while specifying a node of '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 roomnick 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 mesage 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 is not on the member list, 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 on Member List

<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 user on the member list), 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 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 27. 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 [5]) 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.12 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 can 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 [6]).

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 28. 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 29. 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 30. 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 31. 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.13 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 "Not Found" error to the user:

Example 32. 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 33. 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 34. 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 35. 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 36. 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 37. 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 38. 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 39. 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 40. 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 41. 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 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):

Example 42. 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 MAY also add the invitee to the member list. (Note that invitation privileges in members-only rooms SHOULD be restricted to room admins; if a member without privileges to edit the member list attempts to invite another user, the service SHOULD return a "Forbidden" error to the occupant; for details, see the "Modifying the Member List" use case under Moderator Use Cases.)

If the inviter supplies a non-existent JID, the room SHOULD return a "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 43. 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 44. 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 Occupant Modification of the Room Subject

If allowed in accordance with room configuration, a mere occupant MAY have the privileges to change the subject in a room. For details, see the "Modifying the Room Subject" use case under "Moderator Use Cases".

6.9 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 45. 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 46. 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 47. 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 "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.10 Sending a Message to All Occupants

An occupant can send 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 can send 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 48. 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 49. 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.11 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:

Example 50. 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.

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 51. 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#user</value>
      </field>
      <field
          label='First Name'
          type='text-single'
          var='muc#user_first'>
        <required/>
      </field>
      <field
          label='Last Name'
          type='text-single'
          var='muc#user_last'>
        <required/>
      </field>
      <field
          label='Desired Nickname'
          type='text-single'
          var='muc#user_roomnick'>
        <required/>
      </field>
      <field
          label='Your URL'
          type='text-single'
          var='muc#user_url'/>
      <field
          label='Email Address'
          type='text-single'
          var='muc#user_email'/>
      <field
          label='FAQ Entry'
          type='text-multi'
          var='muc#user_faqentry'/>
    </x>
  </query>
</iq>
    

The user SHOULD then submit the form:

Example 52. 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#user</value>
      </field>
      <field var='muc#user_first'>
        <value>Brunhilde</value>
      </field>
      <field var='muc#user_last'>
        <value>Entwhistle-Throckmorton</value>
      </field>
      <field var='muc#user_roomnick'>
        <value>thirdwitch</value>
      </field>
      <field var='muc#user_url'>
        <value>http://witchesonline/~hag66/</value>
      </field>
      <field var='muc#user_email'>
        <value>hag66@witchesonline</value>
      </field>
      <field var='muc#user_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 53. 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 54. 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>
    

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

Example 55. 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 queue the request for review by the room admins or MAY immediately add the user to the member list by changing 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 56. 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 roomnick other than the user's registered roomnick.

6.12 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 57. 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 58. 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. Moderator Use Cases

A moderator has privileges to perform certain actions within the room (e.g., to change the roles of some occupants) but does not have rights to change persistent information about affiliations, which can be changed only by an admin. Exactly which actions can be performed by a moderator is subject to configuration. However, for the purposes of the MUC framework, moderators are stipulated to have privileges to perform the following actions:

  1. discover an occupant's full JID in a semi-anonymous room (occurs by default as shown above)
  2. modify the subject
  3. kick a participant or visitor from the room
  4. grant or revoke voice in a moderated room
  5. modify the list of occupants who have voice in a moderated room

These features shall be implemented with a request/response "conversation" using <iq/> elements that contain children scoped by the 'http://jabber.org/protocol/muc#admin' namespace. The examples below illustrate the protocol interactions to implement the desired functionality. (Except where explicitly noted below, any of the following administrative requests MUST be denied if the user@host of the 'from' address of the request does not match the full JID of one of the moderators; in this case, the service MUST return a "Forbidden" error.)

7.1 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 can be changed by sending a message of type "groupchat" to the room@service, containing no body but a <subject/> that specifies the new subject:

Example 59. 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 60. 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 61. 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>
    

7.2 Kicking a Visitor or Participant from a Room

A moderator has permissions kick a visitor or participant from a room. The kick is normally performed based on the occupant's room nickname (though it MAY be based on the full JID) and is effected by setting the role of a participant or visitor to a value of "none".

Example 62. Moderator Kicks Occupant

<iq from='fluellen@shakespeare.lit/pda'
    id='kick1'
    to='harfleur@henryv.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item nick='pistol' role='none'>
      <reason>Avaunt, you cullion!</reason>
    </item>
  </query>
</iq>
    

The service MUST remove the kicked occupant by sending a presence stanza of type "unavailable" to each kicked occupant, including status code 307 in the extended presence information, optionally along with the reason (if provided) and the bare JID of the user who initiated the kick.

Example 63. Service Removes Kicked Occupant

<presence
    from='harfleur@henryv.shakespeare.lit/pistol'
    to='pistol@shakespeare.lit/harfleur'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='none' role='none'>
      <actor jid='fluellen@shakespeare.lit'/>
      <reason>Avaunt, you cullion!</reason>
    </item>
    <status code='307'/>
  </x>
</presence>
    

The inclusion of the status code assists clients in presenting their own notification messages (e.g., information appropriate to the user's locality). The optional inclusion of the reason and actor enable the kicked user to understand why he or she was kicked, and by whom if the kicked occupant would like to discuss the matter.

After removing the kicked occupant(s), the service MUST then inform the moderator of success:

Example 64. Service Informs Moderator of Success

<iq from='harfleur@henryv.shakespeare.lit'
    id='kick1'
    to='fluellen@shakespeare.lit/pda'
    type='result'/>
    

After informing the moderator, the service MUST then inform all of the remaining occupants that the kicked occupant is no longer in the room by sending presence stanzas of type "unavailable" from the kicked occupant to all the remaining occupants (just as it does when occupants exit the room of their own volition), including the status code and optionally the reason.

Example 65. Service Informs Remaining Occupants

<presence
    from='harfleur@henryv.shakespeare.lit/pistol'
    to='gower@shakespeare.lit/cell'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='none' role='none'/>
    <status code='307'/>
  </x>
</presence>
.
.
.
    

A moderator cannot be kicked from a room, nor can any user with an affiliation of "owner" or "admin". If a moderator attempts to kick such a user, the service MUST deny the request and return a "Not Allowed" error to the sender:

Example 66. Service Returns Error on Attempt to Kick Moderator, Admin, or Owner

<iq from='darkcave@macbeth.shakespeare.lit'
    id='kicktest'
    to='wiccarocks@shakespeare.lit/laptop'
    type='error'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item nick='firstwitch' role='none'>
      <reason>Be gone!</reason>
    </item>
  </query>
  <error code='405' type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

7.3 Granting Voice to a Visitor

In a moderated room, a moderator may want to manage who does and does not have "voice" in the room. Voice is granted based on the visitor's room nickname, which the service will convert into the visitor's full JID internally. The moderator can grant voice to a visitor by changing the visitor's role to "participant" (the <reason/> element is optional):

Example 67. Moderator Grants Voice to a Visitor

<iq from='crone1@shakespeare.lit/desktop'
    id='voice1'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item nick='thirdwitch'
          role='participant'>
      <reason>A worthy witch indeed!</reason>
    </item>
  </query>
</iq>
    

The service MUST then inform the moderator of success:

Example 68. Service Informs Moderator of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='voice1'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

The service MUST then send updated presence from this individual to all occupants, indicating the addition of voice privileges by including 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 "participant".

Example 69. Service Sends Notice of Voice 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'
          nick='thirdwitch'
          role='participant'>
      <reason>A worthy witch indeed!</reason>
    </item>
  </x>
</presence>
.
.
.
    

7.4 Revoking Voice from a Participant

In a moderated room, a moderator may want to revoke a participant's privileges to speak. The moderator can revoke voice from a participant by changing the participant's role to "visitor":

Example 70. Moderator Revokes Voice from a Participant

<iq from='crone1@shakespeare.lit/desktop'
    id='voice2'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item nick='thirdwitch'
          role='visitor'/>
  </query>
</iq>
    

The service MUST then inform the moderator of success:

Example 71. Service Informs Moderator of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='voice2'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

The service MUST then send updated presence from this individual to all occupants, indicating the removal of voice privileges by sending a presence element that contains 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 "visitor".

Example 72. Service Notes Loss of Voice

<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='visitor'/>
  </x>
</presence>
.
.
.
    

A moderator MUST NOT be able to revoke voice from a user whose affiliation is at or above the moderator's level. In addition, a service MUST NOT allow the voice privileges of an admin or owner to be removed by anyone. If a moderator attempts to revoke voice privileges from such a user, the service MUST deny the request and return a "Not Allowed" error to the sender:

Example 73. Service Returns Error on Attempt to Revoke Voice from an Admin, Owner, or User with a Higher Affiliation

<iq from='darkcave@macbeth.shakespeare.lit'
    id='voicetest'
    to='crone1@shakespeare.lit/desktop'
    type='error'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item nick='secondwitch' role='visitor'/>
  </query>
  <error code='405' type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

7.5 Modifying the Voice List

A moderator in a moderated room may want to modify the voice list. To do so, the moderator first requests the voice list by querying the room for all occupants with a role of 'participant'.

Example 74. Moderator Requests Voice List

<iq from='author@shakespeare.lit/globe'
    id='voice3'
    to='goodfolk@chat.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item role='participant'/>
  </query>
</iq>
    

The service MUST then return the voice list to the moderator; each item MUST include the 'nick' and 'role' attributes and SHOULD include the 'affiliation' and 'jid' attributes:

Example 75. Service Sends Voice List to Moderator

<iq from='goodfolk@chat.shakespeare.lit'
    id='voice3'
    to='author@shakespeare.lit/globe'
    type='result'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='none'
          jid='polonius@hamlet/castle'
          nick='Polo'
          role='participant'/>
    <item affiliation='none'
          jid='horatio@hamlet/castle'
          nick='horotoro'
          role='participant'/>
    <item affiliation='member'
          jid='hecate@shakespeare.lit/broom'
          nick='Hecate'
          role='participant'/>
  </query>
</iq>
    

The moderator can then modify the voice list and send the changed items (i.e., only the "delta") back to the service; each item MUST include the 'nick' and 'role' attributes but SHOULD NOT include the 'jid' attribute and MUST NOT include the 'affiliation' attribute (which is used to manage affiliations such as owner rather than the participant role):

Example 76. Moderator Sends Modified Voice List to Service

<iq from='author@shakespeare.lit/globe'
    id='voice4'
    to='goodfolk@chat.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item nick='Hecate'
          role='visitor'/>
    <item nick='rosencrantz'
          role='participant'>
      <reason>A worthy fellow.</reason>
    </item>
    <item nick='guildenstern'
          role='participant'>
      <reason>A worthy fellow.</reason>
    </item>
  </query>
</iq>
    

The service MUST then inform the moderator of success:

Example 77. Service Informs Moderator of Success

<iq from='goodfolk@chat.shakespeare.lit'
    id='voice1'
    to='author@shakespeare.lit/globe'
    type='result'/>
    

The service MUST then send updated presence for any affected individuals to all occupants, indicating the change in voice privileges by sending the appropriate extended presence packets as described in the foregoing use cases.

As noted, voice privileges cannot be revoked from a room owner or room admin, nor from any user with a higher affiliation than the moderator making the request. If a room admin attempts to revoke voice privileges from such a user by modifying the voice list, the service MUST deny the request and return a "Not Allowed" error to the sender:

Example 78. Service Returns Error on Attempt to Revoke Voice from an Admin, Owner, or User with a Higher Affiliation

<iq from='goodfolk@chat.shakespeare.lit'
    id='voicetest'
    to='author@shakespeare.lit/globe'
    type='error'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item jid='hecate@shakespeare.lit'
          nick='Hecate'
          role='visitor'/>
  </query>
  <error code='405' type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

8. Admin Use Cases

A room administrator has privileges to modify persistent information about user affiliations (e.g., by banning users) and to grant and revoke moderator privileges, but does not have rights to change the defining features of the room, which are the sole province of the room owner. Exactly which actions MAY be performed by a room admin will be subject to configuration. However, for the purposes of the MUC framework, room admins are stipulated to have privileges to perform the following actions:

  1. ban a user from the room
  2. modify the list of users who are banned from the room
  3. grant or revoke membership
  4. modify the member list
  5. grant or revoke moderator privileges
  6. modify the list of moderators

These features shall be implemented with a request/response "conversation" using <iq/> elements that contain children scoped by the 'http://jabber.org/protocol/muc#admin' namespace. The examples below illustrate the protocol interactions proposed to implement the desired functionality. (Except where explicitly noted below, any of the following administrative requests MUST be denied if the user@host of the 'from' address of the request does not match the bare JID of one of the room admins; in this case, the service MUST return a "Forbidden" error.)

8.1 Banning a User

An admin or owner can ban one or more users from a room. The ban MUST be performed based on the occupant's bare JID. In order to ban a user, an admin MUST change the user's affiliation to "outcast".

Example 79. Admin Bans User

<iq from='kinghenryv@shakespeare.lit/throne'
    id='ban1'
    to='southampton@henryv.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='outcast'
          jid='earlofcambridge@shakespeare.lit'>
      <reason>Treason</reason>
    </item>
  </query>
</iq>
    

The service MUST add that bare JID to the ban list and inform the admin or owner of success:

Example 80. Service Informs Admin or Owner of Success

<iq from='southampton@henryv.shakespeare.lit'
    id='ban1'
    to='kinghenryv@shakespeare.lit/throne'
    type='result'/>
    

The service MUST also remove any banned users who are in the room by sending a presence stanza of type "unavailable" to each banned occupant, including status code 301 in the extended presence information, optionally along with the reason (if provided) and the bare JID of the user who initiated the ban.

Example 81. Service Removes Banned User

<presence
    from='southampton@henryv.shakespeare.lit/cambridge'
    to='earlofcambridge@shakespeare.lit/stabber'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='outcast' role='none'>
      <actor jid='kinghenryv@shakespeare.lit'/>
      <reason>Treason</reason>
    </item>
    <status code='301'/>
  </x>
</presence>
    

The inclusion of the status code assists clients in presenting their own notification messages (e.g., information appropriate to the user's locality). The optional inclusion of the reason and actor enable the banned user to understand why he or she was banned, and by whom if the banned user would like to discuss the matter.

The service MUST then inform all of the remaining occupants that the banned user is no longer in the room by sending presence stanzas of type "unavailable" from the banned user to all remaining occupants (just as it does when occupants exit the room of their own volition), including the status code and optionally the reason:

Example 82. Service Informs Remaining Occupants

<presence
    type='unavailable'
    from='southampton@henryv.shakespeare.lit/cambridge'
    to='exeter@shakespeare.lit/pda'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='outcast'
          jid='earlofcambridge@shakespeare.lit/stabber'
          role='none'/>
    <status code='301'/>
  </x>
</presence>
.
.
.
    

An owner or admin cannot be banned from a room. If a room admin attempts to ban such a user, the service MUST deny the request and return a "Not Allowed" error to the sender:

Example 83. Service Returns Error on Attempt to Ban an Admin or Owner

<iq from='harfleur@henryv.shakespeare.lit'
    id='bantest'
    to='exeter@shakespeare.lit/pda'
    type='error'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='outcast'
          jid='kinghenryv@shakespeare.lit'
          nick='TheKing'/>
  </query>
  <error code='405' type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

8.2 Modifying the Ban List

A room admin may want to modify the ban list. Note that the ban list is always based on a user's bare JID (unlike the ban command which is usually based on a room nickname), although a nick (perhaps the last room nickname associated with that JID) MAY be included for convenience. To modify the list of banned JIDs, the admin first requests the ban list by querying the room for all users with an affiliation of 'outcast'.

Example 84. Admin Requests Ban List

<iq from='kinghenryv@shakespeare.lit/throne'
    id='ban2'
    to='southampton@henryv.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='outcast'/>
  </query>
</iq>
    

The service MUST then return the list of banned users to the admin; each item MUST include the 'affiliation' and 'jid' attributes but SHOULD NOT include the 'nick' and 'role' attributes:

Example 85. Service Sends Ban List to Admin

<iq from='southampton@henryv.shakespeare.lit'
    id='ban2'
    to='kinghenryv@shakespeare.lit/throne'
    type='result'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='outcast'
          jid='earlofcambridge@shakespeare.lit'>
      <reason>Treason</reason>
    </item>
  </query>
</iq>
    

The admin can then modify the ban list and send the changed items (i.e., only the "delta") back to the service; each item MUST include the 'affiliation' and 'jid' attributes but SHOULD NOT include the 'nick' attribute and MUST NOT include the 'role' attribute (which is used to manage roles such as participant rather than the outcast affiliation); in addition, the reason and actor elements are OPTIONAL:

Example 86. Admin Sends Modified Ban List to Service

<iq from='kinghenryv@shakespeare.lit/throne'
    id='ban3'
    to='southampton@henryv.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='outcast'
          jid='earlofcambridge@shakespeare.lit'>
      <reason>Treason</reason>
    </item>
    <item affiliation='outcast'>
          jid='lordscroop@shakespeare.lit' 
      <reason>Treason</reason>
    </item>
    <item affiliation='outcast'
          jid='sirthomasgrey@shakespeare.lit'>
      <reason>Treason</reason>
    </item>
  </query>
</iq>
    

After updating the ban list, the service MUST inform the admin of success:

Example 87. Service Informs Admin of Success

<iq from='southampton@henryv.shakespeare.lit'
    id='ban3'
    to='kinghenryv@shakespeare.lit/throne'
    type='result'/>
    

The service MUST then remove the affected occupants (if they are in the room) and send updated presence (including the appropriate status code) from them to all the remaining occupants as described in the "Banning a User" use case. (The service SHOULD also remove each banned user's reserved nickname from the list of reserved roomnicks, if appropriate.)

As noted, a room owner or room admin cannot be banned from a room. If a room admin attempts to ban such a user by means of modifying the ban list, the service MUST deny the request and return a "Not Allowed" error to the sender:

Example 88. Service Returns Error on Attempt to Ban an Admin or Owner

<iq from='southampton@henryv.shakespeare.lit'
    id='bantest'
    to='lordscroop@shakespeare.lit'
    type='error'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='outcast'
          jid='exeter@shakespeare.lit'/>
  </query>
  <error code='405' type='cancel'>
    <not-allowed
        xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

When an entity is banned from a room, an implementation SHOULD match JIDs in the following order (these matching rules are the same as those defined for privacy lists in XMPP IM [7]):

  1. <user@domain/resource> (only that resource matches)
  2. <user@domain> (any resource matches)
  3. <domain/resource> (only that resource matches)
  4. <domain> (the domain itself matches, as does any user@domain, domain/resource, or address containing a subdomain)

Some administrators may wish to ban all users associated with a specific domain from all rooms hosted by a MUC service. Such functionality is a service-level feature and is therefore out of scope for this document.

8.3 Granting Membership

An admin can grant membership to a user; this is done by changing the user's affiliation to "member" (normally based on nick if the user is in the room, or on bare JID if not; in either case, if the nick is provided, that nick becomes the user's default nick in the room if that functionality is supported by the implementation):

Example 89. Admin Grants Membership

<iq from='crone1@shakespeare.lit/desktop'
    id='member1'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='member'
          jid='hag66@shakespeare.lit'/>
  </query>
</iq>
    

The service MUST add the user to the member list and then inform the moderator of success:

Example 90. Service Informs Moderator of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='member1'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

If the user is in the room, the service MUST then send updated presence from this individual to all occupants, indicating the granting of membership 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 91. 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>
.
.
.
    

8.4 Revoking Membership

An admin may want to revoke a user's membership; this is done by changing the user's affiliation to "none":

Example 92. Admin Revokes Membership

<iq from='crone1@shakespeare.lit/desktop'
    id='member2'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='none'
          nick='thirdwitch'/>
  </query>
</iq>
    

The service MUST remove the user from the member list and then inform the moderator of success:

Example 93. Service Informs Moderator of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='member2'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

The service MUST then send updated presence from this individual to all occupants, indicating the loss of membership by sending a presence element that contains 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 "none".

Example 94. Service Notes Loss of Membership

<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 room is members-only, the service MUST remove the user from the room, including a status code of 321 to indicate that the user was removed because of an affiliation change, and inform all remaining occupants:

Example 95. Service Removes Non-Member

<presence
    from='darkcave@macbeth.shakespeare.lit/thirdwitch'
    to='crone1@shakespeare.lit/desktop'>
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='none' role='none'>
      <actor jid='author@shakespeare.lit'/>
    </item>
    <status code='321'/>
  </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='none' role='none'/>
    <status code='321'/>
  </x>
</presence>
.
.
.
    

8.5 Modifying the Member List

In the context of a members-only room, the member list is essentially a "whitelist" of people who are allowed to enter the room. Anyone who is not a member is effectively banned from entering the room, even if their affiliation is not "outcast".

In the context of an open room, the member list is simply a list of users (bare JID and reserved nick) who are registered with the room. Such users may appear in a room roster, have their room nickname reserved, be returned in search results or FAQ queries, and the like.

It is RECOMMENDED that only room admins have the privilege to modify the member list in members-only rooms. To do so, the admin first requests the member list by querying the room for all users with an affiliation of "member":

Example 96. Admin Requests Member List

<iq from='crone1@shakespeare.lit/desktop'
    id='member3'
    to='darkcave@macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='member'/>
  </query>
</iq>
    

(A service SHOULD also return the member list to any occupant in a members-only room; i.e., it SHOULD NOT generate a "Forbidden" error when a member in the room requests the member list. This functionality may assist clients in showing all the existing members even if some of them are not in the room, e.g. to help a member determine if another user should be invited.)

The service MUST then return the full member list to the admin in the 'http://jabber.org/protocol/muc#admin' namespace; each item MUST include the 'affiliation' and 'jid' attributes and MAY include the 'nick' and 'role' attributes for each members that is currently an occupant.

Example 97. Service Sends Member List to Admin

<iq from='darkcave@macbeth.shakespeare.lit'
    id='member3'
    to='crone1@shakespeare.lit/desktop'
    type='result'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='member'
          jid='hag66@shakespeare.lit'
          nick='thirdwitch'
          role='participant'/>
  </query>
</iq>
    

The admin can then modify the member list and send the changed items (i.e., only the "delta") to the service; each item MUST include the 'affiliation' and 'jid' attributes but SHOULD NOT include the 'nick' attribute and MUST NOT include the 'role' attribute (which is used to manage roles such as participant rather than the member affiliation):

Example 98. Admin Sends Modified Member List to Service

<iq from='crone1@shakespeare.lit/desktop'
    id='member4'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='none'
          jid='hag66@shakespeare.lit'/>
    <item affiliation='member'
          jid='hecate@shakespeare.lit'/>
  </query>
</iq>
    

The service MUST modify the member list and then inform the moderator of success:

Example 99. Service Informs Moderator of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='member4'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

The service MUST change the affiliation of any affected user. If the user has been removed from the member list, the service MUST change the user's affiliation from "member" to "none". If the user has been added to the member list, the service MUST change the user's affiliation to "member".

If the removed member is currently in a members-only room, the service SHOULD kick the occupant by changing the removed member's role to "none". No matter whether the removed member was in or out of a members-only room, the service MUST subsequently refuse entry to the user.

If the removed member is in an open room, the service 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 "none".

Example 100. Service Sends Notice of Loss 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='none'
          jid='hag66@shakespeare.lit/pda'
          role='participant'/>
  </x>
</presence>
.
.
.
    

In addition, the service SHOULD send an invitation to any user who has been added to the member list of a members-only room (such a user would by definition not be in the room; note also that this example includes a password but not a reason -- both child elements are OPTIONAL):

Example 101. Room Sends Invitation to New Member

<message
    from='darkcave@macbeth.shakespeare.lit'
    to='hecate@shakespeare.lit'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <invite from='author@shakespeare.lit'/>
    <password>cauldron</password>
  </x>
  <x jid='darkcave@macbeth.shakespeare.lit'
     xmlns='jabber:x:conference'/>
</message>
    

While only admins and owners SHOULD be allowed to modify the member list, an implementation MAY provide a configuration option that opens invitation privileges to any member of a members-only room. In such a situation, any invitation sent SHOULD automatically trigger the addition of the invitee to the member list. However, if invitation privileges are restricted to admins and a mere member attempts to a send an invitation, the service MUST deny the invitation request and return a "Forbidden" error to the sender:

Example 102. Service Returns Error on Attempt by Mere Member to Invite Others to a Members-Only Room

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

Invitations sent through an open room MUST NOT trigger the addition of the invitee to the member list.

If a user is added to the member list of an open room and the user is in the room, the service 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 103. Service Sends Notice of Membership to All Occupants

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

8.6 Granting Moderator Privileges

An admin may want to grant moderator privileges to a participant or visitor; this is done by changing the user's role to "moderator":

Example 104. Admin Grants Moderator Privileges

<iq from='crone1@shakespeare.lit/desktop'
    id='mod1'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item nick='thirdwitch'
          role='moderator'/>
  </query>
</iq>
    

The service MUST add the user to the moderator list and then inform the admin of success:

Example 105. Service Informs Moderator of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='mod1'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

The service MUST then send updated presence from this individual to all occupants, indicating the addition of moderator privileges by including 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".

Example 106. Service Sends Notice of Moderator Privileges 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='moderator'/>
  </x>
</presence>
.
.
.
    

8.7 Revoking Moderator Privileges

An admin may want to revoke a user's moderator privileges. An admin MAY revoke moderator privileges only from a user whose affiliation is "member" or "none" (i.e., not from an owner or admin). The privilege is revoked by changing the user's role to "participant":

Example 107. Admin Revokes Moderator Privileges

<iq from='crone1@shakespeare.lit/desktop'
    id='mod2'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item nick='thirdwitch'
          role='participant'/>
  </query>
</iq>
    

The service MUST remove the user from the moderator list and then inform the admin of success:

Example 108. Service Informs Admin of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='mod2'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

The service MUST then send updated presence from this individual to all occupants, indicating the removal of moderator privileges by sending a presence element that contains 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 "participant".

Example 109. Service Notes Loss of Moderator Privileges

<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>
.
.
.
    

As noted, an admin MUST NOT be allowed to revoke moderator privileges from a user whose affiliation is "owner" or "admin". If an admin attempts to revoke moderator privileges from such a user, the service MUST deny the request and return a "Not Allowed" error to the sender:

Example 110. Service Returns Error on Attempt to Revoke Moderator Privileges from an Admin or Owner

<iq from='darkcave@macbeth.shakespeare.lit'
    id='modtest'
    to='crone1@shakespeare.lit/desktop'
    type='error'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item nick='secondwitch' role='participant'/>
  </query>
  <error code='405' type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

8.8 Modifying the Moderator List

An admin may want to modify the moderator list. To do so, the admin first requests the moderator list by querying the room for all users with a role of 'moderator'.

Example 111. Admin Requests Moderator List

<iq from='crone1@shakespeare.lit/desktop'
    id='mod3'
    to='darkcave@macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item role='moderator'/>
  </query>
</iq>
    

The service MUST then return the moderator list to the admin; each item MUST include the 'jid', 'nick', and 'role' attributes and MAY include the 'affiliation' attribute:

Example 112. Service Sends Moderator List to Admin

<iq from='darkcave@macbeth.shakespeare.lit'
    id='mod3'
    to='crone1@shakespeare.lit/desktop'
    type='result'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item jid='hag66@shakespeare.lit/pda'
          nick='thirdwitch'
          role='moderator'/>
  </query>
</iq>
    

The admin can then modify the moderator list and send the changed items (i.e., only the "delta") back to the service; each item MUST include the 'jid' and 'role' attributes but SHOULD NOT include the 'nick' attribute and MUST NOT include the 'affiliation' attribute (which is used to manage affiliations such as admin rather than the moderator role):

Example 113. Admin Sends Modified Moderator List to Service

<iq from='crone1@shakespeare.lit/desktop'
    id='mod4'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item jid='hag66@shakespeare.lit/pda'
          role='participant'/>
    <item jid='hecate@shakespeare.lit/broom'
          role='moderator'/>
  </query>
</iq>
    

The service MUST modify the moderator list and then inform the admin of success:

Example 114. Service Informs Admin of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='mod4'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

The service MUST then send updated presence for any affected individuals to all occupants, indicating the change in moderator privileges by sending the appropriate extended presence packets as described in the foregoing use cases.

As noted, moderator privileges cannot be revoked from a room owner or room admin. If a room admin attempts to revoke moderator privileges from such a user by modifying the moderator list, the service MUST deny the request and return a "Not Allowed" error to the sender:

Example 115. Service Returns Error on Attempt to Revoke Moderator Privileges from an Admin or Owner

<iq from='darkcave@macbeth.shakespeare.lit'
    id='modtest'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item jid='hecate@shakespeare.lit/broom'
          nick='Hecate'
          role='participant'/>
  </query>
  <error code='405' type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

9. Owner Use Cases

Every room MUST have at least one owner, and that owner (or a successor) is a long-lived attribute of the room for as long as the room exists (e.g., the owner does not lose ownership on exiting a persistent room). This JEP assumes that the (initial) room owner is the individual who creates the room and that only a room owner has the right to change defining room configuration settings such as the room type. Ideally, room owners will be able to specify not only the room types (password-protected, members-only, etc.) but also certain attributes of the room as listed under the requirements section of this JEP. In addition, it would be good if an owner were able to specify the JIDs of other owners, but that shall be determined by the implementation.

In order to provide the necessary flexibility for a wide range of configuration options, Data Forms [8] shall be used for room configuration, triggered by use of the 'http://jabber.org/protocol/muc' namespace.

Note that the configuration options shown below address all of the features and room types listed in the requirements section of this JEP, but that the exact configuration options and form layout shall be determined by the implementation or specific deployment. Also, these are examples only and are not intended to define the only allowed or required configuration options for rooms. A given implementation or deployment MAY choose to provide many additional configuration options (profanity filters, setting the default language for a room, message logging, etc.), which is why the use of the jabber:x:data protocol is valuable here.

Note also that the privilege to create rooms MAY be restricted to certain users or reserved to an administrator of the service. If access is restricted and a user attempts to create a room, the service MUST return a "Not Allowed" error:

Example 116. Service Informs User of Inability to Create a Room

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

If access is not restricted, the service MUST allow the user to create a room as described below.

9.1 Creating a Room

From the perspective of room creation, there are in essence two kinds of rooms:

The workflow for creating and configuring such rooms is as follows:

  1. The user MUST send presence to room@service/nick and signal his or her support for the Multi-User Chat protocol by including extended presence information in an empty <x/> child element scoped by the 'http://jabber.org/protocol/muc' namespace (note the lack of an '#owner' or '#user' fragment).

  2. If this user is allowed to create a room and the room does not yet exist, the service MUST create the room according to some default configuration, assign the requesting user as the initial room owner, and add the owner to the room but not allow anyone else to enter the room (effectively "locking" the room). The initial presence stanza received by the owner from the room MUST include extended presence information that indicates the user's status as an owner and that acknowledges that the room has been created (via status code 201) and is awaiting configuration.

  3. If the initial room owner would like to create and configure a reserved room, the room owner MUST then request a configuration form by sending an IQ stanza of type "get" to the room containing an empty <query/> element scoped by the 'http://jabber.org/protocol/muc#owner' namespace, then complete Steps 4 and 5. If the room owner would prefer to create an instant room, the room owner MUST send a query element scoped by the 'http://jabber.org/protocol/muc#owner' namespace and containing an empty <x/> element of type "submit" scoped by the 'jabber:x:data' namespace, then skip to Step 6.

  4. If the room owner requested a configuration form, the service MUST send an IQ to the room owner containing a configuration form in the 'jabber:x:data' namespace. If there are no configuration options available, the room MUST return an empty query element to the room owner.

  5. The initial room owner SHOULD provide a starting configuration for the room (or accept the default configuration) by sending an IQ of type "set" containing the completed configuration form. Alternatively, the room owner can cancel the configuration process. (An implementation MAY set a timeout for initial configuration, such that if the room owner does not configure the room within the timeout period, the room owner is assumed to have accepted the default configuration.)

  6. Once the service receives the completed configuration form from the initial room owner (or receives a request for an instant room), the service MUST "unlock" the room (i.e., allow other users to enter the room) and send an IQ of type "result" to the room owner. If the service receives a cancellation, it MUST destroy the room.

The protocol for this workflow is shown in the examples below.

First, the Jabber user MUST send presence to the room, including and empty <x/> element scoped by the 'http://jabber.org/protocol/muc' namespace (this is the same stanza sent when seeking to enter a room).

Example 117. Jabber User Creates a Room and Signals Support for Multi-User Chat

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

If the room does not yet exist, the service SHOULD create the room (subject to local policies regarding room creation), assign the bare JID of the requesting user as the owner, add the owner to the room, and acknowledge successful creation of the room.

Example 118. Service Creates Room

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

The initial room owner can request an instant room by sending the following XML:

Example 119. Owner Requests Instant Room

<iq from='crone1@shakespeare.lit/desktop'
    id='create1'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <x xmlns='jabber:x:data' type='submit'/>
  </query>
</iq>
    

If the initial room owner wants to create and configure a reserved room, the room owner MUST request an initial configuration form for the room by not including empty data form in the creation request:

Example 120. Owner Requests Configuration Form

<iq from='crone1@shakespeare.lit/desktop'
    id='create1'
    to='darkcave@macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/muc#owner'/>
</iq>
    

If the room does not already exist, the service MUST return an initial room configuration form to the user.

Example 121. Service Sends Configuration Form

<iq from='darkcave@macbeth.shakespeare.lit'
    id='create1'
    to='crone1@shakespeare.lit/desktop'
    type='result'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <x xmlns='jabber:x:data' type='form'>
      <title>Configuration for "darkcave" Room</title>
      <instructions>
          Your room darkcave@macbeth has been created!
          The default configuration is as follows:
            - No logging
            - No moderation
            - Up to 20 occupants
            - No password required
            - No invitation required
            - Room is not persistent
            - Only admins may change the subject
            - Presence broadcasted for all users
          To accept the default configuration, click OK. To
          select a different configuration, please complete
          this form.
      </instructions>
      <field
          type='hidden'
          var='FORM_TYPE'>
        <value>http://jabber.org/protocol/muc#owner</value>
      </field>
      <field
          label='Natural-Language Room Name'
          type='text-single'
          var='muc#owner_roomname'/>
      <field
          label='Short Description of Room'
          type='text-single'
          var='muc#owner_roomdesc'/>
      <field
          label='Natural Language for Room Discussions'
          type='text-single'
          var='muc#owner_roomlang'/>
      <field
          label='Enable Logging?'
          type='boolean'
          var='muc#owner_enablelogging'>
        <value>0</value>
      </field>
      <field
          label='Allow Occupants to Change Subject?'
          type='boolean'
          var='muc#owner_changesubject'>
        <value>0</value>
      </field>
      <field
          label='Allow Occupants to Invite Others?'
          type='boolean'
          var='muc#owner_allowinvites'>
        <value>0</value>
      </field>
      <field
          label='Maximum Number of Occupants'
          type='list-single'
          var='muc#owner_maxusers'>
        <value>20</value>
        <option label='10'><value>10</value></option>
        <option label='20'><value>20</value></option>
        <option label='30'><value>30</value></option>
        <option label='50'><value>50</value></option>
        <option label='100'><value>100</value></option>
        <option label='None'><value>none</value></option>
      </field>
      <field
          label='Roles for which Presence is Broadcast'
          type='list-multi'
          var='muc#owner_presencebroadcast'>
        <value>moderator</value>
        <value>participant</value>
        <value>visitor</value>
        <option label='Moderator'><value>moderator</value></option>
        <option label='Participant'><value>participant</value></option>
        <option label='Visitor'><value>visitor</value></option>
      </field>
      <field
          label='Make Room Publicly Searchable?'
          type='boolean'
          var='muc#owner_publicroom'>
        <value>1</value>
      </field>
      <field
          label='Make Room Persistent?'
          type='boolean'
          var='muc#owner_persistentroom'>
        <value>0</value>
      </field>
      <field
          label='Make Room Moderated?'
          type='boolean'
          var='muc#owner_moderatedroom'>
        <value>0</value>
      </field>
      <field
          label='Make Room Members-Only?'
          type='boolean'
          var='muc#owner_membersonly'>
        <value>0</value>
      </field>
      <field
          label='Password Required to Enter?'
          type='boolean'
          var='muc#owner_passwordprotectedroom'>
        <value>0</value>
      </field>
      <field type='fixed'>
        <value>
          If a password is required to enter this room,
          you must specify the password below.
        </value>
      </field>
      <field
          label='Password'
          type='text-private'
          var='muc#owner_roomsecret'/>
      <field
          label='Who May Discover Real JIDs?'
          type='list-single'
          var='muc#owner_whois'>
        <option label='Moderators Only'>
          <value>moderators</value>
        </option>
        <option label='Anyone'>
          <value>anyone</value>
        </option>
      </field>
      <field type='fixed'>
        <value>
          You may specify additional people who have
          administrative privileges in the room. Please
          provide one Jabber ID per line.
        </value>
      </field>
      <field
          label='Room Admins'
          type='jid-multi'
          var='muc#owner_roomadmins'/>
      <field type='fixed'>
        <value>
          You may specify additional owners for this
          room. Please provide one Jabber ID per line.
        </value>
      </field>
      <field
          label='Room Owners'
          type='jid-multi'
          var='muc#owner_roomowners'/>
    </x>
  </query>
</iq>
    

If there are no configuration options available, the service MUST return an empty query element to the room owner:

Example 122. Service Informs Owner that No Configuration is Possible

<iq from='darkcave@macbeth.shakespeare.lit'
    id='create1'
    to='crone1@shakespeare.lit/desktop'
    type='result'>
  <query xmlns='http://jabber.org/protocol/muc#owner'/>
</iq>
    

The room owner SHOULD then fill out the form and submit it to the service.

Example 123. Owner Submits Configuration Form

<iq from='crone1@shakespeare.lit/desktop'
    id='create2'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <x xmlns='jabber:x:data' type='submit'>
      <field var='FORM_TYPE'>
        <value>http://jabber.org/protocol/muc#owner</value>
      </field>
      <field var='muc#owner_roomname'>
        <value>A Dark Cave</value>
      </field>
      <field var='muc#owner_roomdesc'>
        <value>The place for all good witches!</value>
      </field>
      <field var='muc#owner_enablelogging'>
        <value>0</value>
      </field>
      <field var='muc#owner_changesubject'>
        <value>1</value>
      </field>
      <field var='muc#owner_allowinvites'>
        <value>0</value>
      </field>
      <field var='muc#owner_maxusers'>
        <value>10</value>
      </field>
      <field var='muc#owner_publicroom'>
        <value>0</value>
      </field>
      <field var='muc#owner_persistentroom'>
        <value>0</value>
      </field>
      <field var='muc#owner_moderatedroom'>
        <value>0</value>
      </field>
      <field var='muc#owner_membersonly'>
        <value>0</value>
      </field>
      <field var='muc#owner_passwordprotectedroom'>
        <value>1</value>
      </field>
      <field var='muc#owner_roomsecret'>
        <value>cauldron</value>
      </field>
      <field var='muc#owner_whois'>
        <value>moderators</value>
      </field>
      <field var='muc#owner_roomadmins'>
        <value>
          wiccarocks@shakespeare.lit
          hecate@shakespeare.lit
        </value>
      </field>
    </x>
  </query>
</iq>
    

If room creation is successful, the service MUST inform the new room owner of success:

Example 124. Service Informs New Room Owner of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='create2'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

Alternatively, the room owner can cancel the configuration process:

Example 125. Owner Cancels Initial Configuration

<iq from='crone1@shakespeare.lit/desktop'
    id='create2'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <x xmlns='jabber:x:data' type='cancel'/>
  </query>
</iq>
    

If the room owner cancels the initial configuration, the service SHOULD destroy the room, making sure to send unavailable presence to the room owner (see the "Destroying a Room" use case for protocol details).

If the room owner becomes unavailable for any reason before submitting the form (e.g., a lost connection), the service will receive a presence stanza of type "unavailable" from the owner to the room@service/nick or room@service (or both). The service MUST then destroy the room, sending a presence stanza of type "unavailable" from the room to the owner including a <destroy/> element and reason (if provided) as defined under the "Destroying a Room" use case.

If a user attempts to enter the room while the room 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 "Not Found" error to the user:

Example 126. Service Denies Access Because Room Does Not Yet 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>
    

9.2 Subsequent Room Configuration

At any time after specifying the initial configuration of the room, a room owner may want to change the configuration. In order to initiate this "conversation", a room owner MUST request a new configuration form from the room by sending an IQ to room@service containing an empty <query/> element scoped by the 'http://jabber.org/protocol/muc#owner' namespace.

Example 127. Owner Requests Configuration Form

<iq from='crone1@shakespeare.lit/desktop'
    id='config1'
    to='darkcave@macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/muc#owner'/>
</iq>
    

If the user@host of the 'from' address does not match the bare JID of a room owner, the service MUST return a "Forbidden" error to the sender:

Example 128. Service Denies Configuration Access to Non-Owner

<iq from='darkcave@macbeth.shakespeare.lit'
    id='configures'
    to='wiccarocks@shakespeare.lit/laptop'
    type='error'>
  <query xmlns='http://jabber.org/protocol/muc#owner'/>
  <error code='403' type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

Otherwise, the service MUST send a configuration form to the room owner with the current options set as defaults:

Example 129. Service Sends Configuration Form to Owner

<iq from='darkcave@macbeth.shakespeare.lit'
    id='config1'
    to='crone1@shakespeare.lit/desktop'
    type='result'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <x xmlns='jabber:x:data' type='form'>
      <title>Configuration for "darkcave" Room</title>
      <instructions>
        Complete this form to make changes to
        the configuration of your room.
      </instructions>
      <field
          type='hidden'
          var='FORM_TYPE'>
        <value>http://jabber.org/protocol/muc#owner</value>
      </field>
      <field
          label='Natural-Language Room Name'
          type='text-single'
          var='muc#owner_roomname'>
        <value>A Dark Cave</value>
      </field>
      <field
          label='Short Description of Room'
          type='text-single'
          var='muc#owner_roomdesc'>
        <value>The place for all good witches!</value>
      </field>
      <field
          label='Enable Logging?'
          type='boolean'
          var='muc#owner_enablelogging'>
        <value>0</value>
      </field>
      <field
          label='Allow Occupants to Change Subject?'
          type='boolean'
          var='muc#owner_changesubject'>
        <value>0</value>
      </field>
      <field
          label='Allow Occupants to Invite Others?'
          type='boolean'
          var='muc#owner_allowinvites'>
        <value>0</value>
      </field>
      <field
          label='Maximum Number of Occupants'
          type='list-single'
          var='muc#owner_maxusers'>
        <value>10</value>
        <option label='10'><value>10</value></option>
        <option label='20'><value>20</value></option>
        <option label='30'><value>30</value></option>
        <option label='50'><value>50</value></option>
        <option label='100'><value>100</value></option>
        <option label='None'><value>none</value></option>
      </field>
      <field
          label='Roles for which Presence is Broadcast'
          type='list-multi'
          var='muc#owner_presencebroadcast'>
        <value>moderator</value>
        <value>participant</value>
        <value>visitor</value>
        <option label='Moderator'><value>moderator</value></option>
        <option label='Participant'><value>participant</value></option>
        <option label='Visitor'><value>visitor</value></option>
      </field>
      <field
          label='Make Room Publicly Searchable?'
          type='boolean'
          var='muc#owner_publicroom'>
        <value>0</value>
      </field>
      <field
          label='Make Room Persistent?'
          type='boolean'
          var='muc#owner_persistentroom'>
        <value>0</value>
      </field>
      <field
          label='Make Room Moderated?'
          type='boolean'
          var='muc#owner_moderatedroom'>
        <value>0</value>
      </field>
      <field
          label='Make Room Members Only?'
          type='boolean'
          var='muc#owner_membersonly'>
        <value>0</value>
      </field>
      <field
          label='Password Required for Entry?'
          type='boolean'
          var='muc#owner_passwordprotectedroom'>
        <value>1</value>
      </field>
      <field type='fixed'>
        <value>
          If a password is required to enter this room,
          you must specify the password below.
        </value>
      </field>
      <field
          label='Password'
          type='text-private'
          var='muc#owner_roomsecret'>
        <value>cauldron</value>
      </field>
      <field
          label='Who May Discover Real JIDs?'
          type='list-single'
          var='muc#owner_whois'>
        <value>moderators</value>
        <option label='Moderators Only'>
          <value>moderators</value>
        </option>
        <option label='Anyone'>
          <value>anyone</value>
        </option>
      </field>
      <field type='fixed'>
        <value>
          You may specify additional people who have
          administrative privileges in the room. Please
          provide one Jabber ID per line.
        </value>
      </field>
      <field
          label='Room Admins'
          type='jid-multi'
          var='muc#owner_roomadmins'>
        <value>wiccarocks@shakespeare.lit</value>
        <value>hecate@shakespeare.lit</value>
      </field>
      <field type='fixed'>
        <value>
          You may specify additional owners for this
          room. Please provide one Jabber ID per line.
        </value>
      </field>
      <field
          label='Room Owners'
          type='jid-multi'
          var='muc#owner_roomowners'/>
    </x>
  </query>
</iq>
    

If there are no configuration options available, the service MUST return an empty query element to the room owner as shown above.

The room owner can then submit the form with updated configuration information.

Alternatively, the room owner can cancel the configuration process:

Example 130. Owner Cancels Subsequent Configuration

<iq from='crone1@shakespeare.lit/desktop'
    id='config2'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <x xmlns='jabber:x:data' type='cancel'/>
  </query>
</iq>
    

If the room owner cancels the subsequent configuration, the service MUST leave the configuration of the room as it was before the room owner initiated the subsequent configuration process.

If as a result of a change in the room configuration a room admin loses administrative privileges while the admin is in the room, the room MUST send updated presence for that individual to all occupants, denoting the change in status 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" and the 'role' attribute set to a value of "participant" or "visitor" as appropriate for the affiliation level and the room type:

Example 131. Service Notes Loss of Admin Affiliation

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

If as a result of a change in the room configuration a user gains administrative privileges while the user is in the room, the room MUST send updated presence for that individual to all occupants, denoting the change in status 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 "admin" and the 'role' attribute set to a value of "admin":

Example 132. Service Notes Gain of Admin Affiliation to All Users

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

If as a result of a change in the room configuration a room owner loses owner privileges while that owner is in the room, the room MUST send updated presence for that individual to all occupants, denoting the change in status 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 "admin" and the 'role' attribute set to a value of "moderator":

Example 133. Service Notes Loss of Owner Affiliation

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

As noted, a service MUST NOT allow an owner to revoke his or her own privilege of ownership if there are no other owners; if an owner attempts to do this, the service MUST return a "Conflict" error to the owner.

If as a result of a change in the room configuration a user gains ownership privileges while the user is in the room, the room MUST send updated presence for that individual to all occupants, denoting the change in status 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 "owner" and the 'role' attribute set to a value of 'moderator'.

Example 134. Service Notes Gain of Owner Affiliation to All Users

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

If as a result of a change in the room configuration the room type is changed to members-only but there are non-members in the room, the service MUST remove any non-members from the room and include a status code of 322 in the presence unavailable stanzas sent to those users as well as any remaining occupants.

9.3 Granting Ownership Privileges

If allowed by an implementation, an owner MAY grant ownership privileges to another user; this is done by changing the user's affiliation to "owner":

Example 135. Owner Grants Ownership Privileges

<iq from='crone1@shakespeare.lit/desktop'
    id='owner1'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='owner'
          jid='hecate@shakespeare.lit'/>
  </query>
</iq>
    

The service MUST add the user to the owner list and then inform the owner of success:

Example 136. Service Informs Owner of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='owner1'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

If the user is in the room, the service MUST then send updated presence from this individual to all occupants, indicating the granting of ownership privileges 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 "owner" and the 'role' attribute set to a value of "moderator".

Example 137. Service Sends Notice of Ownership Privileges to All Occupants

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

9.4 Revoking Ownership Privileges

An owner may want to revoke a user's ownership privileges; this is done by changing the user's affiliation to "admin":

Example 138. Owner Revokes Ownership Privileges

<iq from='crone1@shakespeare.lit/desktop'
    id='owner2'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='admin'
          jid='hecate@shakespeare.lit'/>
  </query>
</iq>
    

A service MUST NOT allow an owner to revoke his or her own privilege of ownership if there are no other owners; if an owner attempts to do this, the service MUST return a "Conflict" error to the owner.

In all other cases, the service MUST remove the user from the owner list and then inform the owner of success:

Example 139. Service Informs Owner of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='owner2'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

The service MUST then send updated presence from this individual to all occupants, indicating the loss of ownership privileges by sending a presence element that contains 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 "admin" and the 'role' attribute set to a value of "moderator":

Example 140. Service Notes Loss of Owner Affiliation

<presence
    from='darkcave@macbeth.shakespeare.lit/secondwitch'
    to='crone1@shakespeare.lit/desktop'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='admin'
          jid='hecate@shakespeare.lit/broom'
          role='moderator'/>
  </x>
</presence>
.
.
.
    

9.5 Modifying the Owner List

If allowed by an implementation, a room owner may want to modify the owner list. To do so, the owner first requests the owner list by querying the room for all users with an affiliation of 'owner'.

Example 141. Owner Requests Owner List

<iq from='author@shakespeare.lit/globe'
    id='owner3'
    to='darkcave@macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='owner'/>
  </query>
</iq>
    

The service MUST then return the owner list to the owner; each item MUST include the 'affiliation' and 'jid' attributes and MAY include the 'nick' and 'role' attributes for any owner that is currently an occupant:

Example 142. Service Sends Owner List to Owner

<iq from='darkcave@macbeth.shakespeare.lit'
    id='owner3'
    to='author@shakespeare.lit/globe'
    type='result'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='owner'
          jid='crone1@shakespeare.lit'/>
  </query>
</iq>
    

The owner can then modify the owner list and send the changed items (i.e., only the "delta") back to the service; each item MUST include the 'affiliation' and 'jid' attributes but SHOULD NOT include the 'nick' attribute and MUST NOT include the 'role' attribute (which is used to manage roles such as participant rather than the owner affiliation):

Example 143. Owner Sends Modified Owner List to Service

<iq from='author@shakespeare.lit/globe'
    id='owner4'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='owner'
          jid='hecate@shakespeare.lit'/>
  </query>
</iq>
    

As noted, a service MUST NOT allow an owner to revoke his or her own privilege of ownership if there are no other owners; if an owner attempts to do this, the service MUST return a "Conflict" error to the owner.

In all other cases, the service MUST modify owner list and then inform the owner of success:

Example 144. Service Informs Owner of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='owner4'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

Only owners shall be allowed to modify the owner list. If a non-owner attempts to view or modify the owner list, the service MUST deny the request and return a "Forbidden" error to the sender:

Example 145. Service Returns Error on Attempt by Non-Owner to Modify Owner List

<iq from='darkcave@macbeth.shakespeare.lit'
    id='ownertest'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='owner' 
          jid='hecate@shakespeare.lit'/>
  </query>
  <error code='403' type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

9.6 Granting Administrative Privileges

An owner can grant administrative privileges to a member or unaffiliated user; this is done by changing the user's affiliation to "admin":

Example 146. Owner Grants Admin Privileges

<iq from='crone1@shakespeare.lit/desktop'
    id='admin1'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='admin'
          jid='wiccarocks@shakespeare.lit'/>
  </query>
</iq>
    

The service MUST add the user to the admin list and then inform the owner of success:

Example 147. Service Informs Owner of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='admin1'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

If the user is in the room, the service MUST then send updated presence from this individual to all occupants, indicating the granting of administrative privileges 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 "admin" and the 'role' attribute set to a value of "moderator".

Example 148. Service Sends Notice of Administrative Privileges to All Occupants

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

9.7 Revoking Administrative Privileges

An owner may want to revoke a user's administrative privileges; this is done by changing the user's affiliation to "member":

Example 149. Owner Revokes Administrative Privileges

<iq from='crone1@shakespeare.lit/desktop'
    id='admin2'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='member'
          nick='secondwitch'/>
  </query>
</iq>
    

The service MUST remove the user from the admin list and then inform the owner of success:

Example 150. Service Informs Owner of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='admin2'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

The service MUST then send updated presence from this individual to all occupants, indicating the loss of administrative privileges by sending a presence element that contains 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" and the 'role' attribute set to a value of "participant" or "visitor" as appropriate for the affiliation level and the room type:

Example 151. Service Notes Loss of Admin Affiliation

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

9.8 Modifying the Admin List

A room owner may want to modify the admin list. To do so, the owner first requests the admin list by querying the room for all users with an affiliation of 'admin'.

Example 152. Owner Requests Admin List

<iq from='author@shakespeare.lit/desktopaffiliation
    id='admin3'
    to='darkcave@macbeth.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='admin'/>
  </query>
</iq>
    

The service MUST then return the admin list to the owner; each item MUST include the 'affiliation' and 'jid' attributes and MAY include the 'nick' and 'role' attributes for any admin that is currently an occupant:

Example 153. Service Sends Admin List to Owner

<iq from='darkcave@macbeth.shakespeare.lit'
    id='admin3'
    to='author@shakespeare.lit/globe'
    type='result'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='admin'
          jid='wiccarocks@shakespeare.lit'
          nick='secondwitch'/>
    <item affiliation='admin'
          jid='hag66@shakespeare.lit'/>
  </query>
</iq>
    

The owner can then modify the admin list and send the changed items (i.e., only the "delta") back to the service; each item MUST include the 'affiliation' and 'jid' attributes but SHOULD NOT include the 'nick' attribute and MUST NOT include the 'role' attribute (which is used to manage roles such as participant rather than the admin affiliation):

Example 154. Owner Sends Modified Admin List to Service

<iq from='author@shakespeare.lit/globe'
    id='admin4'
    to='darkcave@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='none'
          jid='hag66@shakespeare.lit'>
    </item>
    <item affiliation='admin'
          jid='hecate@shakespeare.lit'>
    </item>
  </query>
</iq>
    

The service MUST modify the admin list and then inform the owner of success:

Example 155. Service Informs Owner of Success

<iq from='darkcave@macbeth.shakespeare.lit'
    id='admin4'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

Only owners shall be allowed to modify the admin list. If a non-owner attempts to view or modify the admin list, the service MUST deny the request and return a "Forbidden" error to the sender:

Example 156. Service Returns Error on Attempt by Non-Owner to Modify Admin List

<iq from='darkcave@macbeth.shakespeare.lit'
    id='admintest'
    to='hag66@shakespeare.lit/pda'
    type='error'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <item affiliation='admin' 
          jid='hecate@shakespeare.lit'/>
  </query>
  <error code='403' type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

9.9 Destroying a Room

A room owner MUST be able to destroy a room that he or she has created, especially if the room is persistent. The workflow is as follows:

  1. The room owner requests that the room be destroyed, specifying a reason and an alternate venue if desired.

  2. The room removes all users from the room (including appropriate information about the alternate location and the reason for being removed) and destroys the room, even if it was defined as persistent.

This JEP does not specify what if anything a compliant component implementation must do as a result of a room destruction request other than the foregoing. For example, if the room was defined as persistent, an implementation MAY choose to reserve the room ID or redirect enter requests to the alternate venue; however, such behavior is OPTIONAL.

In order to destroy a room, the room owner MUST send an IQ set to the address of the room to be destroyed. The <iq/> stanza shall contain a <query/> element qualified by the 'http://jabber.org/protocol/muc#owner' namespace, which in turn shall contain a <destroy/> element. The address of the alternate venue shall be provided in the <destroy/> element's 'jid' attribute (this is OPTIONAL). The reason for the room destruction shall be provided as the XML character data of a <reason/> child element of the <destroy/> element (this, too, is OPTIONAL).

The following examples illustrate the protocol elements to be sent and received:

Example 157. Owner Submits Room Destruction Request

<iq from='crone1@shakespeare.lit/desktop'
    id='begone'
    to='heath@macbeth.shakespeare.lit'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <destroy jid='darkcave@macbeth.shakespeare.lit'>
      <reason>Macbeth doth come.</reason>
    </destroy>
  </query>
</iq>
    

The service is responsible for removing all the occupants. It SHOULD NOT broadcast presence stanzas of type "unavailable" from all occupants, instead sending only one presence stanza of type "unavailable" to each occupant so that the user knows he or she has been removed from the room. If extended presence information specifying the JID of an alternate location and the reason for the room destruction was provided by the room owner, the presence stanza MUST include that information.

Example 158. Service Removes Each Occupant

<presence
    from='heath@macbeth.shakespeare.lit/firstwitch'
    to='crone1@shakespeare.lit/desktop'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='none' role='none'/>
    <destroy jid='darkcave@macbeth.shakespeare.lit'>
      <reason>Macbeth doth come.</reason>
    </destroy>
  </x>
</presence>

<presence
    from='heath@macbeth.shakespeare.lit/secondwitch'
    to='wiccarocks@shakespeare.lit/laptop'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='none' role='none'/>
    <destroy jid='darkcave@macbeth.shakespeare.lit'>
      <reason>Macbeth doth come.</reason>
    </destroy>
  </x>
</presence>

<presence
    from='heath@macbeth.shakespeare.lit/thirdwitch'
    to='hag66@shakespeare.lit/pda'
    type='unavailable'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <item affiliation='none' role='none'/>
    <destroy jid='darkcave@macbeth.shakespeare.lit'>
      <reason>Macbeth doth come.</reason>
    </destroy>
  </x>
</presence>
    

Example 159. Service Informs Owner of Successful Destruction

<iq from='heath@macbeth.shakespeare.lit'
    id='begone'
    to='crone1@shakespeare.lit/desktop'
    type='result'/>
    

If the user@host of the 'from' address received on a destroy request does not match the bare JID of a room owner, the service MUST return a "Forbidden" error to the sender:

Example 160. Service Denies Destroy Request Submitted by Non-Owner

<iq from='heath@macbeth.shakespeare.lit'
    id='destroytest'
    to='wiccarocks@shakespeare.lit/laptop'
    type='error'>
  <query xmlns='http://jabber.org/protocol/muc#owner'>
    <destroy jid='darkcave@macbeth.shakespeare.lit'>
      <reason>Macbeth doth come.</reason>
    </destroy>
  </query>
  <error code='403' type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

10. Error and Status Codes

The error codes associated with the 'http://jabber.org/protocol/muc#admin' namespace are fairly straightforward. However, in order to make it easier for client and component developers to understand the codes they need to send and receive, the table below provides a summary of all the error and status codes associated with the 'http://jabber.org/protocol/muc#user' namespace. For detailed information about mapping legacy error codes to XMPP-style error types and conditions, refer to Error Condition Mappings [9]; compliant implementations SHOULD support both legacy and XMPP error handling (no such requirement applies to MUC status codes).

Table 8: Error and Status Codes for http://jabber.org/protocol/muc#user Namespace

Code Type Element Context Purpose
100 Status Message Entering a room Inform user that any occupant is allowed to see the user's full JID
101 Status Message (out of band) Affiliation change Inform user that his or her affiliation changed while not in the room
102 Status In-room message Configuration change Inform occupants that room now shows unavailable members
103 Status Message Configuration change Inform occupants that room now does not show unavailable members
104 Status Message Configuration change Inform occupants that some room configuration has changed
201 Status Presence Entering a room Inform user that a new room has been created
301 Status Presence Removal from room Inform user that he or she has been banned from the room
303 Status Presence Exiting a room Inform all occupants of new room nickname
307 Status Presence Removal from room Inform user that he or she has been kicked from the room
321 Status Presence Removal from room Inform user that he or she is being removed from the room because of an affiliation change
322 Status Presence Removal from room Inform user that he or she is being removed from the room because the room has been changed to members-only and the user is not a member
332 Status Presence Removal from room Inform user that he or she is being removed from the room because of a system shutdown
401 Error Presence Entering a room Inform user that a password is required
403 Error Presence Entering a room Inform user that he or she is banned from the room
404 Error Presence Entering a room Inform user that the room does not exist
405 Error Presence Entering a room Inform user that room creation is restricted
407 Error Presence Entering a room Inform user that he or she is not on the member list
409 Error Presence Entering a room Inform user that his or her desired room nickname is taken

This JEP does not stipulate text messages associated with each error condition.

11. Security Considerations

No room entrance authentication method more secure than cleartext passwords is defined or required by this JEP. This is recognized to be sub-optimal; a future proposal will need to address this shortcoming.

12. IANA Considerations

This JEP requires no interaction with the Internet Assigned Numbers Authority (IANA) [10].

13. Jabber Registrar Considerations

The Jabber Registrar [11] shall include the following information in its registries.

13.1 Protocol Namespaces

Multi-User Chat uses the following protocol namespaces:

13.2 Service Discovery Category/Type

A Multi-User Chat service or room is identified by the "conference" category and the "text" type within Service Discovery. A registry submission is not required, since this entry already exists.

13.3 Service Discovery Features

There are many features related to a MUC service or room that can be discovered by means of Service Discovery. The most fundamental of these is the 'http://jabber.org/protocol/muc' namespace. In addition, a MUC room SHOULD provide information when queried about the specific room features it implements, such as password protection and room moderation.

Registry Submission

<var>
  <name>http://jabber.org/protocol/muc</name>
  <desc>Multi-User Chat (MUC) namespace</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_hidden</name>
  <desc>Hidden room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_membersonly</name>
  <desc>Members-only room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_moderated</name>
  <desc>Moderated room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_nonanonymous</name>
  <desc>Non-anonymous room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_open</name>
  <desc>Open room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_passwordprotected</name>
  <desc>Password-protected room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_persistent</name>
  <desc>Persistent room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_public</name>
  <desc>Public room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_semianonymous</name>
  <desc>Semi-anonymous room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_temporary</name>
  <desc>Temporary room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_unmoderated</name>
  <desc>Unmoderated room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_unsecured</name>
  <desc>Unsecured room in Multi-User Chat (MUC)</desc>
  <doc>JEP-0045</doc>
</var>
<var>
  <name>muc_rooms</name>
  <desc>List of MUC rooms (each as a separate item)</desc>
  <doc>JEP-0045</doc>
</var>
    

13.4 Field Standardization

Field Standardization for Data Forms [12] defines a process for standardizing the fields used within Data Forms scoped by a particular namespace. Within MUC, there are two uses of such forms: room registration within muc#user and room configuration within muc#owner. The reserved fields are defined below.

13.4.1 muc#user FORM_TYPE

Registry Submission

<form_type>
  <name>http://jabber.org/protocol/muc#user</name>
  <doc>JEP-0045</doc>
  <desc>
    Forms enabling user registration with a
    Multi-User Chat (MUC) room.
  </desc>
  <field
      var='muc#user_first'
      type='text-single'
      label='First Name'/>
  <field
      var='muc#user_last'
      type='text-single'
      label='Last Name'/>
  <field
      var='muc#user_roomnick'
      type='text-single'
      label='Desired Nickname'/>
  <field
      var='muc#user_url'
      type='text-single'
      label='Your URL'/>
  <field
      var='muc#user_email'
      type='text-single'
      label='Email Address'/>
  <field
      var='muc#user_faqentry'
      type='text-multi'
      label='FAQ Entry'/>
</form_type>
      

13.4.2 muc#owner FORM_TYPE

Registry Submission

<form_type>
  <name>http://jabber.org/protocol/muc#owner</name>
  <doc>JEP-0045</doc>
  <desc>
    Forms enabling owner creation and configuration of
    a Multi-User Chat (MUC) room.
  </desc>
  <field
      var='muc#owner_roomname'
      type='text-single'
      label='Natural-Language Room Name'/>
  <field
      var='muc#owner_roomdesc'
      type='text-single'
      label='Short Description of Room'/>
  <field
      var='muc#owner_enablelogging'
      type='boolean'
      label='Whether to Enable Logging of Room Conversations'/>
  <field
      var='muc#owner_changesubject'
      type='boolean'
      label='Whether to Allow Occupants to Change Subject'/>
  <field
      var='muc#owner_allowinvites'
      type='boolean'
      label='Whether to Allow Occupants to Invite Others'/>
  <field
      var='muc#owner_maxusers'
      type='list-single'
      label='Maximum Number of Room Occupants'/>
  <field
      var='muc#owner_presencebroadcast'
      type='list-multi'
      label='Roles for which Presence is Broadcast'/>
  <field
      var='muc#owner_publicroom'
      type='boolean'
      label='Whether to Allow Public Searching for Room'/>
  <field
      var='muc#owner_persistentroom'
      type='boolean'
      label='Whether to Make Room Persistent'/>
  <field
      var='muc#owner_membersonly'
      type='boolean'
      label='Whether an Make Room Members-Only'/>
  <field
      var='muc#owner_moderatedroom'
      type='boolean'
      label='Whether to Make Room Moderated'/>
  <field
      var='muc#owner_passwordprotectedroom'
      type='boolean'
      label='Whether a Password is Required to Enter'/>
  <field
      var='muc#owner_roomsecret'
      type='text-private'
      label='The Room Password'/>
  <field
      var='muc#owner_whois'
      type='list-single'
      label='Affiliations that May Discover Real JIDs of Occupants'/>
  <field
      var='muc#owner_roomadmins'
      type='jid-multi'
      label='List of Room Admins'/>
  <field
      var='muc#owner_roomowners'
      type='jid-multi'
      label='List of Room Owners'/>
</form_type>
      

13.4.3 muc#roominfo FORM_TYPE

Registry Submission

<form_type>
  <name>http://jabber.org/protocol/muc#roominfo</name>
  <doc>JEP-0045</doc>
  <desc>
    Forms enabling the communication of extended service discovery
    information about a Multi-User Chat (MUC) room.
  </desc>
  <field
      var='muc#roominfo_description'
      type='text-single'
      label='Short Description of Room'/>
  <field
      var='muc#roominfo_lang'
      type='text-single'
      label='Natural Language for Room Discussions'/>
  <field
      var='muc#roominfo_occupants'
      type='text-single'
      label='Current Number of Occupants in Room'/>
  <field
      var='muc#roominfo_subject'
      type='text-single'
      label='Current Subject or Discussion Topic in Room'/>
</form_type>
      

14. Business Rules

14.1 Room JIDs

In order to provide consistency regarding the addresses captured in room JIDs, Room IDs MUST match the Nodeprep profile of Stringprep and Room Nicknames MUST match the Resourceprep profile of Stringprep (both of these are defined in XMPP Core [13]).

14.2 Message

  1. If an occupant wants to send a message to all other occupants, a compliant client MUST set the 'type' attribute to a value of "groupchat". A service MAY ignore messages that are improperly typed, or reject them with a "Bad Request" error.

  2. If a compliant service receives a message directed to the room or to a single occupant from a Jabber user who has a role of "none", the service MUST NOT deliver the message and SHOULD return the message to the sender with a "Forbidden" error.

  3. If a compliant service receives a message directed to a room that does not exist or is locked, the service SHOULD return the message to the sender with a "Not Found" error.

  4. A compliant service SHOULD pass extended information (e.g., an XHTML version of the message body) through to occupants unchanged.

  5. A compliant client MUST NOT generate message events as specified in Message Events [14]; such message events are not intended for use in the context of groupchat.

14.3 Presence

  1. A room MUST silently ignore unavailable presence received from a user who has a role of "none".

  2. Only a component SHOULD generate extended presence information about roles, affiliations, full JIDs, or status codes scoped by the 'http://jabber.org/protocol/muc#user' namespace (based on information the component knows about occupants, e.g., roles, or as a result of actions taken by a moderator or room administrator). A client SHOULD NOT presume to generate such information. If a compliant component receives such extended presence information from an occupant, it MUST NOT reflect it to other occupants. A client can generate extended presence information in the 'http://jabber.org/protocol/muc#user' namespace in order to supply a password, but naturally this is not reflected to other occupants.

  3. A component SHOULD allow all other presence information to pass through, although it MAY choose to block extended presence information. Thus effectively clients can send a custom exit message if desired (as is often done in IRC channels) by including a <status/> element in the presence stanza of type "unavailable" sent when exiting a room.

  4. In order to appropriately inform occupants of room roles and affiliations, and to make it easier for Jabber clients to track the current state of all users in the room, compliant component implementations MUST provide extended presence information about roles and affiliations in all presence stanzas, including presence stanzas of type "unavailable" sent when a user exits the room for any reason.

  5. If a privilege is revoked, the service MUST note that by sending an <x/> element scoped by the 'http://jabber.org/protocol/muc#user' namespace and containing an <item/> child element with the 'role' and/or 'affiliation' attributes set to a value that indicates the loss of the relevant privilege. All future presence stanzas for the occupant MUST include the updated role and affiliation, until and unless they change again.

  6. A compliant service MUST send extended presence to a client even if the client did not send an empty <x/> element scoped by the 'http://jabber.org/protocol/muc' namespace on entering the room; naturally, a Jabber-compliant client MUST ignore such information if it does not understand it.

  7. Extended presence about roles and affiliations sent in the muc#user namespace MUST include the full JID (not the bare JID) as the value of the 'jid' attribute.

14.4 IQ

  1. If an occupant wants to send an IQ stanza to another user in a non-anonymous room, the sender SHOULD send the request directly to the recipient's bare JID or full JID, rather than attempting to send the request through the room (i.e., via the recipient's room JID).

  2. If an occupant wants to send an IQ stanza to another user in a semi-anonymous room, the sender can direct the stanza to the recipient's room JID and the service MAY forward the stanza to the recipient's real JID. However, a compliant service MUST NOT reveal the sender's real JID to the recipient at any time, nor reveal the recipient's real JID to the sender.

  3. A compliant client MUST send only the 'affiliation' attribute or the 'role' attribute in the <item/> element contained within an IQ set scoped by the 'http://jabber.org/protocol/muc#admin' namespace; if a moderator, admin, or owner attempts to modify both the affiliation and role of the same item in the same IQ set, the service MUST return a "Bad Request" error to the sender. However, a compliant service MAY modify a role based on a change to an affiliation and thus MAY send presence updates that include both a modified role and a modified affiliation.

  4. In IQ sets regarding roles, a compliant client MUST include the 'nick' attribute only; in IQ results regarding roles, a compliant service MUST include the 'nick', 'role', 'affiliation', and 'jid' attributes (with the value of the latter set to the user's full JID).

  5. In IQ sets regarding affiliations, a compliant client MUST include the 'jid' attribute only (with the value set to the bare JID); in IQ results regarding affiliations, a compliant service MUST NOT include the 'role' attribute, MUST include the 'affiliation' attribute and the 'jid' attribute (with the value set to the bare JID), and SHOULD include the 'nick' attribute (except if the affiliation is "outcast", since outcasts SHOULD NOT have reserved nicknames).

15. Implementation Notes

The following guidelines may assist client and component developers in creating compliant implementations.

15.1 Services

  1. In handling messages sent by visitors in a moderated room, a chatroom service MAY queue each message for approval by a moderator and MAY inform the sender that the message is being held for approval; however, such behavior is OPTIONAL, and definition of a message approval protocol (e.g., using Data Forms as defined in JEP-0004) is out of scope for this JEP.

  2. It is common for chatroom services to provide in-room messages when certain events occur, such as when the subject changes, when an occupant enters or exits, or when a room is destroyed. Such messages are entirely OPTIONAL and are left up to the implementation or deployment, but if used MUST be messages of type "groupchat" sent from the room JID itself (room@service) rather than a specific occupant (room@service/nick). However, in general it is preferable for the receiving client to generate such messages based on events in the room (e.g., user entrances and exits) as well as specific status codes provided in MUC; this will help ensure correct localization of such messages.

  3. Out of courtesy, a chatroom service MAY send a <message/> to an occupant who is kicked or banned, and MAY broadcast an in-room <message/> to all remaining occupants informing them that the occupant has been kicked or banned from the room. However, such messages are OPTIONAL, and indeed are unnecessary since the information required for a receiving client to generate such messages is communicated in the presence stanzas (specifically the status codes) sent by a MUC-compliant service.

  4. Out of courtesy, a chatroom service MAY send a <message/> outside the context of the room if a user's affiliation changes while the user is not in the room; the message SHOULD be sent from the room to the user's bare JID, MAY contain a <body/> element describing the affiliation change, and MUST contain a status code of 101.

  5. There is no requirement that a chatroom service shall provide special treatment for users of the older "groupchat 1.0" protocol, such as messages that contain equivalents to the extended presence information that is sent in the 'http://jabber.org/protocol/muc#user' namespace.

  6. Room types can be configured in any combination. A chatroom service MAY support or allow any desired room types or combinations thereof.

  7. A chatroom service MAY limit the number of configuration options presented to an owner after initial configuration has been completed, e.g. because certain options cannot take effect without restarting the service.

  8. A chatroom service MAY provide an interface to room creation and configuration (e.g., in the form of a special Jabber user or a Web page), so that the ostensible room owner is actually the application as opposed to a human user.

  9. A chatroom service MAY choose to make available a special in-room resource that provides an interface to administrative functionality (e.g., a "user" named "ChatBot"), which occupants could interact with directly, thus enabling admins to type /command parameter in a private message to that "user". Obviously this kind of implementation would require the service to add a 'ChatBot' user to the room when it is created, and to prevent any occupant from having the nickname 'ChatBot' in the room. This might be difficult to ensure in some implementations or deployments. In any case, any such interface is OPTIONAL.

  10. A chatroom service MAY choose to discard extended presence received from a client before updated presence is sent to the occupants. That is, an implementation MAY choose to reflect only the <show/>, <status/>, and <priority/> child elements of the presence element, with the result that presence "changes" in extended namespaces (e.g., gabber:x:music:info) are not passed through to occupants.

  11. A chatroom service MAY choose to send a message outside the context of the room to any user who is affected by a change in affiliation (e.g., if a user becomes an admin or owner). Such a message could include an appropriate status code in an extended child element scoped by the muc#user namespace.

  12. A chatroom service SHOULD remove a user if the service receives a delivery-related error in relation to a stanza it has previously sent to the user (remote server unreachable, user not found, etc.).

15.2 Clients

  1. Jabber clients MAY present room roles by showing ad-hoc groups for each role within a room roster. This will enable occupants to clearly visualize which occupants are moderators, participants, and visitors. However, such a representation is OPTIONAL.

  2. Jabber clients MAY implement a variety of interface styles that provide "shortcuts" to functionality such as changing one's nickname, kicking or banning users, discovering an occupant's full JID, or changing the subject. One option consists of IRC-style commands such as '/nick', '/kick', '/ban', and '/whois'; another is to enable a user to right-click items in a room roster. All such interface styles are OPTIONAL. However, for convenience, a mapping of IRC commands to MUC protocols is provided below.

15.2.1 IRC Command Mapping

Internet Relay Chat clients use a number of common "shortcut" commands that begin with a forward slash, such as '/nick' and '/ban'. The following table provides a mapping of IRC-style commands to MUC protocols, for use by Jabber clients that wish to support such functionality.

Table 9: IRC Command Mapping

Command Function MUC protocol
/ban <roomnick> [comment] bans user with that roomnick from this room (client translates roomnick to jid)

<iq id='someid'
    to='room@service'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item affiliation='outcast'
          jid='jid-of-roomnick'>
      <reason>comment</reason>
    </item>
  </query>
</iq>
          
/invite <jid> [comment] invites jid to this room

<message to='room@service'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <invite to='jid'>
      <reason>comment</reason>
    </invite>
  </x>
</message>
          
/join <roomname> [pass] joins room on this service (roomnick is same as nick in this room)

<presence to='room@service/nick'>
  <x xmlns='http://jabber.org/protocol/muc#user'>
    <password>pass</password>
  </x>
</presence>
          
/kick <roomnick> [comment] kicks user with that roomnick from this room

<iq id='someid'
    to='room@service'
    type='set'>
  <query xmlns='http://jabber.org/protocol/muc#admin'>
    <item nick='roomnick' role='none'>
      <reason>comment</reason>
    </item>
  </query>
</iq>
          
/msg <roomnick> <foo> sends private message "foo" to roomnick

<message to='room@service/nick'>
  <body>foo</body>
</message>
          
/nick <newnick> changes nick in this room to "newnick"

<presence to='room@service/newnick'/>
          
/part [comment] exits this room (some IRC clients also support /leave)

<presence to='room@service/nick'
          type='unavailable'>
  <status>comment</status>
</presence>
          
/topic <foo> changes subject of this room to "foo"

<message to='room@service' type='groupchat'>
  <subject>foo</subject>
</message>
          

Note: Because MUC roomnicks follow the Resouceprep profile of stringprep, they are allowed to contain a space character, whereas IRC nicknames do not. Although a given client MAY support quotation characters for this purpose (resulting in commands such as '/ban "king lear" insanity is no defense'), most common quotation characters (such as " and ') are also allowed by Resouceprep, thus leading to added complexity and potential problems with quotation of roomnicks that contain both spaces and quotation characters. Therefore it is NOT RECOMMENDED for Jabber clients to support IRC-style shortcut commands with roomnicks that contain space characters.

16. XML Schemas

16.1 http://jabber.org/protocol/muc

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='http://jabber.org/protocol/muc'
    xmlns='http://jabber.org/protocol/muc'
    elementFormDefault='qualified'>

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      JEP-0045: http://www.jabber.org/jeps/jep-0045.html
    </xs:documentation>
  </xs:annotation>

  <xs:element name='x'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='history' minOccurs='0'/>
        <xs:element name='password' type='xs:string' minOccurs='0'/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name='history'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
         <xs:attribute name='maxchars' type='xs:int' use='optional'/>
         <xs:attribute name='maxstanzas' type='xs:int' use='optional'/>
         <xs:attribute name='seconds' type='xs:int' use='optional'/>
         <xs:attribute name='since' type='xs:dateTime' use='optional'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name='empty'>
    <xs:restriction base='xs:string'>
      <xs:enumeration value=''/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>
    

16.2 http://jabber.org/protocol/muc#user

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='http://jabber.org/protocol/muc#user'
    xmlns='http://jabber.org/protocol/muc#user'
    elementFormDefault='qualified'>

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      JEP-0045: http://www.jabber.org/jeps/jep-0045.html
    </xs:documentation>
  </xs:annotation>

  <xs:element name='x'>
    <xs:complexType>
      <xs:choice minOccurs='0' maxOccurs='unbounded'>
        <xs:element ref='decline' minOccurs='0'/>
        <xs:element ref='destroy' minOccurs='0'/>
        <xs:element ref='invite' minOccurs='0'/>
        <xs:element ref='item' minOccurs='0'/>
        <xs:element name='password' type='xs:string' minOccurs='0'/>
        <xs:element ref='status' minOccurs='0'/>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:element name='decline'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='reason' minOccurs='0'/>
      </xs:sequence>
      <xs:attribute name='from' type='xs:string' use='optional'/>
      <xs:attribute name='to' type='xs:string' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='destroy'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='reason' minOccurs='0'/>
      </xs:sequence>
      <xs:attribute name='jid' type='xs:string' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='invite'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='reason' minOccurs='0'/>
      </xs:sequence>
      <xs:attribute name='from' type='xs:string' use='optional'/>
      <xs:attribute name='to' type='xs:string' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='item'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='actor' minOccurs='0'/>
        <xs:element ref='reason' minOccurs='0'/>
      </xs:sequence>
      <xs:attribute name='affiliation' use='required'>
        <xs:simpleType>
          <xs:restriction base='xs:NCName'>
            <xs:enumeration value='admin'/>
            <xs:enumeration value='member'/>
            <xs:enumeration value='none'/>
            <xs:enumeration value='outcast'/>
            <xs:enumeration value='owner'/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name='jid' type='xs:string' use='optional'/>
      <xs:attribute name='nick' type='xs:string' use='optional'/>
      <xs:attribute name='role' use='optional'>
        <xs:simpleType>
          <xs:restriction base='xs:NCName'>
            <xs:enumeration value='moderator'/>
            <xs:enumeration value='none'/>
            <xs:enumeration value='participant'/>
            <xs:enumeration value='visitor'/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>

  <xs:element name='actor'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='jid' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='status'>
    <xs:complexType>
      <xs:attribute name='code' use='required'>
        <xs:simpleType>
          <xs:restriction base='xs:int'>
            <xs:enumeration value='100'/>
            <xs:enumeration value='201'/>
            <xs:enumeration value='301'/>
            <xs:enumeration value='303'/>
            <xs:enumeration value='307'/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>

  <xs:element name='reason' type='xs:string'/>

  <xs:simpleType name='empty'>
    <xs:restriction base='xs:string'>
      <xs:enumeration value=''/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>
    

16.3 http://jabber.org/protocol/muc#admin

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='http://jabber.org/protocol/muc#admin'
    xmlns='http://jabber.org/protocol/muc#admin'
    elementFormDefault='qualified'>

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      JEP-0045: http://www.jabber.org/jeps/jep-0045.html
    </xs:documentation>
  </xs:annotation>

  <xs:element name='query'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='item' minOccurs='0' maxOccurs='unbounded'/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name='item'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='actor' minOccurs='0'/>
        <xs:element ref='reason' minOccurs='0'/>
      </xs:sequence>
      <xs:attribute name='affiliation' use='optional'>
        <xs:simpleType>
          <xs:restriction base='xs:NCName'>
            <xs:enumeration value='admin'/>
            <xs:enumeration value='member'/>
            <xs:enumeration value='none'/>
            <xs:enumeration value='outcast'/>
            <xs:enumeration value='owner'/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name='jid' type='xs:string' use='optional'/>
      <xs:attribute name='nick' type='xs:string' use='optional'/>
      <xs:attribute name='role' use='optional'>
        <xs:simpleType>
          <xs:restriction base='xs:NCName'>
            <xs:enumeration value='moderator'/>
            <xs:enumeration value='none'/>
            <xs:enumeration value='participant'/>
            <xs:enumeration value='visitor'/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>

  <xs:element name='actor'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='jid' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='reason' type='xs:string'/>

  <xs:simpleType name='empty'>
    <xs:restriction base='xs:string'>
      <xs:enumeration value=''/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>
    

16.4 http://jabber.org/protocol/muc#owner

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='http://jabber.org/protocol/muc#owner'
    xmlns='http://jabber.org/protocol/muc#owner'
    elementFormDefault='qualified'>

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      JEP-0045: http://www.jabber.org/jeps/jep-0045.html
    </xs:documentation>
  </xs:annotation>

  <xs:element name='query'>
    <xs:complexType>
      <xs:choice>
        <xs:element ref='item' minOccurs='0' maxOccurs='unbounded'/>
        <xs:element ref='destroy' minOccurs='0'/>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:element name='item'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='actor' minOccurs='0'/>
        <xs:element ref='reason' minOccurs='0'/>
      </xs:sequence>
      <xs:attribute name='affiliation' use='required'>
        <xs:simpleType>
          <xs:restriction base='xs:NCName'>
            <xs:enumeration value='admin'/>
            <xs:enumeration value='member'/>
            <xs:enumeration value='none'/>
            <xs:enumeration value='outcast'/>
            <xs:enumeration value='owner'/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name='jid' type='xs:string' use='optional'/>
      <xs:attribute name='nick' type='xs:string' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='actor'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='jid' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='destroy'>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref='reason' minOccurs='0'/>
      </xs:sequence>
      <xs:attribute name='jid' type='xs:string' use='optional'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='reason' type='xs:string'/>

  <xs:simpleType name='empty'>
    <xs:restriction base='xs:string'>
      <xs:enumeration value=''/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>
    

17. Acknowledgements

The author would like to thank the following individuals for their many helpful comments on various drafts of this proposal: David Sutton, Peter Millard, Joe Hildebrand, Craig Kaes, Alexey Shchepin, David Waite, Jean-Louis Seguineau, Jacek Konieczny, Gaston Dombiak, and many others in the jdev@conference.jabber.org conference room and on the Standards-JIG mailing list.


Notes

1. RFC 1459: Internet Relay Chat <http://www.ietf.org/rfc/rfc1459.txt>.

2. http://www.jabber.org/protocol/groupchat.html

3. JEP-0030: Service Discovery <http://www.jabber.org/jeps/jep-0030.html>.

4. JEP-0128: Service Discovery Extensions <http://www.jabber.org/jeps/jep-0128.html>.

5. JEP-0091: Delayed Delivery <http://www.jabber.org/jeps/jep-0091.html>.

6. JEP-0082: Jabber Date and Time Profiles <http://www.jabber.org/jeps/jep-0082.html>.

7. XMPP IM <http://www.jabber.org/ietf/> (Proposed Standard, RFC number to follow).

8. JEP-0004: Data Forms <http://www.jabber.org/jeps/jep-0004.html>.

9. JEP-0086: Error Condition Mappings <http://www.jabber.org/jeps/jep-0086.html>.

10. 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/>.

11. 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/>.

12. JEP-0068: Field Data Standardization for Data Forms <http://www.jabber.org/jeps/jep-0068.html>.

13. XMPP Core <http://www.jabber.org/ietf/> (Proposed Standard, RFC number to follow).

14. JEP-0022: Message Events <http://www.jabber.org/jeps/jep-0022.html>.


Revision History

Version 1.16 (2004-06-30)

Added example and registry submission for service discovery extension. (psa)

Version 1.15 (2004-06-24)

Removed jabber:iq:browse references; clarified order of presence stanzas sent to new occupant on entering room; specified format of in-room messages (type='groupchat', from='room@service'); clarified allowable attributes in various list-related operations; made admin/owner revocation text and examples consistent with state chart; clarified ownership revocation conflict scenarios; changed the 'muc#owner_inviteonly' field to 'muc#owner_membersonly'; changed attribute order in examples to match XML canonicalization rules; corrected several errors in the schemas. (psa)

Version 1.14 (2004-05-03)

Corrected discovery of registered roomnicks; added note about error to return if nicks are locked down. (psa)

Version 1.13 (2004-03-31)

Fixed an error in the muc#user schema. (psa)

Version 1.12 (2004-03-01)

Corrected a few errors in the examples; added IQ results in order to clarify workflows. (psa)

Version 1.11 (2004-02-05)

Clarified JID matching rules (same as for privacy lists in XMPP IM). (psa)

Version 1.10 (2004-01-07)

Added XMPP error handling; fully specified all conformance terms. (psa)

Version 1.9 (2003-12-14)

Removed protocol for requesting voice in a moderated room (should be performed using Ad-Hoc Commands). (psa)

Version 1.8 (2003-12-04)

Added protocol for requesting voice in a moderated room; added (informational) mapping of IRC commands to MUC protocols. (psa)

Version 1.7 (2003-10-21)

Added room configuration option for restricting presence broadcast to certain roles. (psa)

Version 1.6 (2003-10-03)

Added history management protocol on entering a room. (psa)

Version 1.5 (2003-09-11)

Specified that ban occurs by JID, not roomnick; allowed privileged users to send messages to the room even if not present in the room; added note that service should remove occupant if a delivery-related stanza error occurs; enabled user to disco the room in order to discover registered roomnick; specified that "banning" by domain or regex is a service-level configuration matter and therefore out of scope for MUC; specified that role should be decremented as appropriate if affiliation is lowered; added some clarifying text to room creation workflow; added implementation note about sending an out-of-band message if a user's affiliation changes while the user is not in the room; fixed stringprep references (room nicks use Resourceprep); clarified relationship between Room ID (i.e., node identifier of Room JID, which may be opaque) and natural-language Room Name; specified Field Standardization profile per JEP-0068; defined Jabber Registrar submissions; added schema locations. (psa)

Version 1.4 (2003-02-16)

Added XML schemas. (psa)

Version 1.3 (2003-02-11)

Added reference to nodeprep Internet-Draft. (psa)

Version 1.2 (2003-01-30)

Commented out revision history prior to version 1.0 (too long); clarified business rules regarding when nicks, full JIDs, and bare JIDs are used in reference to roles and affiliations; consistently specified that extended presence information in the muc#user namespace must include the full JID as the value of the 'jid' attribute in all cases; cleaned up text and examples throughout; added open issue regarding syntax of room nicknames. (psa)

Version 1.1 (2002-12-16)

Added protocol for declining an invitation; replaced <created/> element with status code 201; modified the destroy room protocol so that <destroy/> is a child of <query/>; clarified usage of 'nick' attribute when adding members; prohibited use of message events. (psa)

Version 1.0 (2002-11-21)

Per a vote of the Jabber Council, revision 0.23 was advanced to Draft on 2002-11-21. (For earlier revision history, refer to XML source.) (psa)

Version 0.23 (2002-11-06)

Added examples for disco#items queries sent to a room; prohibited 'type' attribute on invite messages sent from client to room; added dependencies for JEPs 11 and 30; changed 'room user' to 'occupant'; fixed many small errors throughout. (psa)

Version 0.22 (2002-11-04)

Added example for disco#items; added support for cancellation of room configuration using type='cancel' from JEP-0004; noted 403 error for invites sent by non-admins in members-only room. (psa)

Version 0.21 (2002-11-01)

Clarified several small ambiguities; made <body/> optional on invites sent from the service to the invitee; added error scenarios for changing nickname and for destroying the room; specified that the service must return the full member list for a members-only room (not only the members in the room); updated the disco examples to track protocol changes. (psa)

Version 0.20 (2002-10-29)

Specified that messages sent to change the room subject must be of type "groupchat"; updated the legal notice to conform to the JSF IPR policy. (psa)

Version 0.19 (2002-10-28)

Added ability to create an instant room within MUC (not by using gc-1.0 protocol); cleaned up disco examples. (psa)

Version 0.18 (2002-10-27)

Added experimental support for disco; added sections for security, IANA, and JANA considerations; corrected typographical errors; cleaned up some DocBook formatting. (psa)

Version 0.17 (2002-10-23)

Added the optional <actor/> element (with 'jid' attribute) to <item/> elements inside presence stanzas of type "unavailable" that are sent to users who are kicked or banned, as well as within IQs for tracking purposes; reverted all list editing use cases (ban, voice, member, moderator, admin, owner) to use of MUC format rather than 'jabber:x:data' namespace; added several guidelines regarding generation and handling of XML stanzas; cleaned up the change room subject use case; changed several ambiguous uses of 'would', 'can', and 'will' to 'should', 'may', or 'must'; fixed several small errors in the text, examples, and DTDs. (psa)

Version 0.16 (2002-10-20)

Added the <item/> element to presence stanzas of type "unavailable" in order to improve the tracking of user states in the room; consolidated <invitee/> and <inviter/> elements into an <invite/> element with 'from' and 'to' attributes; made <reason/> element always a child of <item/> or <invite/> in the muc#user namespace; moved the alternate room location in room destruction to a 'jid' attribute of the <alt/> element; further specified several error messages; disallowed simultaneous modifications of both affiliations and roles by a moderator or admin; added several more rules regarding handling of XML stanzas; added use cases for granting and revoking administrative privileges; adjusted DTD to track all changes. (psa)

Version 0.15 (2002-10-18)

Fully incorporated the change to affiliations + roles; moved a number of admin use cases to a new section for moderator use cases; added participant use case for requesting membership; added admin use cases for adding members, removing members, granting and revoking moderator privileges, and modifying the moderator list; organized the sections in a more logical manner. (psa)

Version 0.14 (2002-10-17)

Significantly modified the privileges model by distinguishing between in-room "roles" and long-lived "affiliations"; specified the privileges of the various roles and affiliations; included state transition charts for both roles and affiliations; removed use of MUC protocol for editing ban, voice, and admin lists (but not for the actions of banning users and granting/revoking voice); added delivery rule regarding IQ stanzas; changed kick so that the action is based on changing the role to "none". (psa)

Version 0.13 (2002-10-16)

Corrected the change nickname examples (newnick sent on unavailable, no nick sent on available). (psa)

Version 0.12 (2002-10-16)

Removed SHA1 passwords; specified that room shall add passwords on invitations to password-protected rooms (not supplied by inviter). (psa)

Version 0.11 (2002-10-16)

Changed 'participant' to 'room user' and 'discussant' to 'participant'; clarified presence rule about client generation of extended presence information; added role of 'none'. (psa)

Version 0.10 (2002-10-15)

Fixed extended presence on entering or creating a room (plain '...muc' with no fragment); harmonized #user with #admin regarding the use of the <item/> element and associated attributes (jid, nick, etc.), and added 'role' attribute; modified management of voice, ban, admin, and member lists to use <query/> wrapper and new <item/> structure; changed the 'member' role to 'discussant', added 'outcast' role for banned users, and added new 'member' role to enable management of member lists; changed invitation-only rooms to members-only rooms and made appropriate adjustments to apply member lists to both members-only rooms and open rooms; modified nickname change protocol slightly to send the old nickname in the unavailable presence and the new nickname in the available presence; removed prohibition on members-only rooms that are password-protected; removed the <query/> wrapper for the <destroy/> element; updated the DTDs. (psa)

Version 0.9 (2002-10-13)

Added extended presence ('...#user') on entering a room for compliant clients; changed namespace on room creation request to '...#owner'; added a service discovery example using jabber:iq:browse; added information about discussion history; made small fixes to several examples; further defined the presence rules; transferred all implementation notes to a dedicated section; added a Terminology section. (psa)

Version 0.8 (2002-10-10)

Made further changes to the room creation workflow (finally correct); removed feature discovery use case (this needs to be addressed by a real service discovery protocol!); added ability for room owners to edit the admin list; removed <body/> from invitations generated by the service; removed messages sent to kicked and banned users (handled by unavailable presence with status code); added a number of implementation notes; converted all examples to Shakespeare style. (psa)

Version 0.7.6 (2002-10-09)

Fixed the room creation workflow; changed some terminology ("join" to "enter" and "leave" to "exit"). (psa)

Version 0.7.5 (2002-10-08)

Specified and improved the handling of invitation-only rooms. In particular, added the ability for room admins to edit the invitation list and added a configuration option that limits the ability to send invitations to room admins only. (psa)

Version 0.7.4 (2002-10-07)

Changed namespaces from http://jabber.org/protocol/muc/owner etc. to http://jabber.org/protocol/muc#owner etc. per Jabber Council discussion. (psa)

Version 0.7.3 (2002-10-07)

Changed namespaces to HTTP URIs; left role handling up to the implementation; further clarified presence rules. (psa)

Version 0.7.2 (2002-10-06)

Disallowed kicking, banning, and revoking voice with respect to room admins and room owners; replaced <x/> with <query/> in the Discovering Room Features and Destroying a Room use cases; corrected some small errors and made many clarifications throughout. (psa)

Version 0.7.1 (2002-10-04)

Removed <whois/> command (unnecessary since participants with appropriate privileges receive the full JID of all participants in presence stanzas); completed many small fixes throughout. (psa)

Version 0.7 (2002-10-03)

More clearly delineated participant roles and defined the hierarchy thereof (owner, admin, member, visitor); replaced <voice/> element in extended presence with <item role='member'/>; changed initial room configuration to use IQ rather than message; adjusted presence rules (especially regarding extended presence information); cleaned up examples throughout; updated DTD to track changes. (psa)

Version 0.6 (2002-09-21)

More clearly defined the scope; removed fully anonymous rooms; changed meaning of semi-anonymous rooms and of non-anonymous rooms; added mechanism for notification of full JIDs in non-anonymous rooms; replaced the <admin/> element in extended presence with a <role/> element (more extensible); changed room passwords to cleartext; added status codes for various messages received from the service; added lists of valid error and status codes associated with the 'http://jabber.org/protocol/muc#user' namespace; added a <reason/> element for invitations; made kick and ban reasons child elements rather than attributes; replaced stopgap feature discovery mechanism with jabber:iq:negotiate; added extended presence element to room creation request and clarified the room creation process; specified presence reflection rules; added method for destroying a room; adjusted DTDs to track all changes. (psa)

Version 0.5.1 (2002-09-20)

Added DTDs; changed feature discovery to use <x/> element rather than query and made service response come in IQ result; fixed reference to JEP 29; changed 'grant' to 'add' and 'revoke' to 'remove' for consistency in the item attributes; made several other small changes. (psa)

Version 0.5 (2002-09-19)

Changed the kick, ban, and voice protocols; added a few more configuration options; specified the restrictions for roomnicks; and added a stopgap service discovery protocol. (psa)

Version 0.4 (2002-09-18)

Changed all non-GC-1.0 use cases to jabber:gc:* namespaces or jabber:x:data; added use cases for ban list management and room moderation; added protocol for sending notice of admin and voice privileges in presence; cleaned up text and many examples. (psa)

Version 0.3 (2002-09-17)

Changed admin use cases; cleaned up participant and owner use cases. (psa)

Version 0.2 (2002-09-12)

Broke content out into three actors (participant, owner, and admin) and added more detail to owner and admin use cases. (psa)

Version 0.1 (2002-09-09)

Initial version. (psa)


END