This commit is contained in:
stpeter 2012-01-23 16:48:40 -07:00
parent ae6b36e030
commit ce9206c397
1 changed files with 44 additions and 44 deletions

View File

@ -47,8 +47,8 @@
<registry/>
&stpeter;
<revision>
<version>1.25rc10</version>
<date>in progress, last updated 2011-12-20</date>
<version>1.25rc11</version>
<date>in progress, last updated 2012-01-23</date>
<initials>psa</initials>
<remark>
<ul>
@ -451,14 +451,14 @@
<li>Interaction between MUC deployments and foreign chat systems (e.g., gateways to IRC or to legacy IM systems)</li>
<li>Mirroring or replication of rooms among multiple MUC deployments</li>
</ul>
<p>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 document and to present a comprehensible protocol that can be implemented by client and component developers alike. Future specifications might address the topics mentioned above.</p>
<p>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 document and to present a comprehensible protocol that can be implemented by client and service developers alike. Future specifications might address the topics mentioned above.</p>
</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 groupchat 1.0 protocol for this baseline functionality, with the result that:</p>
<ul>
<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>Each room is identified as a "room JID" &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 an "occupant JID" &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>
@ -509,12 +509,12 @@
<di><dt>Member</dt><dd>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".</dd></di>
<di><dt>Moderator</dt><dd>A room role that is usually associated with room admins but that can be granted to non-admins; is allowed to kick users, grant and revoke voice, etc. A moderator has a role of "moderator".</dd></di>
<di><dt>MUC</dt><dd>The multi-user chat protocol for text-based conferencing specified in this document.</dd></di>
<di><dt>Multi-Session Nick</dt><dd>If allowed by the service, a user can associate more than one full JID with the same room JID (e.g., the user juliet@capulet.lit is allowed to log in simultaneously as the nick "JuliC" in the characters@chat.shakespeare.lit chatroom from both juliet@capulet.lit/balcony and juliet@capulet.lit/chamber). Multi-session nicks are not currently defined in this document.</dd></di>
<di><dt>Multi-Session Nick</dt><dd>If allowed by the service, a user can associate more than one full JID with the same occupant JID (e.g., the user juliet@capulet.lit is allowed to log in simultaneously as the nick "JuliC" in the characters@chat.shakespeare.lit chatroom from both juliet@capulet.lit/balcony and juliet@capulet.lit/chamber). Multi-session nicks are not currently defined in this document.</dd></di>
<di><dt>Occupant</dt><dd>Any user who is in a room (this is an "abstract class" and does not correspond to any specific role).</dd></di>
<di><dt>Occupant JID</dt><dd>The &lt;room@service/nick&gt; by which an occupant is identified within the context of a room; contrast with Bare JID and Full JID.</dd></di>
<di><dt>Outcast</dt><dd>A user who has been banned from a room. An outcast has an affiliation of "outcast".</dd></di>
<di><dt>Participant</dt><dd>An occupant who does not have admin status; in a moderated room, a participant is further defined as having voice (in contrast to a visitor). A participant has a role of "participant".</dd></di>
<di><dt>Private Message</dt><dd>A message sent from one occupant directly to another's room JID (not to the room itself for broadcasting to all occupants).</dd></di>
<di><dt>Private Message</dt><dd>A message sent from one occupant directly to another's occupant JID (not to the room itself for broadcasting to all occupants).</dd></di>
<di><dt>Role</dt><dd>A temporary position or privilege level within a room, distinct from 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.</dd></di>
<di><dt>Room</dt><dd>A virtual space that users figuratively enter in order to participate in real-time, text-based conferencing with other users.</dd></di>
<di><dt>Room Administrator</dt><dd>A user empowered by the room owner to perform administrative functions such as banning users; however, a room administrator is not allowed to change the room configuration or to destroy the room. An admin has an affiliation of "admin".</dd></di>
@ -538,8 +538,8 @@
<di><dt>Hidden Room</dt><dd>A room that cannot be found by any user through normal means such as searching and service discovery; antonym: Public Room.</dd></di>
<di><dt>Members-Only Room</dt><dd>A room that a user cannot enter without being on the member list; antonym: Open Room.</dd></di>
<di><dt>Moderated Room</dt><dd>A room in which only those with "voice" are allowed to send messages to all occupants; antonym: Unmoderated Room.</dd></di>
<di><dt>Non-Anonymous Room</dt><dd>A room in which an occupant's full JID is exposed to all other occupants, although the occupant can choose any desired room nickname; contrast with Semi-Anonymous Room.</dd></di>
<di><dt>Open Room</dt><dd>A room that anyone is allowed to enter without being on the member list; antonym: Members-Only Room.</dd></di>
<di><dt>Non-Anonymous Room</dt><dd>A room in which an occupant's full JID is exposed to all other occupants, although the occupant can request any desired room nickname; contrast with Semi-Anonymous Room.</dd></di>
<di><dt>Open Room</dt><dd>A room that non-banned entities are allowed to enter without being on the member list; antonym: Members-Only Room.</dd></di>
<di><dt>Password-Protected Room</dt><dd>A room that a user cannot enter without first providing the correct password; antonym: Unsecured Room.</dd></di>
<di><dt>Persistent Room</dt><dd>A room that is not destroyed if the last occupant exits; antonym: Temporary Room.</dd></di>
<di><dt>Public Room</dt><dd>A room that can be found by any user through normal means such as searching and service discovery; antonym: Hidden Room.</dd></di>
@ -797,7 +797,7 @@
</tr>
<tr>
<td>Moderator</td>
<td>Exit room or be kicked by an admin or owner</td>
<td>Exit room or be kicked by an admin or owner *</td>
<td>Admin or owner changes role to visitor *</td>
<td>Admin or owner changes role to participant or revokes moderator status *</td>
<td>--</td>
@ -821,7 +821,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 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>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 might be 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'>
@ -988,8 +988,8 @@
<section1 topic='Entity Use Cases' anchor='entity'>
<p>A MUC implementation MUST support &xep0030; ("disco"). Any entity can complete the following disco-related use cases.</p>
<section2 topic='Discovering a MUC Component' anchor='disco-component'>
<p>An entity often discovers a MUC component by sending a service discovery items ("disco#items") request to its own server.</p>
<section2 topic='Discovering a MUC Service' anchor='disco-service'>
<p>An entity often discovers a MUC service by sending a Service Discovery items ("disco#items") request to its own server.</p>
<example caption='Entity Queries Server for Associated Services'><![CDATA[
<iq from='hag66@shakespeare.lit/pda'
id='h7ns81g'
@ -1004,15 +1004,15 @@
id='h7ns81g'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item jid='chat.shakespeare.lit'
name='Chatroom Service'/>
</query>
</iq>
]]></example>
</section2>
<section2 topic='Discovering the Features Supported by a MUC Component' anchor='disco-component-features'>
<p>An entity may wish to discover if a service implements the Multi-User Chat protocol; in order to do so, it sends a service discovery information ("disco#info") query to the component's JID.</p>
<section2 topic='Discovering the Features Supported by a MUC Service' anchor='disco-service-features'>
<p>An entity may wish to discover if a service implements the Multi-User Chat protocol; in order to do so, it sends a service discovery information ("disco#info") query to the MUC service's JID.</p>
<example caption='Entity Queries Chat Service for MUC Support via Disco'><![CDATA[
<iq from='hag66@shakespeare.lit/pda'
id='lx09df27'
@ -1173,7 +1173,7 @@
</field>
<field var='muc#roominfo_ldapgroup'
label='Associated LDAP Group'>
<value>dc=lit,dc=shakespeare,cn=witches</value>
<value>cn=witches,dc=shakespeare,dc=lit</value>
</field>
<field var='muc#roominfo_lang'
label='Language of discussion'>
@ -1311,7 +1311,7 @@
<li>In-room presence from other occupants</li>
<li>In-room presence from the joining entity itself (so-called "self-presence")</li>
<li>Room history (if any)</li>
<li>The room subject (if any)</li>
<li>The room subject</li>
<li>Live messages, presence updates, new user joins, etc.</li>
</ol>
</section2>
@ -1355,7 +1355,7 @@
</section3>
<section3 topic='Presence Broadcast' anchor='enter-pres'>
<p>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 a single &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 "moderator", "participant", or "visitor", and with the 'affiliation' attribute set to a value of "owner", "admin", "member", or "none" as appropriate. <note>The &PRESENCE; element MUST NOT include more than once instance of the &X; element qualified by the 'http://jabber.org/protocol/muc#user' namespace.</note></p>
<p>If the service is able to add the user to the room, it MUST send presence from all the existing participants' occupant JIDs to the new occupant's full JID, including extended presence information about roles in a single &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 "moderator", "participant", or "visitor", and with the 'affiliation' attribute set to a value of "owner", "admin", "member", or "none" as appropriate. <note>The &PRESENCE; element MUST NOT include more than once instance of the &X; element qualified by the 'http://jabber.org/protocol/muc#user' namespace.</note></p>
<example caption='Service Sends Presence from Existing Occupants to New Occupant'><![CDATA[
<presence
from='coven@chat.shakespeare.lit/firstwitch'
@ -1376,7 +1376,7 @@
</presence>
]]></example>
<p>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 a room owner) and a user with a room nickname of "secondwitch" (who is a room admin).</p>
<p>Unless the room is configured to not broadcast presence from new occupants below a certain affiliation level (as controlled by the "muc#roomconfig_presencebroadcast" room configuration option), 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).</p>
<p>Unless the room is configured to not broadcast presence from new occupants below a certain affiliation level (as controlled by the "muc#roomconfig_presencebroadcast" room configuration option), the service MUST also send presence from the new participant's occupant JID to the full JIDs of all the occupants (including the new occupant).</p>
<example caption="Service Sends New Occupant's Presence to All Occupants"><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
@ -1649,7 +1649,7 @@
]]></example>
<p>Discussion history messages MUST be stamped with &xep0203; information qualified by the 'urn:xmpp:delay' namespace to indicate that they are sent with delayed delivery and to specify the times at which they were originally sent. The 'from' attribute MUST be set to the JID of the room itself.</p>
<p>(Note: The 'urn:xmpp:delay' namespace defined in <cite>XEP-0203</cite> supersedes the older 'jabber:x:delay' namespace defined in &xep0091;; some implementations include both formats for backward compatibility.)</p>
<p>The service MUST send all discussion history messages before delivering the room subject and any "live" messages sent after the user enters the room.</p>
<p>The service MUST send all discussion history messages before delivering the room subject and any "live" messages sent after the user enters the room. Note well that this means the room subject (and changes to the room subject prior to the current subject) are not part of the discussion history.</p>
<p>If the room is non-anonymous, the service MAY include an &xep0033; element that notes the original full JID of the sender by means of the "ofrom" address type:</p>
<example caption='Discussion History Message with Original From'><![CDATA[
<message
@ -1698,7 +1698,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>Note: It is known that not all service implementations support MUC history management, so in practice a client might not be able 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
@ -1754,7 +1754,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. 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>
<p>After the room has optionally sent the discussion history to the new occupant, it SHALL send the current room subject. This is a &MESSAGE; stanza from the room JID (or from the occupant 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'
@ -1840,7 +1840,7 @@
<body>Harpier cries: 'tis time, 'tis time.</body>
</message>
]]></example>
<p>If the sender has voice in the room (this is the default except in moderated rooms) and the message does not violate any service-level or room-level policies (e.g., policies regarding message content or size), 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.</p>
<p>If the sender has voice in the room (this is the default except in moderated rooms) and the message does not violate any service-level or room-level policies (e.g., policies regarding message content or size), the service MUST change the 'from' attribute to the sender's occupant JID and reflect the message out to the full JID of each occupant.</p>
<example caption='Service Reflects Message to All Occupants'><![CDATA[
<message
from='coven@chat.shakespeare.lit/thirdwitch'
@ -1865,11 +1865,11 @@
</message>
]]></example>
<p>Note well that for tracking purposes this service assigns a new 'id' to each message it generates (here using a UUID as defined in &rfc4122;).</p>
<p>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 &notacceptable; error to the sender and SHOULD NOT reflect the message to all occupants; the only exception to this rule is that 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 those users are not occupants.</p>
<p>If the sender is a visitor (i.e., does not have voice in a moderated room), the service MUST 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 &notacceptable; error to the sender and SHOULD NOT reflect the message to all occupants; the only exception to this rule is that 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 those users are not occupants.</p>
</section2>
<section2 topic='Sending a Private Message' anchor='privatemessage'>
<p>Since each occupant has its own room JID, an occupant can send a "private message" to a selected occupant via the service by sending a message to the intended recipient'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 is controlled by the "muc#roomconfig_allowpm" room configuration option.</p>
<p>Since each occupant has its own occupant JID, an occupant can send a "private message" to a selected occupant via the service by sending a message to the intended recipient's occupant JID. The message type SHOULD be "chat" and MUST NOT be "groupchat", but MAY be left unspecified (i.e., a normal message). This privilege is controlled by the "muc#roomconfig_allowpm" room configuration option.</p>
<example caption='Occupant Sends Private Message'><![CDATA[
<message
from='wiccarocks@shakespeare.lit/laptop'
@ -1879,7 +1879,7 @@
<body>I'll give thee a wind.</body>
</message>
]]></example>
<p>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.</p>
<p>The service is responsible for changing the 'from' address to the sender's occupant JID and delivering the message to the intended recipient's full JID.</p>
<example caption='Recipient Receives the Private Message'><![CDATA[
<message
from='coven@chat.shakespeare.lit/firstwitch'
@ -1910,12 +1910,12 @@
</error>
</message>
]]></example>
<p>If the sender attempts to send a private message to a room JID that does not exist, the service MUST return an &notfound; error to the sender.</p>
<p>If the sender attempts to send a private message to an occupant JID that does not exist, the service MUST return an &notfound; error to the sender.</p>
<p>If the sender is not an occupant of the room in which the intended recipient is visiting, the service MUST return a &notacceptable; error to the sender.</p>
</section2>
<section2 topic='Changing Nickname' anchor='changenick'>
<p>A common feature of chat rooms is the ability for an occupant to change his or her nickname within the room. In MUC 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).</p>
<p>A common feature of chat rooms is the ability for an occupant to change his or her nickname within the room. In MUC this is done by sending updated presence information to the room, specifically by sending presence to a new occupant JID in the same room (changing only the resource identifier in the occupant JID).</p>
<example caption='Occupant Changes Nickname'><![CDATA[
<presence
from='hag66@shakespeare.lit/pda'
@ -2108,7 +2108,7 @@
</x>
</message>
]]></example>
<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>
<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 occupant 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'
@ -2155,7 +2155,7 @@
</x>
</message>
]]></example>
<p>It may be wondered why the invitee does not send the decline message directly to the inviter. The main reason is that certain implementations might 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). Thus the service needs to handle both the invites and declines.</p>
<p>It may be wondered why the invitee does not send the decline message directly to the inviter. The main reason is that certain implementations might choose to base invitations on occupant 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). Thus the service needs to handle both the invites and declines.</p>
</section3>
</section2>
@ -2185,7 +2185,7 @@
<p>Now the first person decides to include a third person in the discussion, so she does the following:</p>
<ol start='1'>
<li>Creates a new multi-user chatroom</li>
<li>Sends history of the one-to-one chat to the room (this is purely OPTIONAL; because it might cause information leakage, the client SHOULD warn the user before doing so)</li>
<li>Sends history of the one-to-one chat to the room (this is purely discretionary; however, because it might cause information leakage, the client ought to warn the user before doing so)</li>
<li>Sends an invitation to the second person and the third person, including a &lt;continue/&gt; element (optionally including a 'thread' attribute).</li>
</ol>
<p>Note: The new room SHOULD be non-anonymous and MAY be an instant room as specified in the <link url='#createroom-instant'>Creating an Instant Room</link> section of this document.</p>
@ -2231,7 +2231,7 @@
stamp='2004-09-29T01:55:21Z'/>
</message>
]]></example>
<p>Note: Use of the <cite>Delayed Delivery</cite> protocol enables the room creator to specify the datetime of each message from the one-to-one chat history (via the 'stamp' attribute), as well as the JID of the original sender of each message (via the 'from' attribute); note well that the 'from' here is not the room itself, since the originator of the message is the delaying party. The room creator SHOULD send the complete one-to-one chat history before inviting additional users to the room, and SHOULD also send as history any messages appearing in the one-to-one chat interface after joining the room and before the second person joins the room; if the one-to-one history is especially large, the sending client might want to send the history over a few seconds rather than all at once (to avoid triggering rate limits). The service SHOULD NOT add its own delay elements (as described in the <link url='#enter-history'>Discussion History</link> section of this document) to prior chat history messages received from the room owner.</p>
<p>Note: Use of the <cite>Delayed Delivery</cite> protocol enables the room creator to specify the datetime of each message from the one-to-one chat history (via the 'stamp' attribute), as well as the JID of the original sender of each message (via the 'from' attribute); note well that the 'from' here is not the room itself, since the originator of the message is the delaying party. The room creator might send the complete one-to-one chat history before inviting additional users to the room, and also send as history any messages appearing in the one-to-one chat interface after joining the room and before the second person joins the room; if the one-to-one history is especially large, the sending client might want to send the history over a few seconds rather than all at once (to avoid triggering rate limits). The service SHOULD NOT add its own delay elements (as described in the <link url='#enter-history'>Discussion History</link> section of this document) to prior chat history messages received from the room owner.</p>
<example caption='Continuing the Discussion III: Owner Sends Invitations, Including Continue Flag'><![CDATA[
<message
from='crone1@shakespeare.lit/desktop'
@ -2276,7 +2276,7 @@
</x>
</message>
]]></example>
<p>When the client being used by &lt;wiccarocks@shakespeare.lit/laptop&gt; receives the invitation, it SHOULD auto-join the room or prompt the user whether to join (subject to user preferences) and then seamlessly convert the existing one-to-one chat window into a multi-user conferencing window:</p>
<p>When the client being used by &lt;wiccarocks@shakespeare.lit/laptop&gt; receives the invitation, it can either auto-join the room or prompt the user whether to join (subject to user preferences) and then seamlessly convert the existing one-to-one chat window into a multi-user conferencing window:</p>
<example caption='Invitee Accepts Invitation, Joins Room, and Receives Presence and History'><![CDATA[
<presence
from='wiccarocks@shakespeare.lit/laptop'
@ -2582,7 +2582,7 @@
to='coven@chat.shakespeare.lit/thirdwitch'
type='unavailable'/>
]]></example>
<p>The service MUST then send a presence stanzas of type "unavailable" from the departing occupant's room JID to the departing occupant's full JIDs, including a status code of "110" to indicate that this notification is "self-presence":</p>
<p>The service MUST then send a presence stanzas of type "unavailable" from the departing user's occupant JID to the departing occupant's full JIDs, including a status code of "110" to indicate that this notification is "self-presence":</p>
<example caption='Service Sends Self-Presence Related to Departure of Occupant'><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
@ -2597,7 +2597,7 @@
</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>
<p>The service MUST then send presence stanzas of type "unavailable" from the departing user's occupant JID to the full JIDs of the remaining occupants:</p>
<example caption='Service Sends Presence Related to Departure of Occupant'><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
@ -2641,7 +2641,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 &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>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 occupant 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>
@ -2673,7 +2673,7 @@
<subject>Fire Burn and Cauldron Bubble!</subject>
</message>
]]></example>
<p>The MUC service 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:</p>
<p>The MUC service MUST reflect the message to all other occupants with a 'from' address equal to the room JID or to the occupant JID that corresponds to the sender of the subject change:</p>
<example caption='Service Informs All Occupants of Subject Change'><![CDATA[
<message
from='coven@chat.shakespeare.lit/secondwitch'
@ -3161,7 +3161,7 @@
to='southampton@chat.shakespeare.lit'
type='set'>
<query xmlns='http://jabber.org/protocol/muc#admin'>
<item affiliation='outcast'>
<item affiliation='outcast'
jid='lordscroop@shakespeare.lit'>
<reason>Treason</reason>
</item>
@ -3370,7 +3370,7 @@
type='result'/>
]]></example>
<p>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".</p>
<p>If a removed member is currently in a members-only room, the service SHOULD kick the occupant by changing the removed member's role to "none" and send appropriate presence to the removed member as previously described. If the removed member is not currently in the room, the service SHOULD send a message to the user's bare JID indicating the change in affiliation. No matter whether the removed member was in or out of a members-only room, the service MUST subsequently refuse entry to the user.</p>
<p>If a removed member is currently in a members-only room, the service SHOULD kick the occupant by changing the removed member's role to "none" and send appropriate presence to the removed member as previously described. The service MUST subsequently refuse entry to the user.</p>
<p>For all room types, the service 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 "none".</p>
<example caption="Service Sends Notice of Loss of Membership to All Occupants"><![CDATA[
<presence
@ -5502,7 +5502,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 <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>In order to provide consistency regarding the addresses captured in room JIDs and occupant 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>
@ -5535,8 +5535,8 @@ xmpp:coven@chat.shakespeare.lit?invite;jid=hecate@shakespeare.lit;password=cauld
<section2 topic='IQ' anchor='bizrules-iq'>
<ol start='1'>
<li><p>MUC is designed for sharing of messages and presence, not IQs. An IQ sent to the JID of the room itself is handled by the room and is not reflected to all of the room occupants.</p></li>
<li><p>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).</p></li>
<li><p>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 SHOULD forward the stanza to the recipient's real JID. However, the MUC 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.</p></li>
<li><p>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 occupant JID).</p></li>
<li><p>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 occupant JID and the service SHOULD forward the stanza to the recipient's real JID. However, the MUC 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.</p></li>
<li><p>A MUC client MUST send only the 'affiliation' attribute or the 'role' attribute in the &lt;item/&gt; element contained within an IQ set qualified 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 &badrequest; error to the sender. However, the MUC 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.</p></li>
<li><p>In IQ sets regarding roles, a MUC client MUST include the 'nick' attribute only; in IQ results regarding roles, a MUC service MUST include the 'nick', 'role', 'affiliation', and 'jid' attributes (with the value of the latter set to the user's full JID).</p></li>
<li><p>In IQ sets regarding affiliations, a MUC client MUST include the 'jid' attribute only (with the value set to the bare JID); in IQ results regarding affiliations, a MUC 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).</p></li>
@ -5546,7 +5546,7 @@ xmpp:coven@chat.shakespeare.lit?invite;jid=hecate@shakespeare.lit;password=cauld
</section1>
<section1 topic='Implementation Notes' anchor='impl'>
<p>The following guidelines are intended to assist client and component developers in creating MUC implementations.</p>
<p>The following guidelines are intended to assist client and service developers in creating MUC implementations.</p>
<section2 topic='Services' anchor='impl-service'>
<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>