This commit is contained in:
stpeter 2011-09-30 21:21:02 -06:00
parent 28dee81da2
commit 8a1d07e9a7
1 changed files with 124 additions and 68 deletions

View File

@ -2,8 +2,8 @@
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
<!ENTITY ROOM "&lt;room@service&gt;">
<!ENTITY ROOMJID "&lt;room@service/nick&gt;">
<!ENTITY ROOMJID "&lt;room@service&gt;">
<!ENTITY OCCUPANTJID "&lt;room@service/nick&gt;">
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
@ -47,8 +47,8 @@
<registry/>
&stpeter;
<revision>
<version>1.25rc6</version>
<date>in progress, last updated 2011-09-19</date>
<version>1.25rc7</version>
<date>in progress, last updated 2011-09-30</date>
<initials>psa</initials>
<remark>
<ul>
@ -61,6 +61,7 @@
<li>Corrected delayed delivery examples so that the 'from' address is that of the room.</li>
<li>Added 'id' attributes to most examples, especially message and presence stanzas generated by the room since IDs can be used for tracking purposes and ghost detection.</li>
<li>Added term "Occupant JID" to differentiate between the JID of a &lt;room@service&gt; and the JID of a &lt;room@service/nick&gt;.</li>
<li>Added "muc#maxhistoryfetch" form field.</li>
<li>Removed feature for requesting a unique room name (the client can simply use a UUID).</li>
<li>Removed any mention of fully-anonymous rooms, which are not supported by this specification.</li>
<li>Clarified many small points in the text and examples.</li>
@ -411,7 +412,7 @@
<version>0.4</version>
<date>2002-09-18</date>
<initials>psa</initials>
<remark><p>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.</p></remark>
<remark><p>Changed all non-groupchat-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.</p></remark>
</revision>
<revision>
<version>0.3</version>
@ -433,7 +434,7 @@
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>Traditionally, instant messaging is thought to consist of one-to-one chat rather than many-to-many chat, which is called variously "groupchat" or "text conferencing". Groupchat functionality is familiar from systems such as Internet Relay Chat (IRC) and the chatroom functionality offered by popular consumer IM services. The Jabber/XMPP community developed and implemented a basic groupchat protocol as long ago as 1999. That "groupchat 1.0" (GC) protocol provided a minimal feature set for chat rooms but was rather limited in scope. This specification (Multi-User Chat or MUC) builds on the older GC protocol in a backwards-compatible manner but provides advanced features such as invitations, room moderation and administration, and specialized room types.</p>
<p>Traditionally, instant messaging is thought to consist of one-to-one chat rather than many-to-many chat, which is called variously "groupchat" or "text conferencing". Groupchat functionality is familiar from systems such as Internet Relay Chat (IRC) and the chatroom functionality offered by popular consumer IM services. The Jabber/XMPP community developed and implemented a basic groupchat protocol as long ago as 1999. That "groupchat 1.0" (GC) protocol provided a minimal feature set for chat rooms but was rather limited in scope. This specification (Multi-User Chat or MUC) builds on the older groupchat 1.0 protocol in a backwards-compatible manner but provides advanced features such as invitations, room moderation and administration, and specialized room types.</p>
</section1>
<section1 topic='Scope' anchor='scope'>
@ -452,14 +453,14 @@
</section1>
<section1 topic='Requirements' anchor='reqs'>
<p>This document addresses the minimal functionality provided by Jabber-based multi-user chat services that existed in 2002 when development of MUC began. For the sake of backwards-compatibility, this document uses the original GC protocol for this baseline functionality, with the result that:</p>
<p>This document addresses the minimal functionality provided by Jabber-based multi-user chat services that existed in 2002 when development of MUC began. For the sake of backwards-compatibility, this document uses the original groupchat 1.0 protocol for this baseline functionality, with the result that:</p>
<ul>
<li>Each room is identified as &ROOM; (e.g., &lt;jdev@conference.jabber.org&gt;), where "room" is the name of the room and "service" is the hostname at which the multi-user chat service is running.</li>
<li>Each occupant in a room is identified as &ROOMJID;, where "nick" is the room nickname of the occupant as specified on entering the room or subsequently changed during the occupant's visit.</li>
<li>A user enters a room (i.e., becomes an occupant) by sending directed presence to &ROOMJID;.</li>
<li>Each room is identified as &ROOMJID; (e.g., &lt;jdev@conference.jabber.org&gt;), where "room" is the name of the room and "service" is the hostname at which the multi-user chat service is running.</li>
<li>Each occupant in a room is identified as &OCCUPANTJID;, where "nick" is the room nickname of the occupant as specified on entering the room or subsequently changed during the occupant's visit.</li>
<li>A user enters a room (i.e., becomes an occupant) by sending directed presence to &OCCUPANTJID;.</li>
<li>An occupant can change his or her room nickname and availability status within the room by sending presence information to &lt;room@service/newnick&gt;.</li>
<li>Messages sent within multi-user chat rooms are of a special type "groupchat" and are addressed to the room itself (room@service), then reflected to all occupants.</li>
<li>An occupant exits a room by sending presence of type "unavailable" to its current &ROOMJID;.</li>
<li>An occupant exits a room by sending presence of type "unavailable" to its current &OCCUPANTJID;.</li>
</ul>
<p>The additional features and functionality addressed in MUC include the following:</p>
<ol start='1'>
@ -818,7 +819,7 @@
<p>Support for the owner affiliation is REQUIRED. Support for the admin, member, and outcast affiliations is RECOMMENDED. (The "None" affiliation is the absence of an affiliation.)</p>
<p>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, not the nick (and thus implicitly the full JID) as with roles.</p>
<p>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 (i.e., a service does not maintain a "none list" across visits).</p>
<p>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).</p>
<p>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 register with an open room and thus be lastingly associated with that room in some way (e.g., the user's nickname is reserved in the room).</p>
<p>An outcast is a user who has been banned from a room and who is not allowed to enter the room.</p>
<p>Information about affiliations MUST be sent in all presence stanzas generated or reflected by the room and sent to occupants (if the room is configured to broadcast presence from entities with a given role).</p>
<section3 topic='Privileges' anchor='affil-priv'>
@ -1157,6 +1158,10 @@
label='URL for discussion logs'>
<value>http://www.shakespeare.lit/chatlogs/coven/</value>
</field>
<field var='muc#maxhistoryfetch'
label='Maximum Number of History Messages Returned by Room'>
<value>50</value>
</field>
<field var='muc#roominfo_pubsub'
label='Associated pubsub node'>
<value>xmpp:pubsub.shakespeare.lit?;node=the-coven-node</value>
@ -1204,7 +1209,7 @@
</section2>
<section2 topic='Querying a Room Occupant' anchor='disco-occupant'>
<p>If a non-occupant attempts to send a disco request to an address of the form &ROOMJID;, a MUC service MUST return a &badrequest; error. If an occupant sends such a request, the service MAY pass it through the intended recipient; see the <link url='#impl'>Implementation Guidelines</link> section of this document for details.</p>
<p>If a non-occupant attempts to send a disco request to an address of the form &OCCUPANTJID;, a MUC service MUST return a &badrequest; error. If an occupant sends such a request, the service MAY pass it through the intended recipient; see the <link url='#impl'>Implementation Guidelines</link> section of this document for details.</p>
</section2>
<section2 topic='Discovering Client Support for MUC' anchor='disco-client'>
@ -1270,9 +1275,9 @@
<section1 topic='Occupant Use Cases' anchor='user'>
<p>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 specification, participants and visitors are considered to be "mere" occupants, since they possess no admin status). As will become clear, the protocol elements proposed in this document to fulfill the occupant use cases fall into three categories:</p>
<ol start='1'>
<li><p>the basic functionality for joining a room, exchanging messages with all occupants, etc. (supported by the GC protocol that preceded MUC)</p></li>
<li><p>the basic functionality for joining a room, exchanging messages with all occupants, etc. (supported by the groupchat 1.0 protocol that preceded MUC)</p></li>
<li><p>straightforward additions to the basic functionality, such as handling of errors related to new room types</p></li>
<li><p>additional protocol elements to handle functionality not covered by GC (room invites, room passwords, extended presence related to room roles and affiliations); these are qualified by the 'http://jabber.org/protocol/muc#user' namespace</p></li>
<li><p>additional 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 qualified by the 'http://jabber.org/protocol/muc#user' namespace</p></li>
</ol>
<p>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 XMPP router or session manager. In addition, normal IQ result stanzas sent upon successful completion of a request (as required by &xmppcore;) are not shown.</p>
<section2 topic='Order of Events' anchor='order'>
@ -1288,8 +1293,8 @@
<section2 topic='Entering a Room' anchor='enter'>
<section3 topic='Groupchat 1.0 Protocol' anchor='enter-gc'>
<p>In order to participate in the discussions held in a multi-user chat room, a user MUST first become an occupant by entering the room. In the old GC protocol, this was done by sending presence to &ROOMJID;, 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:</p>
<example caption='User Seeks to Enter a Room (GC)'><![CDATA[
<p>In order to participate in the discussions held in a multi-user chat room, a user MUST first become an occupant by entering the room. In the old groupchat 1.0 protocol, this was done by sending presence with no 'type' attribute to &OCCUPANTJID;, 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:</p>
<example caption='User Seeks to Enter a Room (groupchat 1.0)'><![CDATA[
<presence
from='hag66@shakespeare.lit/pda'
id='ng91xs69''
@ -1308,29 +1313,17 @@
</error>
</presence>
]]></example>
<p>Note: The presence stanza used to join a room MUST NOT possess a 'type' attribute, i.e., it must be available presence. For further discussion, see the <link url='#bizrules-presence'>Presence</link> business rules.</p>
</section3>
<section3 topic='Basic MUC Protocol' anchor='enter-muc'>
<p>Compliant multi-user chat services MUST accept the foregoing as a request to enter a room from any client that knows either the GC protocol or the multi-user chat (MUC) protocol; however, MUC clients SHOULD signal their ability to speak the MUC protocol by including in the initial presence stanza an empty &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc' namespace (note the absence of the '#user' fragment):</p>
<p>Compliant multi-user chat services MUST accept the foregoing as a request to enter a room from any client that knows either the groupchat 1.0 protocol or the multi-user chat (MUC) protocol; however, MUC clients SHOULD signal their ability to speak the MUC protocol by including in the initial presence stanza an empty &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc' namespace (note the absence of the '#user' fragment):</p>
<example caption='User Seeks to Enter a Room (Multi-User Chat)'><![CDATA[
<presence
from='hag66@shakespeare.lit/pda'
id='n13mt3l'
to='coven@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'/>
</presence>
]]></example>
<p>Note: If an error occurs in relation to joining a room, the service SHOULD include the MUC child element (i.e., &lt;x xmlns='http://jabber.org/protocol/muc'/&gt;) in the &PRESENCE; stanza of type "error".</p>
<example caption='Room Does Not Exist'><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='n13mt3l'
to='hag66@shakespeare.lit/pda'
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error by='coven@chat.shakespeare.lit' type='cancel'>
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
]]></example>
<p>Before attempting to enter the room, a MUC-compliant client SHOULD first discover its reserved room nickname (if any) by following the protocol defined in the <link url='#reservednick'>Discovering Reserved Room Nickname</link> section of this document.</p>
@ -1649,6 +1642,7 @@
</tr>
</table>
<p>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 'maxchars' attribute to a value of "0" (zero).</p>
<p>Because not all service implementations support MUC history management, a client SHOULD NOT depend on receiving only the history that it has requested.</p>
<p>The following examples illustrate the use of this feature.</p>
<example caption='User Requests Limit on Number of Characters in History'><![CDATA[
<presence
@ -1704,7 +1698,7 @@
</section3>
<section3 topic='Room Subject' anchor='enter-subject'>
<p>After the room has optionally sent the discussion history to the new occupant, it SHALL send the current room subject (if any). This is a &MESSAGE; stanza from the room itself (or from the room JID of the entity that set the subject), with no &BODY; and only a &SUBJECT;, as shown in the following example.</p>
<p>After the room has optionally sent the discussion history to the new occupant, it SHALL send the current room subject (if any). This is a &MESSAGE; stanza from the room itself (or from the room JID of the entity that set the subject), with a &SUBJECT; element but no &BODY; element, as shown in the following example.</p>
<example caption='Service Informs New Occupant of Room Subject'><![CDATA[
<message
from='coven@chat.shakespeare.lit/secondwitch'
@ -1714,7 +1708,17 @@
<subject>Fire Burn and Cauldron Bubble!</subject>
</message>
]]></example>
<p>Note: In accordance with the core definition of XML stanzas, any message can contain a &SUBJECT; element; only a message that contains a &SUBJECT; but no other child elements shall be considered a subject change for MUC purposes.</p>
<p>If there is no subject set, the room SHOULD return an empty &SUBJECT; element.</p>
<example caption='No Subject'><![CDATA[
<message
from='coven@chat.shakespeare.lit/secondwitch'
id='F437C672-D438-4BD3-9BFF-091050D32EE2'
to='crone1@shakespeare.lit/desktop'
type='groupchat'>
<subject></subject>
</message>
]]></example>
<p>Note: In accordance with the core definition of XML stanzas, any message can contain a &SUBJECT; element; only a message that contains a &SUBJECT; but no &BODY; element shall be considered a subject change for MUC purposes.</p>
</section3>
<section3 topic='Live Messages' anchor='enter-live'>
@ -1770,7 +1774,7 @@
</section2>
<section2 topic='Sending a Message to All Occupants' anchor='message'>
<p>An occupant sends a message to all other occupants in the room by sending a message of type "groupchat" to the &ROOM; itself (a service MAY ignore or reject messages that do not have a type of "groupchat"). In a moderated room, this privilege is restricted to occupants with a role of participant or higher.</p>
<p>An occupant sends a message to all other occupants in the room by sending a message of type "groupchat" to the &ROOMJID; 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.</p>
<example caption='Occupant Sends a Message to All Occupants'><![CDATA[
<message
from='hag66@shakespeare.lit/pda'
@ -1941,6 +1945,26 @@
role='participant'/>
<status code='110'/>
</x>
</presence>
]]></example>
<p>If the service modifies the user's nickname in accordance with local service policies, it MUST include a MUC status code of 210 in the presence stanza sent to the user. An example follows (here the service changes the nickname to all lowercase).</p>
<example caption='Occupant Changes Nickname, Modified by Service'><![CDATA[
<presence
from='hag66@shakespeare.lit/pda'
id='nx6z2v5'
to='coven@chat.shakespeare.lit/OldHag'/>
<presence
from='coven@chat.shakespeare.lit/oldhag'
id='D0E2B666-3373-42C9-B726-D52C40A48383'
to='hag66@shakespeare.lit/pda'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
role='participant'/>
<status code='110'/>
<status code='210'/>
</x>
</presence>
]]></example>
<p>If the user attempts to change his or her room nickname to a room nickname that is already in use by another user (or that is reserved by another user 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:</p>
@ -1974,7 +1998,7 @@
</section2>
<section2 topic='Changing Availability Status' anchor='changepres'>
<p>In text 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 XMPP, availability is of course noted by a change in presence (specifically the &lt;show/&gt; and &lt;status/&gt; elements), which can provide important context within a chatroom. An occupant changes availability status within the room by sending updated presence to its &ROOMJID;.</p>
<p>In text 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 XMPP, availability is of course noted by a change in presence (specifically the &lt;show/&gt; and &lt;status/&gt; elements), which can provide important context within a chatroom. An occupant changes availability status within the room by sending updated presence to its &OCCUPANTJID;.</p>
<example caption='Occupant Changes Availability Status'><![CDATA[
<presence
from='wiccarocks@shakespeare.lit/laptop'
@ -2013,7 +2037,7 @@
</section3>
<section3 topic='Mediated Invitation' anchor='invite-mediated'>
<p>It can be useful to invite another user to a room in which one is an occupant. To send a mediated invitation, a MUC client MUST send XML of the following form to the &ROOM; itself (the reason is OPTIONAL and the message MUST be explicitly or implicitly of type "normal"):</p>
<p>It can be useful to invite another user to a room in which one is an occupant. To send a mediated invitation, a MUC client MUST send XML of the following form to the &ROOMJID; itself (the reason is OPTIONAL and the message MUST be explicitly or implicitly of type "normal"):</p>
<example caption='Occupant Sends a Mediated Invitation'><![CDATA[
<message
from='crone1@shakespeare.lit/desktop'
@ -2028,7 +2052,7 @@
</x>
</message>
]]></example>
<p>The &ROOM; itself MUST then add a 'from' address to the &lt;invite/&gt; element whose value is the bare JID, full JID, or room JID of the inviter and send the invitation to the invitee specified in the 'to' address; the room SHOULD add the password if the room is password-protected):</p>
<p>The &ROOMJID; itself MUST then add a 'from' address to the &lt;invite/&gt; element whose value is the bare JID, full JID, or room JID of the inviter and send the invitation to the invitee specified in the 'to' address; the room SHOULD add the password if the room is password-protected):</p>
<example caption='Room Sends Invitation to Invitee on Behalf of Invitor'><![CDATA[
<message
from='coven@chat.shakespeare.lit'
@ -2046,7 +2070,7 @@
]]></example>
<p>If the room is members-only, the service MAY also add the invitee to the member list. (Note: 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 <link url='#modifymember'>Modifying the Member List</link> section of this document.)</p>
<p>If the inviter supplies a non-existent JID, the room SHOULD return an &notfound; error to the inviter.</p>
<p>The invitee MAY choose to formally decline (as opposed to ignore) the invitation; and this is something that the sender might 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:</p>
<p>The invitee MAY choose to formally decline (as opposed to ignore) the invitation; and this is something that the sender might want to be informed about. In order to decline the invitation, the invitee MUST send a message of the following form to the &ROOMJID; itself:</p>
<example caption='Invitee Declines Invitation'><![CDATA[
<message
from='hecate@shakespeare.lit/broom'
@ -2247,7 +2271,7 @@
</section2>
<section2 topic='Registering with a Room' anchor='register'>
<p>An implementation MAY allow an unaffiliated user (in a moderated room, normally 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). In particular, it is not possible to join a members-only room without being on the member list, so an entity might need to request membership in order to join such a room.</p>
<p>An implementation MAY allow an unaffiliated user (in a moderated room, normally a participant) to register with a room; as a result, the user will become a member of the room and will have their preferred nickname reserved in the room. (Conversely, an implementation MAY restrict this privilege and allow only room admins to add new members.) In particular, it is not possible to join a members-only room without being on the member list, so an entity might need to request membership in order to join such a room.</p>
<p>If allowed, this functionality SHOULD be implemented by enabling a user to send a request for registration requirements to the room qualified by the 'jabber:iq:register' namespace as described in &xep0077;:</p>
<example caption='User Requests Registration Requirements'><![CDATA[
<iq from='hag66@shakespeare.lit/pda'
@ -2419,7 +2443,8 @@
to='hag66@shakespeare.lit/pda'
type='result'/>
]]></example>
<p>After the user submits the form, the service MAY request that the submission be approved by a room admin/owner (see the <link url='#regapprove'>Approving Registration Requests</link> section of this document), MAY immediately add the user to the member list by changing the user's affiliation from "none" to "member", or MAY perform some service-specific checking (e.g., email verification). 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 &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an &lt;item/&gt; child with the 'affiliation' attribute set to a value of "member".</p>
<p>After the user submits the form, the service MAY request that the submission be approved by a room admin/owner (see the <link url='#regapprove'>Approving Registration Requests</link> section of this document), MAY immediately add the user to the member list by changing the user's affiliation from "none" to "member", or MAY perform some service-specific checking (e.g., email verification).</p>
<p>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 &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an &lt;item/&gt; child with the 'affiliation' attribute set to a value of "member".</p>
<example caption="Service Sends Notice of Membership to All Occupants"><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
@ -2433,6 +2458,7 @@
[ ... ]
]]></example>
<p>If the user's nickname is modified by the service as a result of registration and the user is in the room, the service SHOULD include status code "210" in the updated presence notification that it sends to all users.</p>
<p>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 &notacceptable; error to the user if the user attempts to join the room with a roomnick other than the user's registered roomnick (this enables a room to "lock down" roomnicks for consistent identification of occupants).</p>
</section2>
@ -2493,7 +2519,7 @@
</section2>
<section2 topic='Exiting a Room' anchor='exit'>
<p>In order to exit a multi-user chat room, an occupant sends a presence stanza of type "unavailable" to the &ROOMJID; it is currently using in the room.</p>
<p>In order to exit a multi-user chat room, an occupant sends a presence stanza of type "unavailable" to the &OCCUPANTJID; it is currently using in the room.</p>
<example caption='Occupant Exits a Room'><![CDATA[
<presence
from='hag66@shakespeare.lit/pda'
@ -2514,6 +2540,7 @@
</x>
</presence>
]]></example>
<p>Note: The presence stanza used to exit a room MUST possess a 'type' attribute whose value is "unavailable". For further discussion, see the <link url='#bizrules-presence'>Presence</link> business rules.</p>
<p>The service MUST then send presence stanzas of type "unavailable" from the departing occupant's room JID to the full JIDs of the remaining occupants:</p>
<example caption='Service Sends Presence Related to Departure of Occupant'><![CDATA[
<presence
@ -2558,7 +2585,7 @@
<status>gone where the goblins go</status>
</presence>
]]></example>
<p>Normal presence stanza generation rules apply as defined in &xmppim;, so that if the user sends a general unavailable presence stanza, the user's server will broadcast that stanza to the client's &ROOMJID;; as a result, there is no need for the leaving client to send directed unavailable presence to its room JID. It is possible that a user might not be able to gracefully exit the room by sending unavailable presence. If the user goes offline without sending unavailable presence, the user's server is responsible for sending unavailable presence on behalf of the user (in accordance with <cite>RFC 6121</cite>).</p>
<p>Normal presence stanza generation rules apply as defined in &xmppim;, so that if the user sends a general unavailable presence stanza, the user's server will broadcast that stanza to the client's &OCCUPANTJID;; as a result, there is no need for the leaving client to send directed unavailable presence to its room JID. It is possible that a user might not be able to gracefully exit the room by sending unavailable presence. If the user goes offline without sending unavailable presence, the user's server is responsible for sending unavailable presence on behalf of the user (in accordance with <cite>RFC 6121</cite>).</p>
<p>Note: See <link url='#impl-service-ghosts'>Ghost Users</link> for suggestions regarding room occupants that appear to be present in the room but that are actually offline.</p>
<p>Note: If the room is not persistent and this occupant is the last to exit, the service is responsible for destroying the room.</p>
</section2>
@ -2577,7 +2604,10 @@
<p>These features are implemented with a request/response exchange using &lt;iq/&gt; elements that contain child elements qualified 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 &lt;user@host&gt; of the 'from' address of the request does not match the bare JID portion of one of the moderators; in this case, the service MUST return a &forbidden; error.)</p>
<section2 topic='Modifying the Room Subject' anchor='subject-mod'>
<p>A common feature of multi-user chat rooms is the ability to change the subject within the room. By default, only users with a role of "moderator" SHOULD be allowed to change the subject in a room (although this is configurable, with the result that a mere participant or even visitor might be allowed to change the subject, as controlled by the "muc#roomconfig_changesubject" option). The subject is changed by sending a message of type "groupchat" to the &ROOM;, where the &MESSAGE; MUST contain a &lt;subject/&gt; element that specifies the new subject but MUST NOT contain any other element (e.g., no &BODY; element or &THREAD; element). (A message with a &SUBJECT; and a &BODY; is a legitimate message, but it SHALL NOT be interpreted as a subject change.)</p>
<p>A common feature of multi-user chat rooms is the ability to change the subject within the room.</p>
<p>By default, only users with a role of "moderator" SHOULD be allowed to change the subject in a room (although this is configurable, with the result that a mere participant or even visitor might be allowed to change the subject, as controlled by the "muc#roomconfig_changesubject" option).</p>
<p>The subject is changed by sending a message of type "groupchat" to the &ROOMJID;, where the &MESSAGE; MUST contain a &lt;subject/&gt; element that specifies the new subject but MUST NOT contain a &BODY; element (or a &THREAD; element). In accordance with the core definition of XMPP, other child elements are allowed (although the entity that receives them might ignore them).</p>
<p>Note: A message with a &SUBJECT; and a &BODY; or a &SUBJECT; and a &THREAD; is a legitimate message, but it SHALL NOT be interpreted as a subject change.</p>
<example caption='Moderator Changes Subject'><![CDATA[
<message
from='wiccarocks@shakespeare.lit/laptop'
@ -2643,7 +2673,7 @@
</query>
</iq>
]]></example>
<p>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.</p>
<p>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 roomnick or bare JID of the user who initiated the kick.</p>
<example caption='Service Removes Kicked Occupant'><![CDATA[
<presence
from='harfleur@chat.shakespeare.lit/pistol'
@ -2666,7 +2696,7 @@
to='fluellen@shakespeare.lit/pda'
type='result'/>
]]></example>
<p>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 individual's roomnick (&ROOMJID;) 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 and actor.</p>
<p>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 individual's roomnick (&OCCUPANTJID;) 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 and actor.</p>
<example caption='Service Informs Remaining Occupants'><![CDATA[
<presence
from='harfleur@chat.shakespeare.lit/pistol'
@ -2728,7 +2758,7 @@
to='crone1@shakespeare.lit/desktop'
type='result'/>
]]></example>
<p>The service MUST then send updated presence from this individual's &ROOMJID; to all occupants, indicating the addition of voice privileges by including an &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an &lt;item/&gt; child with the 'role' attribute set to a value of "participant".</p>
<p>The service MUST then send updated presence from this individual's &OCCUPANTJID; to all occupants, indicating the addition of voice privileges by including an &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an &lt;item/&gt; child with the 'role' attribute set to a value of "participant".</p>
<example caption="Service Sends Notice of Voice to All Occupants"><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
@ -2996,7 +3026,7 @@
to='kinghenryv@shakespeare.lit/throne'
type='result'/>
]]></example>
<p>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.</p>
<p>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 roomnick or bare JID of the user who initiated the ban.</p>
<example caption='Service Removes Banned User'><![CDATA[
<presence
from='southampton@chat.shakespeare.lit/cambridge'
@ -3582,7 +3612,7 @@
<section1 topic='Owner Use Cases' anchor='owner'>
<p>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 document 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. Room owners can specify not only the room types (password-protected, members-only, etc.) but also certain attributes of the room as listed in the <link url='#reqs'>Requirements</link> section of this document. In addition, an owner can also specify the JIDs of other owners, if supported by the implementation.</p>
<p>In order to provide the necessary flexibility for a wide range of configuration options, Data Forms (<cite>XEP-0004</cite>) are used for room configuration, triggered by use of the 'http://jabber.org/protocol/muc' namespace. If an entity does not include the MUC namespace in its room join/create request, then the service shall create the room and not wait for configuration via Data Forms before creating the room (this ensures backwards-compatibility with the old GC protocol); however, if the room join/create request includes the MUC extension, then the service shall require configuration via Data Forms before creating and unlocking the room.</p>
<p>In order to provide the necessary flexibility for a wide range of configuration options, Data Forms (<cite>XEP-0004</cite>) are used for room configuration, triggered by use of the 'http://jabber.org/protocol/muc' namespace. If an entity does not include the MUC namespace in its room join/create request, then the service shall create the room and not wait for configuration via Data Forms before creating the room (this ensures backwards-compatibility with the old groupchat 1.0 protocol); however, if the room join/create request includes the MUC extension, then the service shall require configuration via Data Forms before creating and unlocking the room.</p>
<p>Note: The configuration options shown below address all of the features and room types listed in the requirements section of this document; however, 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 additional configuration options (clearance levels, profanity filters, supported languages, message logging, etc.), which is why the use of the 'jabber:x:data' protocol is valuable here.</p>
<section2 topic='Creating a Room' anchor='createroom'>
<section3 topic='General Considerations' anchor='createroom-general'>
@ -3606,7 +3636,7 @@
</ul>
<p>The workflow for creating and configuring such rooms is as follows:</p>
<ol start='1'>
<li><p>The user sends presence to &ROOMJID; and signal his or her support for the Multi-User Chat protocol by including extended presence information in an empty &lt;x/&gt; child element qualified by the 'http://jabber.org/protocol/muc' namespace (note the lack of an '#owner' or '#user' fragment).</p></li>
<li><p>The user sends presence to &OCCUPANTJID; and signal his or her support for the Multi-User Chat protocol by including extended presence information in an empty &lt;x/&gt; child element qualified by the 'http://jabber.org/protocol/muc' namespace (note the lack of an '#owner' or '#user' fragment).</p></li>
<li><p>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 indicating the user's status as an owner and acknowledging that the room has been created (via status code 201) and is awaiting configuration.</p></li>
<li><p>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 &lt;query/&gt; element qualified 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 qualified by the 'http://jabber.org/protocol/muc#owner' namespace and containing an empty &lt;x/&gt; element of type "submit" qualified by the 'jabber:x:data' namespace, then skip to Step 6.</p></li>
<li><p>If the room owner requested a configuration form, the service MUST send an IQ result to the room owner containing a configuration form qualified by the 'jabber:x:data' namespace. If there are no configuration options available, the room MUST return an empty query element to the room owner.</p></li>
@ -3636,11 +3666,11 @@
</presence>
]]></example>
<p>After receiving notification that the room has been created, the room owner needs to decide whether to accept the default room configuration (i.e., create an "instant room") or configure the room to use something other than the default room configuration (i.e., create a "reserved room"). The protocol flows for completing those two use cases are shown in the following sections.</p>
<p>Note: If the presence stanza sent to a nonexistent room does not include an &X; element qualified by the 'http://jabber.org/protocol/muc' namespace as shown above, the service SHOULD create a default room without delay (i.e., it MUST assume that the client supports GC rather than MUC and therefore it MUST NOT lock the room while waiting for the room creator to either accept an instant room or configure a reserved room).</p>
<p>Note: If the presence stanza sent to a nonexistent room does not include an &X; element qualified by the 'http://jabber.org/protocol/muc' namespace as shown above, the service SHOULD create a default room without delay (i.e., it MUST assume that the client supports groupchat 1.0 rather than MUC and therefore it MUST NOT lock the room while waiting for the room creator to either accept an instant room or configure a reserved room).</p>
</section3>
<section3 topic='Creating an Instant Room' anchor='createroom-instant'>
<p>If the initial room owner wants to accept the default room configuration (i.e., create an "instant room"), the room owner MUST decline an initial configuration form by sending an IQ set to the &ROOM; itself containing a &QUERY; element qualified by the 'http://jabber.org/protocol/muc#owner' namespace, where the only child of the &QUERY; is an empty &X; element that is qualified by the 'jabber:x:data' namespace and that possesses a 'type' attribute whose value is "submit":</p>
<p>If the initial room owner wants to accept the default room configuration (i.e., create an "instant room"), the room owner MUST decline an initial configuration form by sending an IQ set to the &ROOMJID; itself containing a &QUERY; element qualified by the 'http://jabber.org/protocol/muc#owner' namespace, where the only child of the &QUERY; is an empty &X; element that is qualified by the 'jabber:x:data' namespace and that possesses a 'type' attribute whose value is "submit":</p>
<example caption='Owner Requests Instant Room'><![CDATA[
<iq from='crone1@shakespeare.lit/desktop'
id='create1'
@ -3655,7 +3685,7 @@
</section3>
<section3 topic='Creating a Reserved Room' anchor='createroom-reserved'>
<p>If the initial room owner wants to create and configure a reserved room, the room owner MUST request an initial configuration form by sending an IQ get to the &ROOM; itself containing an empty &QUERY; element qualified by the 'http://jabber.org/protocol/muc#owner' namespace:</p>
<p>If the initial room owner wants to create and configure a reserved room, the room owner MUST request an initial configuration form by sending an IQ get to the &ROOMJID; itself containing an empty &QUERY; element qualified by the 'http://jabber.org/protocol/muc#owner' namespace:</p>
<example caption='Owner Requests Configuration Form'><![CDATA[
<iq from='crone1@shakespeare.lit/desktop'
id='create1'
@ -3826,6 +3856,12 @@
<value>anyone</value>
</option>
</field>
<field
label='Maximum Number of History Messages Returned by Room'
type='text-single'
var='muc#maxhistoryfetch'>
<value>50</value>
</field>
<field type='fixed'>
<value>
You may specify additional people who have
@ -3914,6 +3950,9 @@
<field var='muc#roomconfig_whois'>
<value>moderators</value>
</field>
<field var='muc#maxhistoryfetch'>
<value>50</value>
</field>
<field var='muc#roomconfig_roomadmins'>
<value>wiccarocks@shakespeare.lit</value>
<value>hecate@shakespeare.lit</value>
@ -3952,13 +3991,13 @@
</iq>
]]></example>
<p>If the room owner cancels the initial configuration, the service MUST destroy the room, making sure to send unavailable presence to the room owner (see the "Destroying a Room" use case for protocol details).</p>
<p>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 owner's &ROOMJID;. The service MUST then destroy the room, sending a presence stanza of type "unavailable" from the room to the owner including a &lt;destroy/&gt; element and reason (if provided) as defined in the <link url='#destroyroom'>Destroying a Room</link> section of this document.</p>
<p>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 owner's &OCCUPANTJID;. The service MUST then destroy the room, sending a presence stanza of type "unavailable" from the room to the owner including a &lt;destroy/&gt; element and reason (if provided) as defined in the <link url='#destroyroom'>Destroying a Room</link> section of this document.</p>
</section3>
</section2>
<section2 topic='Subsequent Room Configuration' anchor='roomconfig'>
<p>At any time after specifying the initial configuration of the room, a room owner might want to change the configuration. In order to initiate this process, a room owner requests a new configuration form from the room by sending an IQ get to &ROOM; containing an empty &lt;query/&gt; element qualified by the 'http://jabber.org/protocol/muc#owner' namespace.</p>
<p>At any time after specifying the initial configuration of the room, a room owner might want to change the configuration. In order to initiate this process, a room owner requests a new configuration form from the room by sending an IQ get to &ROOMJID; containing an empty &lt;query/&gt; element qualified by the 'http://jabber.org/protocol/muc#owner' namespace.</p>
<example caption='Owner Requests Configuration Form'><![CDATA[
<iq from='crone1@shakespeare.lit/desktop'
id='config1'
@ -4133,6 +4172,12 @@
<value>anyone</value>
</option>
</field>
<field
label='Maximum Number of History Messages Returned by Room'
type='text-single'
var='muc#maxhistoryfetch'>
<value>50</value>
</field>
<field type='fixed'>
<value>
You may specify additional people who have
@ -4175,7 +4220,7 @@
</iq>
]]></example>
<p>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.</p>
<p>If as a result of a change in the room configuration a room admin loses admin status while in the room, the room MUST send updated presence for that individual to all occupants, denoting the change in status by including an &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an &lt;item/&gt; child with the 'affiliation' attribute set to a value of "member" or "non" and the 'role' attribute set to a value of "participant" or "visitor" as appropriate for the affiliation level and the room type:</p>
<p>If as a result of a change in the room configuration a room admin loses admin status while in the room, the room MUST send updated presence for that individual to all occupants, denoting the change in status by including an &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an &lt;item/&gt; child with the 'affiliation' attribute set to a value of "member" or "none" and the 'role' attribute set to a value of "participant" or "visitor" as appropriate for the affiliation level and the room type:</p>
<example caption="Service Notes Loss of Admin Affiliation"><![CDATA[
<presence
from='coven@chat.shakespeare.lit/secondwitch'
@ -4500,14 +4545,14 @@
</section2>
<section2 topic='Revoking Admin Status' anchor='revokeadmin'>
<p>An owner might want to revoke a user's admin status; this is done by changing the user's affiliation to something other than "admin" or "owner".</p>
<p>An owner might want to revoke a user's admin status; this is done by changing the user's affiliation to something other than "admin" or "owner" (typically to "member" in a members-only room or to "none" in other types of room).</p>
<example caption='Owner Revokes Admin Status'><![CDATA[
<iq from='crone1@shakespeare.lit/desktop'
id='admin2'
to='coven@chat.shakespeare.lit'
type='set'>
<query xmlns='http://jabber.org/protocol/muc#admin'>
<item affiliation='member'
<item affiliation='none'
jid='wiccarocks@shakespeare.lit'/>
</query>
</iq>
@ -4519,7 +4564,7 @@
to='coven@chat.shakespeare.lit'
type='set'>
<query xmlns='http://jabber.org/protocol/muc#admin'>
<item affiliation='member'
<item affiliation='none'
jid='wiccarocks@shakespeare.lit'>
<reason>Not so worthy after all!</reason>
</item>
@ -4539,7 +4584,7 @@
from='coven@chat.shakespeare.lit/secondwitch'
to='crone1@shakespeare.lit/desktop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
<item affiliation='none'
jid='wiccarocks@shakespeare.lit'
role='participant'/>
</x>
@ -4554,7 +4599,7 @@
id='2CF9013B-E8A8-42A1-9633-85AD7CA12F40'
to='crone1@shakespeare.lit/desktop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
<item affiliation='none'
jid='wiccarocks@shakespeare.lit'
role='none'/>
</x>
@ -4724,7 +4769,7 @@
<p>As specified in <cite>RFC 6120</cite>, XMPP entities (including MUC rooms and MUC services) SHOULD respect the value of the 'xml:lang' attribute provided with any given stanza. However, simultaneous translation of groupchat messages is out of scope for this document (see &xep0171;).</p>
<p>The status and error codes defined herein enable a client implementation to present a localized interface; however, definition of the localized text strings for any given language community is out of scope for this document.</p>
<p>Although the labels for various data form fields are shown here in English, MUC clients SHOULD present localized text for these fields rather than the English text.</p>
<p>Nicknames can contain virtually any Unicode character introduces the possibility of nick spoofing; see &rfc6122; for a description of related security considerations.</p>
<p>Nicknames can contain virtually any Unicode character. This introduces the possibility of nick spoofing; see &rfc6122; for a description of related security considerations.</p>
</section1>
<section1 topic='Security Considerations' anchor='security'>
@ -4777,7 +4822,7 @@
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
<p>The &REGISTRAR; includes the following information in its registries.</p>
<section2 topic='Protocol Namespaces' anchor='registrar-protocol'>
<p>The XMPP Registrar includes the following MUC-related namespaces in its registry of protocol namespaces:</p>
<p>The XMPP Registrar includes the following MUC-related namespaces in its registry of protocol namespaces at &NAMESPACES;:</p>
<ul>
<li>http://jabber.org/protocol/muc</li>
<li>http://jabber.org/protocol/muc#admin</li>
@ -4961,6 +5006,10 @@
Forms enabling creation and configuration of
a Multi-User Chat (MUC) room.
</desc>
<field
var='muc#maxhistoryfetch'
type='text-single'
label='Maximum Number of History Messages Returned by Room'/>
<field
var='muc#roomconfig_allowinvites'
type='boolean'
@ -5054,6 +5103,10 @@
Forms enabling the communication of extended service discovery
information about a Multi-User Chat (MUC) room.
</desc>
<field
var='muc#maxhistoryfetch'
type='text-single'
label='Maximum Number of History Messages Returned by Room'/>
<field
var='muc#roominfo_contactjid'
type='jid-multi'
@ -5099,7 +5152,7 @@
<section2 topic='Status Codes Registry' anchor='registrar-statuscodes'>
<section3 topic='Process' anchor='registrar-statuscodes-process'>
<p>The XMPP Registrar maintains a registry of values for the 'code' attribute of the &lt;status/&gt; element when qualified by the 'http://jabber.org/protocol/muc#user' namespace.</p>
<p>The XMPP Registrar maintains a registry at &MUCSTATUS; that defines values for the 'code' attribute of the &lt;status/&gt; element when qualified by the 'http://jabber.org/protocol/muc#user' namespace.</p>
&REGPROCESS;
<code><![CDATA[
<statuscode>
@ -5217,7 +5270,7 @@
<statuscode>
<number>210</number>
<stanza>presence</stanza>
<context>Entering a room</context>
<context>Entering a room, changing nickname, etc.</context>
<purpose>
Inform user that service has assigned or modified occupant's roomnick
</purpose>
@ -5392,7 +5445,7 @@ xmpp:coven@chat.shakespeare.lit?invite;jid=hecate@shakespeare.lit;password=cauld
<section1 topic='Business Rules' anchor='bizrules'>
<section2 topic='Addresses' anchor='bizrules-jids'>
<p>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 &rfc3920;). As explicitly stated in <cite>RFC 6120</cite>, both the Room ID (node) and Room Nickname (resource) portions of an Occupant JID MUST be of non-zero length. In addition, a MUC service MUST NOT allow empty or invisible Room Nicknames (i.e., Room Nicknames that consist only of one or more space characters).</p>
<p>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 <cite>RFC 6122</cite>). As explicitly stated in <cite>RFC 6122</cite>, both the Room ID (node) and Room Nickname (resource) portions of an Occupant JID MUST be of non-zero length. In addition, a MUC service MUST NOT allow empty or invisible Room Nicknames (i.e., Room Nicknames that consist only of one or more space characters).</p>
<p>It is up to the service implementation whether it will further restrict roomnicks (e.g., by applying case folding routines, the Nodeprep profile of stringprep, or other restrictions).</p>
</section2>
@ -5408,13 +5461,16 @@ xmpp:coven@chat.shakespeare.lit?invite;jid=hecate@shakespeare.lit;password=cauld
<section2 topic='Presence' anchor='bizrules-presence'>
<ol start='1'>
<li><p>The presence stanza used to join a room MUST NOT possess a 'type' attribute, i.e., it must be available presence. A MUC service MUST NOT treat a presence stanza with a 'type' attribute (e.g., a presence probe) as a request to join the room.</p></li>
<li><p>The presence stanza used to exit a room MUST possess a 'type' attribute whose value is "unavailable". A MUC service MUST NOT treat a presence stanza with a 'type' attribute whose value is other than "unavailable" (e.g., a presence probe) as a request to exit the room.</p></li>
<li><p>A MUC service MAY handle presence probes sent to the room JID &ROOMJID; or an occupant JID &OCCUPANTJID; (e.g, these might be sent by an occupant's home server to determine if the room is still online or to synchronize presence information if the user or the user's server has gone offline temporarily or has started sharing presence again, as for instance when &xep0273; is used).</p></li>
<li><p>A room MUST silently ignore unavailable presence received from a user who has a role of "none".</p></li>
<li><p>Only the MUC service itself SHOULD generate data about roles, affiliations, full JIDs, or status codes qualified by the 'http://jabber.org/protocol/muc#user' namespace (based on information the service 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 MUC service receives such extended presence information from an occupant, it MUST NOT reflect it to other occupants. (A client MAY generate extended presence information qualified by the 'http://jabber.org/protocol/muc#user' namespace in order to supply a password, but naturally this is not reflected to other occupants.)</p></li>
<li><p>A MUC service SHOULD allow all other presence information to pass through, although it MAY choose to block extended presence information; see the <link url='#impl-service-traffic'>Allowable Traffic</link> section of this document.</p></li>
<li><p>In order to inform occupants of room roles and affiliations, and to make it easier for clients to track the current state of all users in the room, MUC service implementations MUST provide role and affiliation data (and, if allowed by the room configuration, full JID) in all presence stanzas, including presence stanzas of type "unavailable" sent when a user exits the room for any reason.</p></li>
<li><p>If a role or affiliation is revoked, the service MUST note that fact by sending an &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an &lt;item/&gt; child element with the 'role' and/or 'affiliation' attributes set to a value that indicates the loss of the relevant status. All future presence stanzas for the occupant MUST include the updated role and affiliation, until and unless they change again.</p></li>
<li><p>A MUC service MUST include the MUC extensions even if the client did not send an empty &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc' namespace on entering the room; naturally, a client MUST ignore such information if it does not understand it (in accordance with <cite>RFC 6120</cite>).</p></li>
<li><p>If the service includes an occupant's JabberID in the MUC presence extension, the value of hte 'jid' attribute MUST be the full JID (not the bare JID).</p></li>
<li><p>If the service includes an occupant's JabberID in the MUC presence extension, the value of the 'jid' attribute MUST be the full JID (not the bare JID).</p></li>
<li><p>A client MAY send a custom exit message if desired (as is often done in IRC channels) by including a &lt;status/&gt; element in the presence stanza of type "unavailable" sent when <link url='#exit'>exiting a room</link>.</p></li>
</ol>
</section2>
@ -5438,7 +5494,7 @@ xmpp:coven@chat.shakespeare.lit?invite;jid=hecate@shakespeare.lit;password=cauld
<ol start='1'>
<li><p>In handling messages sent by visitors in a moderated room, a MUC 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 <cite>XEP-0004</cite>) is out of scope for this document.</p></li>
<li><p>Out of courtesy, a MUC service MAY send an out-of-room &lt;message/&gt; 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 &lt;body/&gt; element describing the affiliation change, and MUST contain a status code of 101.</p></li>
<li><p>There is no requirement that a MUC service shall provide special treatment for users of the older GC protocol, such as messages that contain equivalents to the extended presence information that is qualified by the 'http://jabber.org/protocol/muc#user' namespace.</p></li>
<li><p>There is no requirement that a MUC 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 qualified by the 'http://jabber.org/protocol/muc#user' namespace.</p></li>
<li><p>Room types MAY be configured in any combination. A MUC service MAY support or allow any desired room types or combinations thereof. There is no guarantee that any such combination is sensible.</p></li>
<li><p>A MUC 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.</p></li>
<li><p>A MUC service MAY provide an interface to room creation and configuration (e.g., in the form of a special XMPP entity or a Web page), so that the ostensible room owner is actually the application instead of a human user.</p></li>
@ -5680,7 +5736,7 @@ xmpp:coven@chat.shakespeare.lit?invite;jid=hecate@shakespeare.lit;password=cauld
<xs:element ref='decline' minOccurs='0'/>
<xs:element ref='destroy' minOccurs='0'/>
<xs:element ref='invite' minOccurs='0' maxOccurs='unbounded'/>
<xs:element ref='item' minOccurs='0'/>
<xs:element ref='item' minOccurs='0' maxOccurs='unbounded'/>
<xs:element name='password' type='xs:string' minOccurs='0'/>
<xs:element ref='status' minOccurs='0' maxOccurs='unbounded'/>
</xs:choice>