You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

6238 lines
327 KiB

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
<!ENTITY ROOMJID "&lt;room@service&gt;">
<!ENTITY OCCUPANTJID "&lt;room@service/nick&gt;">
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>Multi-User Chat</title>
<abstract>This specification defines an XMPP protocol extension for multi-user text chat, whereby multiple XMPP users can exchange messages in the context of a room or channel, similar to Internet Relay Chat (IRC). In addition to standard chatroom features such as room topics and invitations, the protocol defines a strong room control model, including the ability to kick and ban users, to name room moderators and administrators, to require membership or passwords in order to join the room, etc.</abstract>
&LEGALNOTICE;
<number>0045</number>
<status>Draft</status>
<type>Standards Track</type>
<sig>Standards</sig>
<dependencies>
<spec>XMPP Core</spec>
<spec>XMPP IM</spec>
<spec>XEP-0004</spec>
<spec>XEP-0030</spec>
<spec>XEP-0068</spec>
<spec>XEP-0082</spec>
<spec>XEP-0128</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>muc</shortname>
<schemaloc>
<ns>muc</ns>
<url>http://www.xmpp.org/schemas/muc.xsd</url>
</schemaloc>
<schemaloc>
<ns>muc#admin</ns>
<url>http://www.xmpp.org/schemas/muc-admin.xsd</url>
</schemaloc>
<schemaloc>
<ns>muc#owner</ns>
<url>http://www.xmpp.org/schemas/muc-owner.xsd</url>
</schemaloc>
<schemaloc>
<ns>muc#user</ns>
<url>http://www.xmpp.org/schemas/muc-user.xsd</url>
</schemaloc>
<registry/>
&stpeter;
<revision>
<version>1.34.2</version>
<date>2021-06-24</date>
<initials>lk</initials>
<remark><p>Clean up anonymous types values.</p></remark>
</revision>
<revision>
<version>1.34.1</version>
<date>2021-03-04</date>
<initials>mw</initials>
<remark><p>Cross-document editorial adjustments for inclusive language.</p></remark>
</revision>
<revision>
<version>1.34.0</version>
<date>2020-10-28</date>
<initials>jsc</initials>
<remark><p>Specify the use of a delay element in the initial subject message.</p></remark>
</revision>
<revision>
<version>1.33.0</version>
<date>2020-04-15</date>
<initials>mw</initials>
<remark><p>Clarify that the 307 status code should not be used alongside 333 for user disconnects.</p></remark>
</revision>
<revision>
<version>1.32.0</version>
<date>2019-05-15</date>
<initials>gl</initials>
<remark><p>Remove Group Chat 1.0 compatibility due to operational issues.</p></remark>
</revision>
<revision>
<version>1.31.2</version>
<date>2018-07-31</date>
<initials>jwi</initials>
<remark><p>Add implementation note about legacy invitations.</p></remark>
</revision>
<revision>
<version>1.31.1</version>
<date>2018-03-12</date>
<initials>kis</initials>
<remark>
<p>Fix the wrong JID in an example.</p>
</remark>
</revision>
<revision>
<version>1.31</version>
<date>2018-03-06</date>
<initials>gl</initials>
<remark>
<p>Require the service to maintain the 'id' attribute on message reflections.</p>
</remark>
</revision>
<revision>
<version>1.30</version>
<date>2018-02-23</date>
<initials>jwi</initials>
<remark>
<p>Add 333 status code with OPTIONAL feature.</p>
</remark>
</revision>
<revision>
<version>1.29</version>
<date>2017-09-01</date>
<initials>gl</initials>
<remark>
<p>Clarify wording for a client re-syncing to a MUC</p>
</remark>
</revision>
<revision>
<version>1.28</version>
<date>2017-05-31</date>
<initials>gl</initials>
<remark>
<p>Introduce &lt;x/&gt; tag in MUC-PMs to support better Carbon delivery.</p>
</remark>
</revision>
<revision>
<version>1.27.1</version>
<date>2016-12-03</date>
<initials>XEP Editor: ssw</initials>
<remark>
<p>Editorial typo and whitespace fixes.</p>
</remark>
</revision>
<revision>
<version>1.27</version>
<date>2016-10-29</date>
<initials>XEP Editor: ssw</initials>
<remark>
<ul>
<li>Clarify behavior on MUC join.</li>
</ul>
</remark>
</revision>
<revision>
<version>1.26</version>
<date>2016-05-16</date>
<initials>XEP Editor (ssw)</initials>
<remark>
<ul>
<li>Add status code to self-presence example.</li>
<li>muc#roomconfig_allowpm should be list-single.</li>
<li>muc#roomconfig_allowinvites should be boolean.</li>
<li>Typo: Publish-Subscribe.</li>
<li>15.6.2 Initial Submission: Status code 174 is missing.</li>
<li>muc#role should be list-single</li>
<li>muc#register_faqentry: mixed occurrences of text-single and text-multi</li>
</ul>
</remark>
</revision>
<revision>
<version>1.25</version>
<date>2012-02-08</date>
<initials>psa</initials>
<remark>
<ul>
<li>Clarified the fact that room roles and affiliations are shortcuts to bundles of privileges.</li>
<li>Removed references to service discovery feature for "gc-1.0" since it is now obsolete.</li>
<li>Added security consideration about information leaks related to service discovery.</li>
<li>Corrected some examples of presence and message errors so that the 'from' and 'to' addresses are merely swapped, in accordance with RFC 6120; also added 'by' attribute to show that the room itself generated the error.</li>
<li>Added 'nick' attribute to &lt;actor/&gt; element so that an action can be attributed either to a real JID or to a roomnick.</li>
<li>Clarified the meaning of status code 100.</li>
<li>Corrected delayed delivery text and examples so that the 'from' address is that of the room, and specified optional inclusion of the XEP-0033 'ofrom' address to note original sender.</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>Loosened handling of room joins when nicks are locked down, so that the service should modify the roomnick instead of returning an error.</li>
<li>Specified that the room must return a room subject, even if the subject is empty.</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>
</ul>
</remark>
</revision>
<revision>
<version>1.24</version>
<date>2008-07-16</date>
<initials>psa</initials>
<remark><p>Added more examples of the reason element; removed mention of nick inclusion with regard to ban lists; added denial of service considerations.</p></remark>
</revision>
<revision>
<version>1.23</version>
<date>2008-01-14</date>
<initials>psa</initials>
<remark>
<ul>
<li>Defined getmemberlist room configuration option</li>
<li>Added direct invitation protocol</li>
<li>Corrected logic regarding admission of room owner/admin when room is full</li>
<li>Defined service discovery extension field for associated LDAP group</li>
<li>Specified that room config fields can be listed in extended room information</li>
<li>Specified message format for affiliation change notifications if user is not in the room</li>
<li>Added example showing use of Result Set Management</li>
<li>Recommended inclusion of MUC child element in presence errors</li>
<li>Described use of ThreadID for continuity between one-to-one chat and multi-user chat, including definition of thread attribute for continue element in invitations.</li>
</ul>
</remark>
</revision>
<revision>
<version>1.22</version>
<date>2007-04-10</date>
<initials>psa</initials>
<remark><p>Updated delayed delivery reference to reflect advancement of XEP-0203 to Draft and deprecation of XEP-0091.</p></remark>
</revision>
<revision>
<version>1.21</version>
<date>2006-09-13</date>
<initials>psa</initials>
<remark>
<ul>
<li>Clarified that inclusion of MUC extension in room join/create request triggers Data Forms flow but that absence of MUC extension leads to automatic room creation for backwards compatibility with older groupchat 1.0 protocol.</li>
<li>Specified use of &lt;not-acceptable/&gt; error on nickname change if nicks are locked down.</li>
<li>Required clients to discover room configuration prior to entering room and specified related security considerations, including use of privacy-related status codes 170, 171, 172, 173, and 174.</li>
<li>Specified use of &lt;not-acceptable/&gt; error if room configuration options cannot be processed or violate service policies.</li>
<li>Made explicit that roomnicks must not consist only of spaces.</li>
<li>Moved all service discovery use cases into dedicated section.</li>
<li>Changed urn:xmpp:delay support from SHOULD to MUST.</li>
<li>Clarified that _whois room configuration option specifies room type.</li>
<li>Defined XEP-0128 room information fields for discussion logs, associated pubsub node, and contact JID.</li>
<li>Specified that changing role to moderator upon affiliation change to admin or owner is recommended, not required.</li>
<li>Added internationalization consideration about localization of field labels for various data forms.</li>
<li>Specified that implementations may persist roles across visits and should do so for moderated rooms.</li>
<li>Added protocol and service discovery feature for requesting a unique room name prior to room creation.</li>
<li>Further clarified nature of reserved room nicknames and nickname lockdown.</li>
<li>Defined data forms for requesting voice and approving voice requests.</li>
<li>Added multiple invitee example for XMPP URI.</li>
<li>Clarified order of presence, discussion history, etc.</li>
<li>Added status codes for occupant's own roomnick, service-modified roomnick, and warning that room discussion is publicly logged.</li>
<li>Clarified privacy and anonymity considerations regarding room logging and non-anonymous rooms.</li>
</ul>
</remark>
</revision>
<revision>
<version>1.20</version>
<date>2005-09-08</date>
<initials>psa</initials>
<remark><p>Harmonized ability to kick and ban users, and clarified that a user cannot be kicked or banned by a moderator or admin with a lower affiliation.</p></remark>
</revision>
<revision>
<version>1.19</version>
<date>2005-04-21</date>
<initials>psa</initials>
<remark><p>Specified how to send multiple invitations simultaneously; corrected some errors regarding consistency of affiliation state changes; changed message events prohibition from MUST NOT to SHOULD NOT; corrected error handling related to the #traffic disco node; allowed &lt;password/&gt; as a child of &lt;destroy/&gt;; changed max users error from &notallowed; to &unavailable;; specified that the maxchars attribute counts characters in complete XML stanzas; added disco features for FORM_TYPEs; defined registry for status codes; split Create Instant Room into separate use case for protocol compliance purposes; adjusted XML schemas to reflect the foregoing changes; re-wrote the introduction; clarified small textual matters throughout.</p></remark>
</revision>
<revision>
<version>1.18</version>
<date>2004-11-02</date>
<initials>psa</initials>
<remark><p>Corrected several errors in the affiliation state chart and in the examples (wrong FORM_TYPE values); mentioned /me command.</p></remark>
</revision>
<revision>
<version>1.17</version>
<date>2004-10-04</date>
<initials>psa</initials>
<remark><p>Added text about allowable extension namespaces and related service discovery mechanisms; specified well-known service discovery nodes; added conformance terms to clarify some descriptions; modified affiliation state chart to allow more flexible state changes; per list dicussion, added ability to convert a one-to-one chat into a conference, including sending of history; specified error to use when max users limit is reached; specified form for admin approval of user registration requests and modified FORM_TYPE from http://jabber.org/protocol/muc#user to http://jabber.org/protocol/muc#register; modified FORM_TYPE for room configuration from http://jabber.org/protocol/muc#owner to http://jabber.org/protocol/muc#roomconfig.</p></remark>
</revision>
<revision>
<version>1.16</version>
<date>2004-06-30</date>
<initials>psa</initials>
<remark><p>Added example and registry submission for service discovery extension.</p></remark>
</revision>
<revision>
<version>1.15</version>
<date>2004-06-24</date>
<initials>psa</initials>
<remark><p>Removed jabber:iq:browse references; clarified order of presence stanzas sent to new occupant on entering room; specified format of in-room messages (type='groupchat', from='room@service'); clarified allowable attributes in various list-related operations; made admin/owner revocation text and examples consistent with state chart; clarified ownership revocation conflict scenarios; changed the 'muc#roomconfig_inviteonly' field to 'muc#roomconfig_membersonly'; changed attribute order in examples to match XML canonicalization rules; corrected several errors in the schemas.</p></remark>
</revision>
<revision>
<version>1.14</version>
<date>2004-05-03</date>
<initials>psa</initials>
<remark><p>Corrected discovery of registered roomnicks; added note about error to return if nicks are locked down.</p></remark>
</revision>
<revision>
<version>1.13</version>
<date>2004-03-31</date>
<initials>psa</initials>
<remark><p>Fixed an error in the muc#user schema.</p></remark>
</revision>
<revision>
<version>1.12</version>
<date>2004-03-01</date>
<initials>psa</initials>
<remark><p>Corrected a few errors in the examples; added IQ results in order to clarify workflows.</p></remark>
</revision>
<revision>
<version>1.11</version>
<date>2004-02-05</date>
<initials>psa</initials>
<remark><p>Clarified JID matching rules (same as for privacy lists in XMPP IM).</p></remark>
</revision>
<revision>
<version>1.10</version>
<date>2004-01-07</date>
<initials>psa</initials>
<remark><p>Added XMPP error handling; fully specified all conformance terms.</p></remark>
</revision>
<revision>
<version>1.9</version>
<date>2003-12-14</date>
<initials>psa</initials>
<remark><p>Removed protocol for requesting voice in a moderated room (should be performed using Ad-Hoc Commands).</p></remark>
</revision>
<revision>
<version>1.8</version>
<date>2003-12-04</date>
<initials>psa</initials>
<remark><p>Added protocol for requesting voice in a moderated room; added (informational) mapping of IRC commands to MUC protocols.</p></remark>
</revision>
<revision>
<version>1.7</version>
<date>2003-10-21</date>
<initials>psa</initials>
<remark><p>Added room configuration option for restricting presence broadcast to certain roles.</p></remark>
</revision>
<revision>
<version>1.6</version>
<date>2003-10-03</date>
<initials>psa</initials>
<remark><p>Added history management protocol on entering a room.</p></remark>
</revision>
<revision>
<version>1.5</version>
<date>2003-09-11</date>
<initials>psa</initials>
<remark><p>Specified that ban occurs by JID, not roomnick; allowed privileged users to send messages to the room even if not present in the room; added note that service should remove occupant if a delivery-related stanza error occurs; enabled user to disco the room in order to discover registered roomnick; specified that "banning" by domain or regex is a service-level configuration matter and therefore out of scope for MUC; specified that role should be decremented as appropriate if affiliation is lowered; added some clarifying text to room creation workflow; added implementation note about sending an out-of-band message if a user's affiliation changes while the user is not in the room; fixed stringprep references (room nicks use Resourceprep); clarified relationship between Room ID (i.e., node identifier of Room JID or Occupant JID, which may be opaque) and natural-language Room Name; specified Field Standardization profile per XEP-0068; defined XMPP Registrar submissions; added schema locations.</p></remark>
</revision>
<revision>
<version>1.4</version>
<date>2003-02-16</date>
<initials>psa</initials>
<remark><p>Added XML schemas.</p></remark>
</revision>
<revision>
<version>1.3</version>
<date>2003-02-11</date>
<initials>psa</initials>
<remark><p>Added reference to nodeprep Internet-Draft.</p></remark>
</revision>
<revision>
<version>1.2</version>
<date>2003-01-30</date>
<initials>psa</initials>
<remark><p>Commented out revision history prior to version 1.0 (too long); clarified business rules regarding when nicks, full JIDs, and bare JIDs are used in reference to roles and affiliations; consistently specified that extended presence information in the muc#user namespace must include the full JID as the value of the 'jid' attribute in all cases; cleaned up text and examples throughout; added open issue regarding syntax of room nicknames.</p></remark>
</revision>
<revision>
<version>1.1</version>
<date>2002-12-16</date>
<initials>psa</initials>
<remark><p>Added protocol for declining an invitation; replaced &lt;created/&gt; element with status code 201; modified the destroy room protocol so that &lt;destroy/&gt; is a child of &lt;query/&gt;; clarified usage of 'nick' attribute when adding members; prohibited use of message events.</p></remark>
</revision>
<revision>
<version>1.0</version>
<date>2002-11-21</date>
<initials>psa</initials>
<remark><p>Per a vote of the Jabber Council, revision 0.23 was advanced to Draft on 2002-11-21. (For earlier revision history, refer to XML source.)</p></remark>
</revision>
<revision>
<version>0.23</version>
<date>2002-11-06</date>
<initials>psa</initials>
<remark><p>Added examples for disco#items queries sent to a room; prohibited 'type' attribute on invite messages sent from client to room; added dependencies on browse and disco; changed 'room user' to 'occupant'; fixed many small errors throughout.</p></remark>
</revision>
<revision>
<version>0.22</version>
<date>2002-11-04</date>
<initials>psa</initials>
<remark><p>Added example for disco#items; added support for cancellation of room configuration using type='cancel' from XEP-0004; noted 403 error for invites sent by non-admins in members-only room.</p></remark>
</revision>
<revision>
<version>0.21</version>
<date>2002-11-01</date>
<initials>psa</initials>
<remark><p>Clarified several small ambiguities; made &lt;body/&gt; optional on invites sent from the service to the invitee; added error scenarios for changing nickname and for destroying the room; specified that the service must return the full member list for a members-only room (not only the members in the room); updated the disco examples to track protocol changes.</p></remark>
</revision>
<revision>
<version>0.20</version>
<date>2002-10-29</date>
<initials>psa</initials>
<remark><p>Specified that messages sent to change the room subject must be of type "groupchat"; updated the legal notice to conform to the XSF IPR policy.</p></remark>
</revision>
<revision>
<version>0.19</version>
<date>2002-10-28</date>
<initials>psa</initials>
<remark><p>Added ability to create an instant room within MUC (not by using gc-1.0 protocol); cleaned up disco examples.</p></remark>
</revision>
<revision>
<version>0.18</version>
<date>2002-10-27</date>
<initials>psa</initials>
<remark><p>Added experimental support for disco; added sections for security, IANA, and JANA considerations; corrected typographical errors; cleaned up some DocBook formatting.</p></remark>
</revision>
<revision>
<version>0.17</version>
<date>2002-10-23</date>
<initials>psa</initials>
<remark><p>Added the optional &lt;actor/&gt; element (with 'jid' attribute) to &lt;item/&gt; elements inside presence stanzas of type "unavailable" that are sent to users who are kicked or banned, as well as within IQs for tracking purposes; reverted all list editing use cases (ban, voice, member, moderator, admin, owner) to use of MUC format rather than 'jabber:x:data' namespace; added several guidelines regarding generation and handling of XML stanzas; cleaned up the change room subject use case; changed several ambiguous uses of 'would', 'can', and 'will' to 'should', 'may', or 'must'; fixed several small errors in the text, examples, and DTDs.</p></remark>
</revision>
<revision>
<version>0.16</version>
<date>2002-10-20</date>
<initials>psa</initials>
<remark><p>Added the &lt;item/&gt; element to presence stanzas of type "unavailable" in order to improve the tracking of user states in the room; consolidated &lt;invitee/&gt; and &lt;inviter/&gt; elements into an &lt;invite/&gt; element with 'from' and 'to' attributes; made &lt;reason/&gt; element always a child of &lt;item/&gt; or &lt;invite/&gt; in the muc#user namespace; moved the alternate room location in room destruction to a 'jid' attribute of the &lt;alt/&gt; element; further specified several error messages; disallowed simultaneous modifications of both affiliations and roles by a moderator or admin; added several more rules regarding handling of XML stanzas; added use cases for granting and revoking admin status; adjusted DTD to track all changes.</p></remark>
</revision>
<revision>
<version>0.15</version>
<date>2002-10-18</date>
<initials>psa</initials>
<remark><p>Fully incorporated the change to affiliations + roles; moved a number of admin use cases to a new section for moderator use cases; added participant use case for requesting membership; added admin use cases for adding members, removing members, granting and revoking moderator status, and modifying the moderator list; organized the sections in a more logical manner.</p></remark>
</revision>
<revision>
<version>0.14</version>
<date>2002-10-17</date>
<initials>psa</initials>
<remark><p>Significantly modified the privileges model by distinguishing between in-room "roles" and long-lived "affiliations"; specified the privileges of the various roles and affiliations; included state transition charts for both roles and affiliations; removed use of MUC protocol for editing ban, voice, and admin lists (but not for the actions of banning users and granting/revoking voice); added delivery rule regarding IQ stanzas; changed kick so that the action is based on changing the role to "none".</p></remark>
</revision>
<revision>
<version>0.13</version>
<date>2002-10-16</date>
<initials>psa</initials>
<remark><p>Corrected the change nickname examples (newnick sent on unavailable, no nick sent on available).</p></remark>
</revision>
<revision>
<version>0.12</version>
<date>2002-10-16</date>
<initials>psa</initials>
<remark><p>Removed SHA1 passwords; specified that room shall add passwords on invitations to password-protected rooms (not supplied by inviter).</p></remark>
</revision>
<revision>
<version>0.11</version>
<date>2002-10-16</date>
<initials>psa</initials>
<remark><p>Changed 'participant' to 'room user' and 'discussant' to 'participant'; clarified presence rule about client generation of extended presence information; added role of 'none'.</p></remark>
</revision>
<revision>
<version>0.10</version>
<date>2002-10-15</date>
<initials>psa</initials>
<remark><p>Fixed extended presence on entering or creating a room (plain '...muc' with no fragment); harmonized #user with #admin regarding the use of the &lt;item/&gt; element and associated attributes (jid, nick, etc.), and added 'role' attribute; modified management of voice, ban, admin, and member lists to use &lt;query/&gt; wrapper and new &lt;item/&gt; structure; changed the 'member' role to 'discussant', added 'outcast' role for banned users, and added new 'member' role to enable management of member lists; changed invitation-only rooms to members-only rooms and made appropriate adjustments to apply member lists to both members-only rooms and open rooms; modified nickname change protocol slightly to send the old nickname in the unavailable presence and the new nickname in the available presence; removed prohibition on members-only rooms that are password-protected; removed the &lt;query/&gt; wrapper for the &lt;destroy/&gt; element; updated the DTDs.</p></remark>
</revision>
<revision>
<version>0.9</version>
<date>2002-10-13</date>
<initials>psa</initials>
<remark><p>Added extended presence ('...#user') on entering a room for MUC clients; changed namespace on room creation request to '...#owner'; added a service discovery example using jabber:iq:browse; added information about discussion history; made small fixes to several examples; further defined the presence rules; transferred all implementation notes to a dedicated section; added a Terminology section.</p></remark>
</revision>
<revision>
<version>0.8</version>
<date>2002-10-10</date>
<initials>psa</initials>
<remark><p>Made further changes to the room creation workflow (finally correct); removed feature discovery use case (this needs to be addressed by a real service discovery protocol!); added ability for room owners to edit the admin list; removed &lt;body/&gt; from invitations generated by the service; removed messages sent to kicked and banned users (handled by unavailable presence with status code); added a number of implementation notes; converted all examples to Shakespeare style.</p></remark>
</revision>
<revision>
<version>0.7.6</version>
<date>2002-10-09</date>
<initials>psa</initials>
<remark><p>Fixed the room creation workflow; changed some terminology ("join" to "enter" and "leave" to "exit").</p></remark>
</revision>
<revision>
<version>0.7.5</version>
<date>2002-10-08</date>
<initials>psa</initials>
<remark><p>Specified and improved the handling of invitation-only rooms. In particular, added the ability for room admins to edit the invitation list and added a configuration option that limits the ability to send invitations to room admins only.</p></remark>
</revision>
<revision>
<version>0.7.4</version>
<date>2002-10-07</date>
<initials>psa</initials>
<remark><p>Changed namespaces from http://jabber.org/protocol/muc/owner etc. to http://jabber.org/protocol/muc#owner etc. per Jabber Council discussion.</p></remark>
</revision>
<revision>
<version>0.7.3</version>
<date>2002-10-07</date>
<initials>psa</initials>
<remark><p>Changed namespaces to HTTP URIs; left role handling up to the implementation; further clarified presence rules.</p></remark>
</revision>
<revision>
<version>0.7.2</version>
<date>2002-10-06</date>
<initials>psa</initials>
<remark><p>Disallowed kicking, banning, and revoking voice with respect to room admins and room owners; replaced &lt;x/&gt; with &lt;query/&gt; in the Discovering Room Features and Destroying a Room use cases; corrected some small errors and made many clarifications throughout.</p></remark>
</revision>
<revision>
<version>0.7.1</version>
<date>2002-10-04</date>
<initials>psa</initials>
<remark><p>Removed &lt;whois/&gt; command (unnecessary since participants with appropriate privileges receive the full JID of all participants in presence stanzas); completed many small fixes throughout.</p></remark>
</revision>
<revision>
<version>0.7</version>
<date>2002-10-03</date>
<initials>psa</initials>
<remark><p>More clearly delineated participant roles and defined the hierarchy thereof (owner, admin, member, visitor); replaced &lt;voice/&gt; element in extended presence with &lt;item role='member'/&gt;; changed initial room configuration to use IQ rather than message; adjusted presence rules (especially regarding extended presence information); cleaned up examples throughout; updated DTD to track changes.</p></remark>
</revision>
<revision>
<version>0.6</version>
<date>2002-09-21</date>
<initials>psa</initials>
<remark><p>More clearly defined the scope; removed fully anonymous rooms; changed meaning of semi-anonymous rooms and of non-anonymous rooms; added mechanism for notification of full JIDs in non-anonymous rooms; replaced the &lt;admin/&gt; element in extended presence with a &lt;role/&gt; element (more extensible); changed room passwords to cleartext; added status codes for various messages received from the service; added lists of valid error and status codes associated with the 'http://jabber.org/protocol/muc#user' namespace; added a &lt;reason/&gt; element for invitations; made kick and ban reasons child elements rather than attributes; replaced stopgap feature discovery mechanism with jabber:iq:negotiate; added extended presence element to room creation request and clarified the room creation process; specified presence reflection rules; added method for destroying a room; adjusted DTDs to track all changes.</p></remark>
</revision>
<revision>
<version>0.5.1</version>
<date>2002-09-20</date>
<initials>psa</initials>
<remark><p>Added DTDs; changed feature discovery to use &lt;x/&gt; element rather than query and made service response come in IQ result; fixed reference to JID spec; changed 'grant' to 'add' and 'revoke' to 'remove' for consistency in the item attributes; made several other small changes.</p></remark>
</revision>
<revision>
<version>0.5</version>
<date>2002-09-19</date>
<initials>psa</initials>
<remark><p>Changed the kick, ban, and voice protocols; added a few more configuration options; specified the restrictions for roomnicks; and added a stopgap service discovery protocol.</p></remark>
</revision>
<revision>
<version>0.4</version>
<date>2002-09-18</date>
<initials>psa</initials>
<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>
<date>2002-09-17</date>
<initials>psa</initials>
<remark><p>Changed admin use cases; cleaned up participant and owner use cases.</p></remark>
</revision>
<revision>
<version>0.2</version>
<date>2002-09-12</date>
<initials>psa</initials>
<remark><p>Broke content out into three actors (participant, owner, and admin) and added more detail to owner and admin use cases.</p></remark>
</revision>
<revision>
<version>0.1</version>
<date>2002-09-09</date>
<initials>psa</initials>
<remark><p>Initial version.</p></remark>
</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) is not compatible to the groupchat 1.0 protocol, but provides advanced features such as invitations, room moderation and administration, and specialized room types.</p>
</section1>
<section1 topic='Scope' anchor='scope'>
<p>This document addresses common requirements related to configuration of, participation in, and administration of individual text-based conference rooms. All of the requirements addressed herein apply at the level of the individual room and are "common" in the sense that they have been widely discussed within the Jabber/XMPP community or are familiar from existing text-based conference environments (e.g., Internet Relay Chat as defined in &rfc1459; and its successors: &rfc2810;, &rfc2811;, &rfc2812;, &rfc2813;).</p>
<p>This document explicitly does <em>not</em> address the following:</p>
<ul>
<li>Relationships between rooms (e.g., hierarchies of rooms)</li>
<li>Management of multi-user chat services (e.g., managing permissions across an entire service or registering a global room nickname); such use cases are specified in &xep0133;</li>
<li>Moderation of individual messages</li>
<li>Encryption of messages sent through a room</li>
<li>Advanced features such as attaching files to a room, integrating whiteboards, and using MUC rooms as a way to manage the signalling for multi-user audio or video conferencing (see &xep0272;)</li>
<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 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. This design is based on the original groupchat 1.0 protocol, with the result that:</p>
<ul>
<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>
<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'>
<li>native conversation logging (no in-room bot required)</li>
<li>enabling users to request membership in a room</li>
<li>enabling occupants to view an occupant's full JID in a non-anonymous room</li>
<li>enabling moderators to view an occupant's full JID in a semi-anonymous room</li>
<li>allowing only moderators to change the room subject</li>
<li>enabling moderators to kick participants and visitors from the room</li>
<li>enabling moderators to grant and revoke voice (i.e., the privilege to speak) in a moderated room, and to manage the voice list</li>
<li>enabling admins to grant and revoke moderator status, and to manage the moderator list</li>
<li>enabling admins to ban users from the room, and to manage the ban list</li>
<li>enabling admins to grant and revoke membership privileges, and to manage the member list for a members-only room</li>
<li>enabling owners to configure various room parameters (e.g., limiting the number of occupants)</li>
<li>enabling owners to specify other owners</li>
<li>enabling owners to grant and revoke admin status, and to manage the admin list</li>
<li>enabling owners to destroy the room</li>
</ol>
<p>In addition, this document provides protocol elements for supporting the following room types:</p>
<ol start='1'>
<li>public vs. hidden</li>
<li>persistent vs. temporary</li>
<li>password-protected vs. unsecured</li>
<li>members-only vs. open</li>
<li>moderated vs. unmoderated</li>
<li>non-anonymous vs. semi-anonymous</li>
</ol>
<p>The extensions needed to implement these requirements are qualified by the 'http://jabber.org/protocol/muc' namespace (and the #owner, #admin, and #user fragments on the main namespace URI).</p>
</section1>
<section1 topic='Terminology' anchor='terms'>
<section2 topic='General Terms' anchor='terms-general'>
<dl>
<di><dt>Affiliation</dt><dd>A long-lived association or connection with a room; the possible affiliations are "owner", "admin", "member", and "outcast" (naturally it is also possible to have no affiliation); affiliation is distinct from role. An affiliation lasts across a user's visits to a room.</dd></di>
<di><dt>Ban</dt><dd>To remove a user from a room such that the user is not allowed to re-enter the room (until and unless the ban has been removed). A banned user has an affiliation of "outcast".</dd></di>
<di><dt>Bare JID</dt><dd>The &lt;user@host&gt; by which a user is identified outside the context of any existing session or resource; contrast with Full JID and Occupant JID.</dd></di>
<di><dt>Full JID</dt><dd>The &lt;user@host/resource&gt; by which an online user is identified outside the context of a room; contrast with Bare JID and Occupant JID.</dd></di>
<di><dt>GC</dt><dd>The minimal "groupchat 1.0" protocol developed within the Jabber community in 1999; Old versions of MUC were backwards-compatible with GC.</dd></di>
<di><dt>History</dt><dd>A limited number of message stanzas sent to a new occupant to provide the context of current discussion.</dd></di>
<di><dt>Invitation</dt><dd>A special message sent from one user to another asking the recipient to join a room; the invitation can be sent directly (see &xep0249;) or mediated through the room (as described under <link url='#invite'>Inviting Another User to a Room</link>).</dd></di>
<di><dt>IRC</dt><dd>Internet Relay Chat.</dd></di>
<di><dt>Kick</dt><dd>To temporarily remove a participant or visitor from a room; the user is allowed to re-enter the room at any time. A kicked user has a role of "none".</dd></di>
<di><dt>Logging</dt><dd>Storage of discussions that occur within a room for public retrieval outside the context of the room.</dd></di>
<di><dt>Member</dt><dd>A user who is on the "permitted" list 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 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 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>
<di><dt>Room ID</dt><dd>The localpart of a Room JID, which might be opaque and thus lack meaning for human users (see under <link url='#bizrules'>Business Rules</link> for syntax); contrast with Room Name.</dd></di>
<di><dt>Room JID</dt><dd>The &lt;room@service&gt; address of a room.</dd></di>
<di><dt>Room Name</dt><dd>A user-friendly, natural-language name for a room, configured by the room owner and presented in Service Discovery queries; contrast with Room ID.</dd></di>
<di><dt>Room Nickname</dt><dd>The resourcepart of an Occupant JID (see <link url='#bizrules'>Business Rules</link> for syntax); this is the "friendly name" by which an occupant is known in the room.</dd></di>
<di><dt>Room Owner</dt><dd>The user who created the room or a user who has been designated by the room creator or owner as someone with owner status (if allowed); an owner is allowed to change the room configuration and destroy the room, in addition to all admin status. An owner has an affiliation of "owner".</dd></di>
<di><dt>Room Roster</dt><dd>A client's representation of the occupants in a room.</dd></di>
<di><dt>Server</dt><dd>An XMPP server that may or may not have associated with it a text-based conferencing service.</dd></di>
<di><dt>Service</dt><dd>A host that offers text-based conferencing capabilities; often but not necessarily a sub-domain of an XMPP server (e.g., conference.jabber.org).</dd></di>
<di><dt>Subject</dt><dd>A temporary discussion topic within a room.</dd></di>
<di><dt>Visit</dt><dd>A user's "session" in a room, beginning when the user enters the room (i.e., becomes an occupant) and ending when the user exits the room.</dd></di>
<di><dt>Visitor</dt><dd>In a moderated room, an occupant who does not have voice (in contrast to a participant). A visitor has a role of "visitor".</dd></di>
<di><dt>Voice</dt><dd>In a moderated room, the privilege to send messages to all occupants.</dd></di>
</dl>
</section2>
<section2 topic='Room Types' anchor='terms-rooms'>
<dl>
<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 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>
<di><dt>Semi-Anonymous Room</dt><dd>A room in which an occupant's full JID can be discovered by room admins only; contrast with Non-Anonymous Room.</dd></di>
<di><dt>Temporary Room</dt><dd>A room that is destroyed if the last occupant exits; antonym: Persistent Room.</dd></di>
<di><dt>Unmoderated Room</dt><dd>A room in which any occupant is allowed to send messages to all occupants; antonym: Moderated Room.</dd></di>
<di><dt>Unsecured Room</dt><dd>A room that anyone is allowed to enter without first providing the correct password; antonym: Password-Protected Room.</dd></di>
</dl>
</section2>
<section2 topic='Dramatis Personae' anchor='terms-personae'>
<p>Most of the examples in this document use the scenario of the witches' meeting held in a dark cave at the beginning of Act IV, Scene I of Shakespeare's <cite>Macbeth</cite>, represented here as the "coven@chat.shakespeare.lit" chatroom. The characters are as follows:</p>
<table caption='Dramatis Personae'>
<tr>
<th>Room Nickname</th>
<th>Full JID</th>
<th>Affiliation</th>
</tr>
<tr>
<td>firstwitch</td>
<td>crone1@shakespeare.lit/desktop</td>
<td>Owner</td>
</tr>
<tr>
<td>secondwitch</td>
<td>wiccarocks@shakespeare.lit/laptop</td>
<td>Admin</td>
</tr>
<tr>
<td>thirdwitch</td>
<td>hag66@shakespeare.lit/pda</td>
<td>None</td>
</tr>
</table>
</section2>
</section1>
<section1 topic='Roles, Affiliations, and Privileges' anchor='associations'>
<p>A user might be allowed to perform any number of actions in a room, from joining or sending a message to changing configuration options or destroying the room altogether. We call each permitted action a "privilege". There are two ways we might structure privileges:</p>
<ol>
<li><p>Define each privilege atomically and explicitly define each user's particular privileges; this is flexible but can be confusing to manage.</p></li>
<li><p>Define bundles of privileges that are generally applicable and assign a user-friendly "shortcut" to each bundle (e.g., "moderator" or "admin").</p></li>
</ol>
<p>MUC takes the second approach.</p>
<p>MUC also defines two different associations: long-lived affiliations and session-specific roles. These two association types are distinct from each other in MUC, since an affiliation lasts across visits, while a role lasts only for the duration of a visit. In addition, there is no one-to-one correspondence between roles and affiliations; for example, someone who is not affiliated with a room may be a (temporary) moderator, and a member may be a participant or a visitor in a moderated room. These concepts are explained more fully below.</p>
<section2 topic='Roles' anchor='roles'>
<p>The following roles are defined:</p>
<table caption='Roles'>
<tr>
<th>Name</th>
<th>Support</th>
</tr>
<tr>
<td>Moderator</td>
<td>REQUIRED</td>
</tr>
<tr>
<td>None</td>
<td>N/A (the absence of a role)</td>
</tr>
<tr>
<td>Participant</td>
<td>REQUIRED</td>
</tr>
<tr>
<td>Visitor</td>
<td>RECOMMENDED</td>
</tr>
</table>
<p>Roles are temporary in that they do not necessarily persist across a user's visits to the room and MAY change during the course of an occupant's visit to the room. An implementation MAY persist roles across visits and SHOULD do so for moderated rooms (since the distinction between visitor and participant is critical to the functioning of a moderated room).</p>
<p>There is no one-to-one mapping between roles and affiliations (e.g., a member could be a participant or a visitor).</p>
<p>A moderator is the most powerful role within the context of the room, and can to some extent manage other occupants' roles in the room. A participant has fewer privileges than a moderator, although he or she always has the right to speak. A visitor is a more restricted role within the context of a moderated room, since visitors are not allowed to send messages to all occupants (depending on room configuration, it is even possible that visitors' presence will not be broadcasted to the room).</p>
<p>Roles are granted, revoked, and maintained based on the occupant's room nickname or full JID rather than bare JID. The privileges associated with these roles, as well as the actions that trigger changes in roles, are defined below.</p>
<p>Information about roles MUST be sent in all presence stanzas generated or reflected by the room and thus sent to occupants (if the room is configured to broadcast presence for a given role).</p>
<section3 topic='Privileges' anchor='roles-priv'>
<p>For the most part, roles exist in a hierarchy. For instance, a participant can do anything a visitor can do, and a moderator can do anything a participant can do. Each role has all the privileges possessed by the next-lowest role, plus additional privileges; these privileges are specified in the following table as defaults (an implementation MAY provide configuration options that override these defaults).</p>
<table caption='Privileges Associated With Roles'>
<tr>
<th>Privilege</th>
<th>None</th>
<th>Visitor</th>
<th>Participant</th>
<th>Moderator</th>
</tr>
<tr>
<td>Present in Room</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Receive Messages</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Receive Occupant Presence</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Broadcast Presence to All Occupants</td>
<td>No</td>
<td>Yes*</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Change Availability Status</td>
<td>No</td>
<td>Yes*</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Change Room Nickname</td>
<td>No</td>
<td>Yes*</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Send Private Messages</td>
<td>No</td>
<td>Yes*</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Invite Other Users</td>
<td>No</td>
<td>Yes*</td>
<td>Yes*</td>
<td>Yes</td>
</tr>
<tr>
<td>Send Messages to All</td>
<td>No</td>
<td>No**</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Modify Subject</td>
<td>No</td>
<td>No*</td>
<td>Yes*</td>
<td>Yes</td>
</tr>
<tr>
<td>Kick Participants and Visitors</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Grant Voice</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Revoke Voice</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes***</td>
</tr>
</table>
<p>* Default; configuration settings MAY modify this privilege.</p>
<p>** An implementation MAY grant voice by default to visitors in unmoderated rooms.</p>
<p>*** A moderator MUST NOT be able to revoke voice privileges from an admin or owner.</p>
</section3>
<section3 topic='Default Roles' anchor='roles-default'>
<p>The following table summarizes the initial default roles that a service SHOULD set based on the user's affiliation (there is no role associated with the "outcast" affiliation, since such users are not allowed to enter the room).</p>
<table caption='Initial Role Based on Affiliation'>
<tr>
<th>Room Type</th>
<th>None</th>
<th>Member</th>
<th>Admin</th>
<th>Owner</th>
</tr>
<tr>
<td>Moderated</td>
<td>Visitor</td>
<td>Participant</td>
<td>Moderator</td>
<td>Moderator</td>
</tr>
<tr>
<td>Unmoderated</td>
<td>Participant</td>
<td>Participant</td>
<td>Moderator</td>
<td>Moderator</td>
</tr>
<tr>
<td>Members-Only</td>
<td>N/A *</td>
<td>Participant</td>
<td>Moderator</td>
<td>Moderator</td>
</tr>
<tr>
<td>Open</td>
<td>Participant</td>
<td>Participant</td>
<td>Moderator</td>
<td>Moderator</td>
</tr>
</table>
<p>* Entry is not permitted.</p>
</section3>
<section3 topic='Changing Roles' anchor='roles-change'>
<p>The ways in which an occupant's role changes are well-defined. Sometimes the change results from the occupant's own action (e.g., entering or exiting the room), whereas sometimes the change results from an action taken by a moderator, admin, or owner. If an occupant's role changes, a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change to all occupants (if the room is configured to broadcast presence from entities with a given role). Role changes and their triggering actions are specified in the following table.</p>
<table caption='Role State Chart'>
<tr>
<th>&gt;</th>
<th>None</th>
<th>Visitor</th>
<th>Participant</th>
<th>Moderator</th>
</tr>
<tr>
<td>None</td>
<td>--</td>
<td>Enter moderated room</td>
<td>Enter unmoderated room</td>
<td>Admin or owner enters room</td>
</tr>
<tr>
<td>Visitor</td>
<td>Exit room or be kicked by a moderator</td>
<td>--</td>
<td>Moderator grants voice</td>
<td>Admin or owner grants moderator status</td>
</tr>
<tr>
<td>Participant</td>
<td>Exit room or be kicked by a moderator</td>
<td>Moderator revokes voice</td>
<td>--</td>
<td>Admin or owner grants moderator status</td>
</tr>
<tr>
<td>Moderator</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>
</tr>
</table>
<p>* A moderator SHOULD NOT be allowed to revoke moderation privileges from someone with a higher affiliation than themselves (i.e., an unaffiliated moderator SHOULD NOT be allowed to revoke moderation privileges from an admin or an owner, and an admin SHOULD NOT be allowed to revoke moderation privileges from an owner).</p>
<p class='box'>Note: Certain roles are typically implicit in certain affiliations. For example, an admin or owner is automatically a moderator, so if an occupant is granted an affiliation of admin then the occupant will by that fact be granted a role of moderator; similarly, when an occupant is granted an affiliation of member in a moderated room, the occupant automatically has a role of participant. However, the loss of the admin affiliation does not necessarily mean that the occupant no longer has a role of moderator (since a "mere" occupant can be a moderator). Therefore, the role that is gained when an occupant is granted a certain affiliation is stable, whereas the role that is lost when an occupant loses a certain affilitation is not hardcoded and is left up to the implementation.</p>
</section3>
</section2>
<section2 topic='Affiliations' anchor='affil'>
<p>The following affiliations are defined:</p>
<ol start='1'>
<li>Owner</li>
<li>Admin</li>
<li>Member</li>
<li>Outcast</li>
<li>None (the absence of an affiliation)</li>
</ol>
<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 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 "permitted" list 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 (one result might be that the service could reserve the user's nickname 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'>
<p>For the most part, affiliations exist in a hierarchy. For instance, an owner can do anything an admin can do, and an admin can do anything a member can do. Each affiliation has all the privileges possessed by the next-lowest affiliation, plus additional privileges; these privileges are specified in the following table.</p>
<table caption='Privileges Associated With Affiliations'>
<tr>
<th>Privilege</th>
<th>Outcast</th>
<th>None</th>
<th>Member</th>
<th>Admin</th>
<th>Owner</th>
</tr>
<tr>
<td>Enter Open Room</td>
<td>No</td>
<td>Yes*</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Register with Open Room</td>
<td>No</td>
<td>Yes</td>
<td>N/A</td>
<td>N/A</td>
<td>N/A</td>
</tr>
<tr>
<td>Retrieve Member List</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Enter Members-Only Room</td>
<td>No</td>
<td>No</td>
<td>Yes*</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Ban Members and Unaffiliated Users</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Edit Member List</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Assign and Remove Moderator Role</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes**</td>
<td>Yes**</td>
</tr>
<tr>
<td>Edit Admin List</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Edit Owner List</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Change Room Configuration</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Destroy Room</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
</table>
<p>* As a default, an unaffiliated user enters a moderated room as a visitor, and enters an open room as a participant. A member enters a room as a participant. An admin or owner enters a room as a moderator.</p>
<p>** As noted, a moderator SHOULD NOT be allowed to revoke moderation privileges from someone with a higher affiliation than themselves (i.e., an unaffiliated moderator SHOULD NOT be allowed to revoke moderation privileges from an admin or an owner, and an admin SHOULD NOT be allowed to revoke moderation privileges from an owner).</p>
</section3>
<section3 topic='Changing Affiliations' anchor='affil-change'>
<p>The ways in which a user's affiliation changes are well-defined. Sometimes the change results from the user's own action (e.g., registering as a member of the room), whereas sometimes the change results from an action taken by an admin or owner. If a user's affiliation changes, a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that to all occupants (if the room is configured to broadcast presence from entities with a given role). Affiliation changes and their triggering actions are specified in the following table.</p>
<table caption='Affiliation State Chart'>
<tr>
<th>&gt;</th>
<th>Outcast</th>
<th>None</th>
<th>Member</th>
<th>Admin</th>
<th>Owner</th>
</tr>
<tr>
<td>Outcast</td>
<td>--</td>
<td>Admin or owner removes ban</td>
<td>Admin or owner adds user to member list</td>
<td>Owner adds user to admin list</td>
<td>Owner adds user to owner list</td>
</tr>
<tr>
<td>None</td>
<td>Admin or owner applies ban</td>
<td>--</td>
<td>Admin or owner adds user to member list, or user registers as member (if allowed)</td>
<td>Owner adds user to admin list</td>
<td>Owner adds user to owner list</td>
</tr>
<tr>
<td>Member</td>
<td>Admin or owner applies ban</td>
<td>Admin or owner changes affiliation to "none"</td>
<td>--</td>
<td>Owner adds user to admin list</td>
<td>Owner adds user to owner list</td>
</tr>
<tr>
<td>Admin</td>
<td>Owner applies ban</td>
<td>Owner changes affiliation to "none"</td>
<td>Owner changes affiliation to "member"</td>
<td>--</td>
<td>Owner adds user to owner list</td>
</tr>
<tr>
<td>Owner</td>
<td>Owner applies ban</td>
<td>Owner changes affiliation to "none"</td>
<td>Owner changes affiliation to "member"</td>
<td>Owner changes affiliation to "admin"</td>
<td>--</td>
</tr>
</table>
</section3>
</section2>
</section1>
<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 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'
to='shakespeare.lit'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
]]></example>
<p>The server then returns the services that are associated with it.</p>
<example caption='Server Returns Disco Items Result'><![CDATA[
<iq from='shakespeare.lit'
id='h7ns81g'
to='hag66@shakespeare.lit/pda'
type='result'>
<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 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'
to='chat.shakespeare.lit'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>
<p>The service MUST return its identity and the features it supports.</p>
<example caption='Service Returns Disco Info Result'><![CDATA[
<iq from='chat.shakespeare.lit'
id='lx09df27'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity
category='conference'
name='Shakespearean Chat Service'
type='text'/>
<feature var='http://jabber.org/protocol/muc'/>
</query>
</iq>
]]></example>
</section2>
<section2 topic='Discovering Rooms' anchor='disco-rooms'>
<p>The service discovery items ("disco#items") protocol enables an entity to query a service for a list of associated items, which in the case of a chat service would consist of the specific chat rooms hosted by the service.</p>
<example caption='Entity Queries Chat Service for Rooms'><![CDATA[
<iq from='hag66@shakespeare.lit/pda'
id='zb8q41f4'
to='chat.shakespeare.lit'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
]]></example>
<p>The service SHOULD return a full list of the public rooms it hosts (i.e., not return any rooms that are hidden).</p>
<example caption='Service Returns Disco Items Result'><![CDATA[
<iq from='chat.shakespeare.lit'
id='zb8q41f4'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item jid='heath@chat.shakespeare.lit'
name='A Lonely Heath'/>
<item jid='coven@chat.shakespeare.lit'
name='A Dark Cave'/>
<item jid='forres@chat.shakespeare.lit'
name='The Palace'/>
<item jid='inverness@chat.shakespeare.lit'
name='Macbeth&apos;s Castle'/>
</query>
</iq>
]]></example>
<p>If the full list of rooms is large (see <cite>XEP-0030</cite> for details), the service MAY return only a partial list of rooms. If it does so, it SHOULD include a &lt;set/&gt; element qualified by the 'http://jabber.org/protocol/rsm' namespace (as defined in &xep0059;) to indicate that the list is not the full result set.</p>
<example caption='Service Returns Limited List of Disco Items Result'><![CDATA[
<iq from='chat.shakespeare.lit'
id='hx51v49s'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item jid='alls-well-that-ends-well@chat.shakespeare.lit'/>
<item jid='as-you-like-it@chat.shakespeare.lit'/>
<item jid='cleopatra@chat.shakespeare.lit'/>
<item jid='comedy-of-errors@chat.shakespeare.lit'/>
<item jid='coriolanus@chat.shakespeare.lit'/>
<item jid='cymbeline@chat.shakespeare.lit'/>
<item jid='hamlet@chat.shakespeare.lit'/>
<item jid='henry-the-fourth-one@chat.shakespeare.lit'/>
<item jid='henry-the-fourth-two@chat.shakespeare.lit'/>
<item jid='henry-the-fifth@chat.shakespeare.lit'/>
<set xmlns='http://jabber.org/protocol/rsm'>
<first index='0'>alls-well-that-ends-well@chat.shakespeare.lit</first>
<last>henry-the-fifth@chat.shakespeare.lit</last>
<count>37</count>
</set>
</query>
</iq>
]]></example>
</section2>
<section2 topic='Querying for Room Information' anchor='disco-roominfo'>
<p>Using the disco#info protocol, an entity may also query a specific chat room for more detailed information about the room. An entity SHOULD do so before entering a room in order to determine the privacy and security profile of the room configuration (see the <link url='#security'>Security Considerations</link> for details).</p>
<example caption='Entity Queries for Information about a Specific Chat Room'><![CDATA[
<iq from='hag66@shakespeare.lit/pda'
id='ik3vs715'
to='coven@chat.shakespeare.lit'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>
<p>The room MUST return its identity and SHOULD return the features it supports:</p>
<example caption='Room Returns Disco Info Result'><![CDATA[
<iq from='coven@chat.shakespeare.lit'
id='ik3vs715'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity
category='conference'
name='A Dark Cave'
type='text'/>
<feature var='http://jabber.org/protocol/muc'/>
<feature var='http://jabber.org/protocol/muc#stable_id'/>
<feature var='muc_passwordprotected'/>
<feature var='muc_hidden'/>
<feature var='muc_temporary'/>
<feature var='muc_open'/>
<feature var='muc_unmoderated'/>
<feature var='muc_nonanonymous'/>
</query>
</iq>
]]></example>
<p>Note: The room SHOULD return the materially-relevant features it supports, such as password protection and room moderation (these are listed fully in the feature registry maintained by the XMPP Registrar; see also the <link url='#registrar'>XMPP Registrar</link> section of this document).</p>
<p>A chatroom MAY return more detailed information in its disco#info response using &xep0128;, identified by inclusion of a hidden FORM_TYPE field whose value is "http://jabber.org/protocol/muc#roominfo". Such information might include a more verbose description of the room, the current room subject, and the current number of occupants in the room:</p>
<example caption='Room Returns Extended Disco Info Result'><![CDATA[
<iq from='coven@chat.shakespeare.lit'
id='ik3vs715'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity
category='conference'
name='A Dark Cave'
type='text'/>
<feature var='http://jabber.org/protocol/muc'/>
<feature var='muc_passwordprotected'/>
<feature var='muc_hidden'/>
<feature var='muc_temporary'/>
<feature var='muc_open'/>
<feature var='muc_unmoderated'/>
<feature var='muc_nonanonymous'/>
<x xmlns='jabber:x:data' type='result'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/muc#roominfo</value>
</field>
<field var='muc#roominfo_description'
label='Description'>
<value>The place for all good witches!</value>
</field>
<field var='muc#roominfo_changesubject'
label='Occupants May Change the Subject'>
<value>true</value>
</field>
<field var='muc#roominfo_contactjid'
label='Contact Addresses'>
<value>crone1@shakespeare.lit</value>
</field>
<field var='muc#roominfo_subject'
label='Current Discussion Topic'>
<value>Spells</value>
</field>
<field var='muc#roomconfig_changesubject'
label='Subject can be modified'>
<value>true</value>
</field>
<field var='muc#roominfo_occupants'
label='Number of occupants'>
<value>3</value>
</field>
<field var='muc#roominfo_ldapgroup'
label='Associated LDAP Group'>
<value>cn=witches,dc=shakespeare,dc=lit</value>
</field>
<field var='muc#roominfo_lang'
label='Language of discussion'>
<value>en</value>
</field>
<field var='muc#roominfo_logs'
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>
</field>
</x>
</query>
</iq>
]]></example>
<p>Some extended room information is dynamically generated (e.g., the URL for discussion logs, which may be based on service-wide configuration), whereas other information is based on the more-stable room configuration, which is why any field defined for the <link url='#registrar-formtype-owner'>muc#roomconfig FORM_TYPE</link> can be included in the extended service discovery fields (as shown above for the "muc#roomconfig_changesubject" field).</p>
<p>Note: The foregoing extended service discovery fields for the 'http://jabber.org/protocol/muc#roominfo' FORM_TYPE are examples only and might be supplemented in the future via the mechanisms described in the <link url="#registrar-formtype">Field Standardization</link> section of this document.</p>
</section2>
<section2 topic='Querying for Room Items' anchor='disco-roomitems'>
<p>An entity MAY also query a specific chat room for its associated items:</p>
<example caption='Entity Queries for Items Associated with a Specific Chat Room'><![CDATA[
<iq from='hag66@shakespeare.lit/pda'
id='kl2fax27'
to='coven@chat.shakespeare.lit'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
]]></example>
<p>An implementation MAY return a list of existing occupants if that information is publicly available, or return no list at all if this information is kept private. Implementations and deployments are advised to turn off such information sharing by default.</p>
<example caption='Room Returns Disco Items Result (Items are Public)'><![CDATA[
<iq from='coven@chat.shakespeare.lit'
id='kl2fax27'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item jid='coven@chat.shakespeare.lit/firstwitch'/>
<item jid='coven@chat.shakespeare.lit/secondwitch'/>
</query>
</iq>
]]></example>
<p>Note: These &lt;item/&gt; elements are qualified by the disco#items namespace, not the muc namespace; this means that they cannot possess 'affiliation' or 'role' attributes, for example.</p>
<p>If the list of occupants is private, the room MUST return an empty &QUERY; element, in accordance with <cite>XEP-0030</cite>.</p>
<example caption='Room Returns Empty Disco Items Result (Items are Private)'><![CDATA[
<iq from='coven@chat.shakespeare.lit'
id='kl2fax27'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
]]></example>
</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 &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'>
<p>An entity might want to discover if one of the entity's contacts supports the Multi-User Chat protocol (e.g., before attempting to invite the contact to a room). This can be done using Service Discovery.</p>
<example caption='Entity Queries Contact Regarding MUC Support'><![CDATA[
<iq from='hag66@shakespeare.lit/pda'
id='yh2fs843'
to='wiccarocks@shakespeare.lit/laptop'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>
<p>The client SHOULD return its identity and the features it supports.</p>
<example caption='Contact Returns Disco Info Result'><![CDATA[
<iq from='wiccarocks@shakespeare.lit/laptop'
id='yh2fs843'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity
category='client'
type='pc'/>
...
<feature var='http://jabber.org/protocol/muc'/>
...
</query>
</iq>
]]></example>
<p>An entity may also query a contact regarding which rooms the contact is in. This is done by querying the contact's full JID (&lt;user@host/resource&gt;) while specifying the well-known Service Discovery node 'http://jabber.org/protocol/muc#rooms'.</p>
<example caption='Entity Queries Contact for Current Rooms'><![CDATA[
<iq from='hag66@shakespeare.lit/pda'
id='gp7w61v3'
to='wiccarocks@shakespeare.lit/laptop'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#items'
node='http://jabber.org/protocol/muc#rooms'/>
</iq>
]]></example>
<example caption='Contact Returns Room Query Result'><![CDATA[
<iq from='wiccarocks@shakespeare.lit/laptop'
id='gp7w61v3'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'
node='http://jabber.org/protocol/muc#rooms'>
<item jid='coven@chat.shakespeare.lit'/>
<item jid='characters@conference.shakespeare.lit'/>
</query>
</iq>
]]></example>
<p>Optionally, the contact MAY include its roomnick as the value of the 'name' attribute:</p>
<code><![CDATA[
...
<item jid='coven@chat.shakespeare.lit'
name='secondwitch'/>
...
]]></code>
<p>If this information is private, the user MUST return an empty &QUERY; element, in accordance with <cite>XEP-0030</cite>.</p>
</section2>
</section1>
<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 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 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'>
<p>The order of events involved in joining a room needs to be consistent so that clients can know which events to expect when. After a client sends presence to join a room, the MUC service MUST send it events in the following order:</p>
<ol>
<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</li>
<li>Live messages, presence updates, new user joins, etc.</li>
</ol>
</section2>
<section2 topic='Entering a Room' anchor='enter'>
<section3 topic='Basic MUC Protocol' anchor='enter-muc'>
<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. </p>
<p>MUC clients MUST 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>In this example, a user with a full JID of "hag66@shakespeare.lit/pda" has requested to enter the room "coven" on the "chat.shakespeare.lit" chat service with a room nickname of "thirdwitch".</p>
<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>
<p>If the user does not specify a room nickname (note the bare JID on the 'from' address in the following example), the service MUST return a &badjid; error:</p>
<example caption='No Nickname Specified'><![CDATA[
<presence
from='coven@chat.shakespeare.lit'
id='273hs51g'
to='hag66@shakespeare.lit/pda'
type='error'>
<error by='coven@chat.shakespeare.lit' type='modify'>
<jid-malformed 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>
<p>When a MUC service receives an &lt;x/&gt; tagged join stanza from an already-joined client (as identified by the client's full JID), the service should assume that the client lost its synchronization, and therefore it SHOULD send exactly the same stanzas to the client as if it actually just joined the MUC. The server MAY also send a presence update to the other participants according to the received join presence.</p>
</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 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'
id='3DCB0401-D7CF-4E31-BE05-EDF8D057BFBD'
to='hag66@shakespeare.lit/pda'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='owner' role='moderator'/>
</x>
</presence>
<presence
from='coven@chat.shakespeare.lit/secondwitch'
id='C2CD9EE3-8421-431E-854A-A2AD0CE2E23D'
to='hag66@shakespeare.lit/pda'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='admin' role='moderator'/>
</x>
</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 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'
id='27C55F89-1C6A-459A-9EB5-77690145D624'
to='crone1@shakespeare.lit/desktop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='participant'/>
</x>
</presence>
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='9E757BAE-8AC8-4093-AA9C-407F6AEF15D6'
to='wiccarocks@shakespeare.lit/laptop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='participant'/>
</x>
</presence>
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='026B3509-2CCE-4D69-96D6-25F41FFDC408'
to='hag66@shakespeare.lit/pda'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='participant'/>
<status code='110'/>
</x>
</presence>
]]></example>
<p>In this example, initial room presence is being sent from the new occupant (thirdwitch) to all occupants, including the new occupant.</p>
<p>As shown in the last stanza, the "self-presence" sent by the room to the new user MUST include a status code of 110 so that the user knows this presence refers to itself as an occupant. This self-presence MUST NOT be sent to the new occupant until the room has sent the presence of all other occupants to the new occupant; this enables the new occupant to know when it has finished receiving the room roster.</p>
<p>The service MAY rewrite the new occupant's roomnick (e.g., if roomnicks are locked down or based on some other policy).</p>
<p>In particular, if roomnicks are locked down then the service MUST do one of the following.</p>
<p>If the user has connected using a "groupchat 1.0" client (as indicated on joining the room by the lack of the MUC extension), then the service SHOULD deny the nickname change request and return a presence stanza of type "error" with a &notacceptable; error condition:</p>
<example caption='Service Denies Room Join Because Roomnicks Are Locked Down'><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='ng91xs69'
to='hag66@shakespeare.lit/pda'
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error by='coven@chat.shakespeare.lit' type='cancel'>
<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
]]></example>
<p>If the user has connected using a MUC client (as indicated on joining the room by inclusion of the MUC extension), then the service MUST allow the client to enter the room, modify the nick in accordance with the lockdown policy, and include a status code of "210" in the presence broadcast that it sends to the new occupant.</p>
<example caption="Service Sends New Occupant's Presence to New Occupant"><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='n13mt3l'
to='hag66@shakespeare.lit/pda'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='participant'/>
<status code='110'/>
<status code='210'/>
</x>
</presence>
]]></example>
<p>Note: The order of the presence stanzas sent to the new occupant is important. The service MUST first send the complete list of the existing occupants to the new occupant and only then send the new occupant's own presence to the new occupant. This helps the client know when it has received the complete "room roster". For tracking purposes, the room might also reflect the original 'id' value if provided in the presence stanza sent by the user.</p>
<p>After sending the presence broadcast (and only after doing so), the service MAY then send discussion history, the room subject, live messages, presence updates, and other in-room traffic.</p>
</section3>
<section3 topic='Non-Anonymous Rooms' anchor='enter-nonanon'>
<p>If the room is non-anonymous, the service MUST send the new occupant's full JID to all occupants using extended presence information in an &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an &lt;item/&gt; child with a 'jid' attribute specifying the occupant's full JID:</p>
<example caption="Service Sends Full JID to All Occupants"><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='17232D15-134F-43C8-9A29-61C20A64B236'
to='crone1@shakespeare.lit/desktop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='none'
jid='hag66@shakespeare.lit/pda'
role='participant'/>
</x>
</presence>
[ ... ]
]]></example>
<p>If the user is entering a room that is non-anonymous (i.e., which informs all occupants of each occupant's full JID as shown above), the service MUST warn the user by including a status code of "100" in the initial presence that the room sends to the new occupant:</p>
<example caption="Service Sends New Occupant's Presence to New Occupant"><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='n13mt3l'
to='hag66@shakespeare.lit/pda'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='participant'/>
<status code='100'/>
<status code='110'/>
<status code='210'/>
</x>
</presence>
]]></example>
<p>The inclusion of the status code assists clients in presenting their own notification messages (e.g., information appropriate to the user's locality).</p>
</section3>
<section3 topic='Semi-Anonymous Rooms' anchor='enter-semianon'>
<p>If the room is semi-anonymous, the service MUST send presence from the new occupant to all occupants as specified above (i.e., 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), but MUST include the new occupant's full JID only in the presence notifications it sends to occupants with a role of "moderator" and not to non-moderator occupants.</p>
<p>(Note: All subsequent examples include the 'jid' attribute for each &lt;item/&gt; element, even though this information is not sent to non-moderators in semi-anonymous rooms.)</p>
</section3>
<section3 topic='Password-Protected Rooms' anchor='enter-pw'>
<p>If the room requires a password and the user did not supply one (or the password provided is incorrect), the service MUST deny access to the room and inform the user that they are unauthorized; this is done by returning a presence stanza of type "error" specifying a &notauthorized; error:</p>
<example caption='Service Denies Access Because No Password Provided'><![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='auth'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
]]></example>
<p>Passwords SHOULD be supplied with the presence stanza sent when entering the room, contained within an &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc' namespace and containing a &lt;password/&gt; child. Passwords are to be sent as cleartext; no other authentication methods are supported at this time, and any such authentication or authorization methods shall be defined in a separate specification (see the <link url='#security'>Security Considerations</link> section of this document).</p>
<example caption='User Provides Password On Entering a Room'><![CDATA[
<presence
from='hag66@shakespeare.lit/pda'
id='djn4714'
to='coven@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<password>cauldronburn</password>
</x>
</presence>
]]></example>
</section3>
<section3 topic='Members-Only Rooms' anchor='enter-members'>
<p>If the room is members-only but the user is not on the member list, the service MUST deny access to the room and inform the user that they are not allowed to enter the room; this is done by returning a presence stanza of type "error" specifying a &registration; error condition:</p>
<example caption='Service Denies Access Because User Is Not on Member List'><![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='auth'>
<registration-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
]]></example>
</section3>
<section3 topic='Banned Users' anchor='enter-banned'>
<p>If the user has been banned from the room (i.e., has an affiliation of "outcast"), the service MUST deny access to the room and inform the user of the fact that they are banned; this is done by returning a presence stanza of type "error" specifying a &forbidden; error condition:</p>
<example caption='Service Denies Access Because User is Banned'><![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='auth'>
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
]]></example>
</section3>
<section3 topic='Nickname Conflict' anchor='enter-conflict'>
<p>If the room already contains another user with the nickname desired by the user seeking to enter the room (or if the nickname is reserved by another user on the member list), the service MUST deny access to the room and inform the user of the conflict; this is done by returning a presence stanza of type "error" specifying a &conflict; error condition:</p>
<example caption='Service Denies Access Because of Nick Conflict'><![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'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
]]></example>
<p>However, if the bare JID &LOCALBARE; of the present occupant matches the bare JID of the user seeking to enter the room, then the service SHOULD allow entry to the user, so that the user has two (or more) in-room "sessions" with the same roomnick, one for each resource. If a service allows more than one occupant with the same bare JID and the same room nickname, it MUST route in-room messages to all of the user's resources and allow all of the user's resources to send messages to the room; it is up to the implementation whether to route private messages to all resources or only one resource (based on presence priority or some other algorithm); however, it is RECOMMENDED to route to all resources.</p>
<p>How nickname conflicts are determined is up to the implementation (e.g., whether the service applies a case folding routine, a stringprep profile such as Resourceprep or Nodeprep, etc.).</p>
</section3>
<section3 topic='Max Users' anchor='enter-maxusers'>
<p>If the room has reached its maximum number of occupants, the service SHOULD deny access to the room and inform the user of the restriction; this is done by returning a presence stanza of type "error" specifying a &unavailable; error condition:</p>
<example caption='Service Informs User that Room Occupant Limit Has Been Reached'><![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='wait'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
]]></example>
<p>Alternatively, the room could kick an "idle user" in order to free up space (where the definition of "idle user" is up to the implementation).</p>
<p>If the room has reached its maximum number of occupants and a room admin or owner attempts to join, the room MUST allow the admin or owner to join, up to some reasonable number of additional occupants; this helps to prevent denial of service attacks caused by stuffing the room with non-admin users.</p>
</section3>
<section3 topic='Locked Room' anchor='enter-locked'>
<p>If a user attempts to enter a room while it is "locked" (i.e., before the room creator provides an initial configuration and therefore before the room officially exists), the service MUST refuse entry and return an &notfound; error to the user:</p>
<example caption='Service Denies Access Because Room Does Not (Yet) 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>
</section3>
<section3 topic='Nonexistent Room' anchor='enter-nonexistent'>
<p>If the room does not already exist when the user seeks to enter it, the service SHOULD create it; however, this is not required, since an implementation or deployment MAY choose to restrict the privilege of creating rooms. For details, see the <link url='#createroom'>Creating a Room</link> section of this document.</p>
</section3>
<section3 topic='Room Logging' anchor='enter-logging'>
<p>If the user is entering a room in which the discussions are logged to a public archive (often accessible via HTTP), the service SHOULD allow the user to enter the room but MUST also warn the user that the discussions are logged. This is done by including a status code of "170" in the initial presence that the room sends to the new occupant:</p>
<example caption="Service Sends New Occupant's Presence to New Occupant"><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='n13mt3l'
to='hag66@shakespeare.lit/pda'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='participant'/>
<status code='100'/>
<status code='110'/>
<status code='170'/>
<status code='210'/>
</x>
</presence>
]]></example>
</section3>
<section3 topic='Discussion History' anchor='enter-history'>
<p>After sending initial presence as shown above, depending on local service policy or room configuration a room MAY send discussion history to the new occupant. (The room MUST NOT send any discussion history before it finishes sending room presence as specified in the <link url='#enter-pres'>Presence Broadcast</link> section of this document.) Whether such history is sent, and how many messages comprise the history, shall be determined by the chat service implementation or specific deployment depending on local service policy or room configuration.</p>
<example caption='Delivery of Discussion History'><![CDATA[
<message
from='coven@chat.shakespeare.lit/firstwitch'
id='162BEBB1-F6DB-4D9A-9BD8-CFDCC801A0B2'
to='hecate@shakespeare.lit/broom'
type='groupchat'>
<body>Thrice the brinded cat hath mew'd.</body>
<delay xmlns='urn:xmpp:delay'
from='coven@chat.shakespeare.lit'
stamp='2002-10-13T23:58:37Z'/>
</message>
<message
from='coven@chat.shakespeare.lit/secondwitch'
id='90057840-30FD-4141-AA44-103EEDF218FC'
to='hecate@shakespeare.lit/broom'
type='groupchat'>
<body>Thrice and once the hedge-pig whined.</body>
<delay xmlns='urn:xmpp:delay'
from='coven@chat.shakespeare.lit'
stamp='2002-10-13T23:58:43Z'/>
</message>
<message
from='coven@chat.shakespeare.lit/thirdwitch'
id='77E07BB0-55CF-4BD4-890E-3F7C0E686BBD'
to='hecate@shakespeare.lit/broom'
type='groupchat'>
<body>Harpier cries 'Tis time, 'tis time.</body>
<delay xmlns='urn:xmpp:delay'
from='coven@chat.shakespeare.lit'
stamp='2002-10-13T23:58:49Z'/>
</message>
]]></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. 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
from='coven@chat.shakespeare.lit/firstwitch'
id='162BEBB1-F6DB-4D9A-9BD8-CFDCC801A0B2'
to='hecate@shakespeare.lit/broom'
type='groupchat'>
<body>Thrice the brinded cat hath mew'd.</body>
<delay xmlns='urn:xmpp:delay'
from='coven@chat.shakespeare.lit'
stamp='2002-10-13T23:58:37Z'/>
<addresses xmlns='http://jabber.org/protocol/address'>
<address type='ofrom' jid='crone1@shakespeare.lit/desktop'/>
</addresses>
</message>
]]></example>
</section3>
<section3 topic='Managing Discussion History' anchor='enter-managehistory'>
<p>A user might want to manage the amount of discussion history provided on entering a room (perhaps because the user is on a low-bandwidth connection or is using a small-footprint client). This is accomplished by including a &lt;history/&gt; child in the initial presence stanza sent when joining the room. There are four allowable attributes for this element:</p>
<table caption='History Management Attributes'>
<tr>
<th>Attribute</th>
<th>Datatype</th>
<th>Meaning</th>
</tr>
<tr>
<td>maxchars</td>
<td>int</td>
<td>Limit the total number of characters in the history to "X" (where the character count is the characters of the complete XML stanzas, not only their XML character data).</td>
</tr>
<tr>
<td>maxstanzas</td>
<td>int</td>
<td>Limit the total number of messages in the history to "X".</td>
</tr>
<tr>
<td>seconds</td>
<td>int</td>
<td>Send only the messages received in the last "X" seconds.</td>
</tr>
<tr>
<td>since</td>
<td>dateTime</td>
<td>Send only the messages received since the UTC datetime specified (which MUST conform to the DateTime profile specified in &xep0082;).</td>
</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>Note: It is known that not all service implementations support MUC history management, so in practice a client might not be able to 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
from='hag66@shakespeare.lit/pda'
id='n13mt3l'
to='coven@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history maxchars='65000'/>
</x>
</presence>
]]></example>
<example caption='User Requests Limit on Number of Messages in History'><![CDATA[
<presence
from='hag66@shakespeare.lit/pda'
id='n13mt3l'
to='coven@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history maxstanzas='20'/>
</x>
</presence>
]]></example>
<example caption='User Requests History in Last 3 Minutes'><![CDATA[
<presence
from='hag66@shakespeare.lit/pda'
id='n13mt3l'
to='coven@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history seconds='180'/>
</x>
</presence>
]]></example>
<example caption='User Requests All History Since the Beginning of the Unix Era'><![CDATA[
<presence
from='hag66@shakespeare.lit/pda'
id='n13mt3l'
to='coven@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history since='1970-01-01T00:00:00Z'/>
</x>
</presence>
]]></example>
<p>Obviously the service SHOULD NOT return all messages sent in the room since the beginning of the Unix era, and SHOULD appropriately limit the amount of history sent to the user based on service or room defaults.</p>
<example caption='User Requests No History'><![CDATA[
<presence
from='hag66@shakespeare.lit/pda'
id='n13mt3l'
to='coven@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history maxchars='0'/>
</x>
</presence>
]]></example>
</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 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. In addition, the subject SHOULD be stamped with &xep0203; information qualified by the 'urn:xmpp:delay' namespace to indicate the time at which the subject was last modified. If the &lt;delay/&gt; element is included, its 'from' attribute MUST be set to the JID of the room itself.</p>
<example caption='Service Informs New Occupant of Room Subject'><![CDATA[
<message
from='coven@chat.shakespeare.lit/secondwitch'
id='F437C672-D438-4BD3-9BFF-091050D32EE2'
to='crone1@shakespeare.lit/desktop'
type='groupchat'>
<subject>Fire Burn and Cauldron Bubble!</subject>
<delay xmlns='urn:xmpp:delay' from='coven@chat.shakespeare.lit' stamp='1610-04-20T00:00:00Z'/>
</message>
]]></example>
<p>Interoperability Note: The &lt;delay/&gt; element has been specified in version 1.34.0 of this document. Hence, consuming entities need to be able to deal with servers which do not send a &lt;delay/&gt; element. Most notably, this means that the presence of the &lt;delay/&gt; element cannot be used to distinguish a historic vs. a live subject change.</p>
<p>If there is no subject set, the room MUST return an empty &SUBJECT; element. The &lt;delay/&gt; SHOULD be included if the subject was actively cleared and MAY be omitted if the room never had a subject set.</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'>
<p>After the room has sent the room subject, it SHALL begin to send live messages, presence changes, occupant "joins" and "leaves", and other real-time traffic to the new occupant, as described in other sections of this document.</p>
</section3>
<section3 topic='Error Conditions' anchor='enter-errorcodes'>
<p>The following table summarizes the XMPP error conditions that can be returned to an entity that attempts to enter a MUC room.</p>
<table caption='Error Conditions for Entering a Room'>
<tr>
<th>Condition</th>
<th>Purpose</th>
</tr>
<tr>
<td>&notauthorized;</td>
<td>Inform user that a password is required</td>
</tr>
<tr>
<td>&forbidden;</td>
<td>Inform user that he or she is banned from the room</td>
</tr>
<tr>
<td>&notfound;</td>
<td>Inform user that the room does not exist</td>
</tr>
<tr>
<td>&notallowed;</td>
<td>Inform user that room creation is restricted</td>
</tr>
<tr>
<td>&notacceptable;</td>
<td>Inform user that the reserved roomnick must be used</td>
</tr>
<tr>
<td>&registration;</td>
<td>Inform user that he or she is not on the member list</td>
</tr>
<tr>
<td>&conflict;</td>
<td>Inform user that his or her desired room nickname is in use or registered by another user</td>
</tr>
<tr>
<td>&unavailable;</td>
<td>Inform user that the maximum number of users has been reached</td>
</tr>
</table>
</section3>
<section3 topic='Groupchat 1.0 Protocol' anchor='enter-gc'>
<p>In the old groupchat 1.0 protocol, entering a room 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'
to='coven@chat.shakespeare.lit/thirdwitch'/>
]]></example>
<p>This behavior can not be distinguished from a presence update from a MUC-supporting client that was desynchronized from the room. Treating this as a groupchat 1.0 join will mask the error and leave the client in a partially-synchronized state. Therefore, starting with version 1.32 of this specification, it is RECOMMENDED that a service receiving a &lt;presence&gt; without an &lt;x&gt; element from a non-occupant full-JID responds with an explicit kick to that client. The kick MUST contain the status codes 110 (occupant's presence), 307 (kick), and 333 (kick due to technical problems).</p>
<example caption='Service Response to groupchat 1.0 join / non-occupant presence update'><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
to='hag66@shakespeare.lit/pda'
type='unavailable'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='none' role='none'>
<reason>You are not in the room.</reason>
</item>
<status code='110'/>
<status code='307'/>
<status code='333'/>
</x>
</presence>
]]></example>
</section3>
</section2>
<section2 topic='Occupant Modification of the Room Subject' anchor='subject-occupant'>
<p>If allowed in accordance with room configuration, a mere occupant MAY be allowed to change the subject in a room. For details, see the <link url='#subject-mod'>Modifying the Room Subject</link> section of this document.</p>
</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 &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'
id='hysf1v37'
to='coven@chat.shakespeare.lit'
type='groupchat'>
<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 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'
id='hysf1v37'
to='crone1@shakespeare.lit/desktop'
type='groupchat'>
<body>Harpier cries: 'tis time, 'tis time.</body>
</message>
<message
from='coven@chat.shakespeare.lit/thirdwitch'
id='hysf1v37'
to='wiccarocks@shakespeare.lit/laptop'
type='groupchat'>
<body>Harpier cries: 'tis time, 'tis time.</body>
</message>
<message
from='coven@chat.shakespeare.lit/thirdwitch'
id='hysf1v37'
to='hag66@shakespeare.lit/pda'
type='groupchat'>
<body>Harpier cries: 'tis time, 'tis time.</body>
</message>
]]></example>
<p>The service SHOULD reflect the message with the same 'id' that was generated by the client, to allow clients to track their outbound messages. If the client did not provide an 'id', the server MAY generate an 'id' and use it for all reflections of the same message (e.g. using a UUID as defined in &rfc4122;).</p>
<p><strong>Note:</strong> the requirement to reflect the 'id' attribute was added in version 1.31 of this XEP. Servers following the new specification SHOULD advertise that with a disco info feature of 'http://jabber.org/protocol/muc#stable_id' on both the service domain and on individual MUCs, so that clients can check for support.</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 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>
<p>To allow for proper synchronization of these messages to the user's other clients by &xep0280;, the sending client SHOULD add an &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc#user' namespace to the message.</p>
<p><strong>Note:</strong> because this requirement was only added in revision 1.28 of this XEP, receiving entities MUST NOT rely on the existence of the &lt;x/&gt; element on private messages for proper processing.</p>
<example caption='Occupant Sends Private Message'><![CDATA[
<message
from='wiccarocks@shakespeare.lit/laptop'
id='hgn27af1'
to='coven@chat.shakespeare.lit/firstwitch'
type='chat'>
<body>I'll give thee a wind.</body>
<x xmlns='http://jabber.org/protocol/muc#user' />
</message>
]]></example>
<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. The service SHOULD add the &lt;x/&gt; element if the message does not contain it already.</p>
<example caption='Recipient Receives the Private Message'><![CDATA[
<message
from='coven@chat.shakespeare.lit/secondwitch'
id='hgn27af1'
to='crone1@shakespeare.lit/desktop'
type='chat'>
<body>I'll give thee a wind.</body>
<x xmlns='http://jabber.org/protocol/muc#user' />
</message>
]]></example>
<p>If the sender attempts to send a private message of type "groupchat" to a particular occupant, the service MUST refuse to deliver the message (since the recipient's client would expect in-room messages to be of type "groupchat") and return a &badrequest; error to the sender:</p>
<example caption='Occupant Attempts to Send a Message of Type "Groupchat" to a Particular Occupant'><![CDATA[
<message
from='wiccarocks@shakespeare.lit/laptop'
id='bx71f29k'
to='coven@chat.shakespeare.lit/firstwitch'
type='groupchat'>
<body>I'll give thee a wind.</body>
</message>
<message
from='coven@chat.shakespeare.lit/firstwitch'
id='bx71f29k'
to='wiccarocks@shakespeare.lit/laptop'
type='error'>
<body>I'll give thee a wind.</body>
<error by='coven@chat.shakespeare.lit' type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</message>
]]></example>
<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 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'
id='ifd1c35'
to='coven@chat.shakespeare.lit/oldhag'/>
]]></example>
<p>The service then sends two presence stanzas to the full JID of each occupant (including the occupant who is changing his or her room nickname), one of type "unavailable" for the old nickname and one indicating availability for the new nickname.</p>
<p>The unavailable presence MUST contain the following as extended presence information in an &lt;x/&gt; element qualified by the 'http://jabber.org/protocol/muc#user' namespace:</p>
<ul>
<li>The new nickname (in this case, nick='oldhag')</li>
<li>A status code of 303</li>
</ul>
<p>This enables the recipients to correlate the old roomnick with the new roomnick.</p>
<example caption='Service Updates Nick'><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='5C1B95B3-7CCC-4422-A952-8885A050BDE9'
to='crone1@shakespeare.lit/desktop'
type='unavailable'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
nick='oldhag'
role='participant'/>
<status code='303'/>
</x>
</presence>
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='B0E6ABD5-575D-42F0-8242-569004D88F73'
to='wiccarocks@shakespeare.lit/laptop'
type='unavailable'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
nick='oldhag'
role='participant'/>
<status code='303'/>
</x>
</presence>
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='DC352437-C019-40EC-B590-AF29E879AF98'
to='hag66@shakespeare.lit/pda'
type='unavailable'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
nick='oldhag'
role='participant'/>
<status code='303'/>
<status code='110'/>
</x>
</presence>
<presence
from='coven@chat.shakespeare.lit/oldhag'
id='19E41EB3-3F4C-444F-8A1B-713A8860980C'
to='crone1@shakespeare.lit/desktop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
role='participant'/>
</x>
</presence>
<presence
from='coven@chat.shakespeare.lit/oldhag'
id='79225CEA-F610-49BE-9B97-FEFA8737185B'
to='wiccarocks@shakespeare.lit/laptop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
role='participant'/>
</x>
</presence>
<presence
from='coven@chat.shakespeare.lit/oldhag'
id='5B4F27A4-25ED-43F7-A699-382C6B4AFC67'
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'/>
</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>
<example caption='Service Denies Nickname Change Because of Nick Conflict'><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='ifd1c35'
to='hag66@shakespeare.lit/pda'
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error by='coven@chat.shakespeare.lit' type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
]]></example>
<p>However, if the bare JID &LOCALBARE; of the present occupant matches the bare JID of the user seeking to change his or her nickname, then the service MAY allow the nickname change. See the <link url='#enter-conflict'>Nickname Conflict</link> section of this document for details.</p>
<p>If the user attempts to change their room nickname but nicknames are "locked down", the service MUST either deny the nickname change request and return a presence stanza of type "error" with a &notacceptable; error condition:</p>
<example caption='Service Denies Nickname Change Because Roomnicks Are Locked Down'><![CDATA[
<presence
from='coven@chat.shakespeare.lit/thirdwitch'
id='ifd1c35'
to='hag66@shakespeare.lit/pda'
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error by='coven@chat.shakespeare.lit' type='cancel'>
<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
]]></example>
<p>The user SHOULD then discover its reserved nickname as specified in the <link url='#reservednick'>Discovering Reserved Room Nickname</link> section of this document.</p>
</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 &OCCUPANTJID;.</p>
<example caption='Occupant Changes Availability Status'><![CDATA[
<presence
from='wiccarocks@shakespeare.lit/laptop'
id='kr7v143h'
to='coven@chat.shakespeare.lit/oldhag'>
<show>xa</show>
<status>gone where the goblins go</status>
</presence>
]]></example>
<p>If the room is configured to broadcast presence from entities with the occupant's role, the service then sends a presence stanza from the occupant changing his or her presence to the full JID of each occupant, including extended presence information about the occupant's role and full JID to those with privileges to view such information:</p>
<example caption='Service Passes Along Changed Presence to All Occupants'><![CDATA[
<presence
from='coven@chat.shakespeare.lit/secondwitch'
id='86E11ABF-26BC-46F1-AD3B-F5E54F3C1EE5'
to='crone1@shakespeare.lit/desktop'>
<show>xa</show>
<status>gone where the goblins go</status>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='admin'
jid='wiccarocks@shakespeare.lit/laptop'
role='moderator'/>
</x>
</presence>
[ ... ]
]]></example>
</section2>
<section2 topic='Inviting Another User to a Room' anchor='invite'>
<p>There are two ways of inviting another user to a room: direct invitations and mediated invitations.</p>
<p>Direct invitations were the original method used in the early Jabber community's "groupchat 1.0" protocol. Mediated invitations were added in Multi-User Chat as a way to handle invitations in the context of members-only rooms (so that the room could exercise control over the issuance of invitations). The existence of two different invitation methods might cause confusion among client developers. Because the room needs to be involved in the invitation process only for members-only rooms, because members-only rooms are relatively rare, and because mediated invitations do not work when &xep0016; or similar technologies are used to block communication from entities not in a user's roster, client developers are encouraged to use direct invitations for all other room types.</p>
<section3 topic='Direct Invitation' anchor='invite-direct'>
<p>A method for sending a direct invitation (not mediated by the room itself) is defined in &xep0249;. Sending the invitation directly can help to work around communications blocking on the part of the invitee (which might reject or discard messages from entities not in its roster).</p>
</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 &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'
id='nzd143v8'
to='coven@chat.shakespeare.lit'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<invite to='hecate@shakespeare.lit'>
<reason>
Hey Hecate, this is the place for all good witches!
</reason>
</invite>
</x>
</message>
]]></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 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'
id='nzd143v8'
to='hecate@shakespeare.lit'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<invite from='crone1@shakespeare.lit/desktop'>
<reason>
Hey Hecate, this is the place for all good witches!
</reason>
</invite>
<password>cauldronburn</password>
</x>
</message>
]]></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><strong>Implementation Note:</strong> <link url='https://xmpp.org/extensions/attic/jep-0045-1.19.html#invite'>In the past</link>, it was specified that a &lt;x xmlns='jabber:x:conference'&gt; element with the reason as text payload was to be included in the mediated invitation as sent by the room. While this has since been removed from this specification, implementations should be aware that there still exist server implementations which emit that payload for compatibility reasons.</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 &ROOMJID; itself:</p>
<example caption='Invitee Declines Invitation'><![CDATA[
<message
from='hecate@shakespeare.lit/broom'
id='jk2vs61v'
to='coven@chat.shakespeare.lit'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<decline to='crone1@shakespeare.lit'>
<reason>
Sorry, I'm too busy right now.
</reason>
</decline>
</x>
</message>
]]></example>
<example caption='Room Informs Invitor that Invitation Was Declined'><![CDATA[
<message
from='coven@chat.shakespeare.lit'
id='jk2vs61v'
to='crone1@shakespeare.lit/desktop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<decline from='hecate@shakespeare.lit'>
<reason>
Sorry, I'm too busy right now.
</reason>
</decline>
</x>
</message>
]]></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 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>
<section2 topic='Converting a One-to-One Chat Into a Multi-User Conference' anchor='continue'>
<p>Sometimes it is desirable to convert a one-to-one chat into a multi-user conference. The process is as follows.</p>
<p>First, two users begin a one-to-one chat.</p>
<example caption='A One-to-One Chat'><![CDATA[
<message
from='crone1@shakespeare.lit/desktop'
id='mjs51f36'
to='wiccarocks@shakespeare.lit/laptop'
type='chat'>
<thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread>
<body>Thrice the brinded cat hath mew'd.</body>
</message>
<message
from='wiccarocks@shakespeare.lit/laptop'
id='l9ij1f3h'
to='crone1@shakespeare.lit/desktop'
type='chat'>
<thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread>
<body>Thrice and once the hedge-pig whined.</body>
</message>
]]></example>
<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 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>
<p>Note: If the one-to-one chat messages included a &THREAD; element, the person who creates the room SHOULD include the ThreadID with the history messages, specify the ThreadID in the invitations as the value of the &lt;continue/&gt; element's 'thread' attribute, and include the ThreadID in any new messages sent to the room. Use of ThreadIDs is RECOMMENDED because it helps to provide continuity between the one-to-one chat and the multi-user chat.</p>
<example caption='Continuing the Discussion I: User Creates Room'><![CDATA[
<presence
from='crone1@shakespeare.lit/desktop'
to='coven@chat.shakespeare.lit/firstwitch'>
<x xmlns='http://jabber.org/protocol/muc'/>
</presence>
<presence
from='coven@chat.shakespeare.lit/firstwitch'
to='crone1@shakespeare.lit/desktop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='owner' role='moderator'/>
<status code='110'/>
</x>
</presence>
]]></example>
<example caption='Continuing the Discussion II: Owner Sends History to Room'><![CDATA[
<message
from='crone1@shakespeare.lit/desktop'
id='b4va73n0'
to='coven@chat.shakespeare.lit'
type='groupchat'>
<thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread>
<body>Thrice the brinded cat hath mew'd.</body>
<delay xmlns='urn:xmpp:delay'
from='crone1@shakespeare.lit/desktop'
stamp='2004-09-29T01:54:37Z'/>
</message>
<message
from='crone1@shakespeare.lit/desktop'
id='i4hs759k'
to='coven@chat.shakespeare.lit'
type='groupchat'>
<thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread>
<body>Thrice and once the hedge-pig whined.</body>
<delay xmlns='urn:xmpp:delay'
from='crone1@shakespeare.lit/desktop'
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 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'
id='gl3s85n7'
to='coven@chat.shakespeare.lit'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<invite to='wiccarocks@shakespeare.lit/laptop'>
<reason>This coven needs both wiccarocks and hag66.</reason>
<continue thread='e0ffe42b28561960c6b12b944a092794b9683a38'/>
</invite>
<invite to='hag66@shakespeare.lit'>
<reason>This coven needs both wiccarocks and hag66.</reason>
<continue thread='e0ffe42b28561960c6b12b944a092794b9683a38'/>
</invite>
</x>
</message>
]]></example>
<p>Note: Since the inviter's client knows the full JID of the person with whom the inviter was having a one-to-one chat, it SHOULD include the full JID (rather than the bare JID) in its invitation to that user.</p>
<p>The invitations are delivered to the invitees:</p>
<example caption='Invitations Delivered'><![CDATA[
<message
from='coven@chat.shakespeare.lit/firstwitch'
id='DB0414CB-AFBA-407E-9DE3-0E014E84860F'
to='wiccarocks@shakespeare.lit/laptop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<invite from='crone1@shakespeare.lit'>
<reason>This coven needs both wiccarocks and hag66.</reason>
<continue thread='e0ffe42b28561960c6b12b944a092794b9683a38'/>
</invite>
</x>
</message>
<message
from='coven@chat.shakespeare.lit/firstwitch'
id='89028D79-AB4C-44C0-BE81-B07607C2F4C2'
to='hag66@shakespeare.lit'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<invite from='crone1@shakespeare.lit'>
<reason>This coven needs both wiccarocks and hag66.</reason>
<continue thread='e0ffe42b28561960c6b12b944a092794b9683a38'/>
</invite>
</x>
</message>
]]></example>
<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'
to='coven@chat.shakespeare.lit/secondwitch'>
<x xmlns='http://jabber.org/protocol/muc'/>
</presence>
<presence
from='coven@chat.shakespeare.lit/firstwitch'
to='wiccarocks@shakespeare.lit/laptop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='owner' role='moderator'/>
</x>
</presence>
<presence
from='coven@chat.shakespeare.lit/secondwitch'
to='wiccarocks@shakespeare.lit/laptop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='participant'/>
</x>
</presence>
<message
from='coven@chat.shakespeare.lit'
id='67268D36-100C-457D-A769-8A3663BD1949'
to='wiccarocks@shakespeare.lit/laptop'
type='groupchat'>
<thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread>
<body>Thrice the brinded cat hath mew'd.</body>
<delay xmlns='urn:xmpp:delay'
from='coven@chat.shakespeare.lit'
stamp='2004-09-29T01:54:37Z'/>
</message>
<message
from='coven@chat.shakespeare.lit'
id='367DCF6B-0CB4-482D-A142-C0B9E08016B5'
to='wiccarocks@shakespeare.lit/laptop'
type='groupchat'>
<thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread>
<body>Thrice and once the hedge-pig whined.</body>
<delay xmlns='urn:xmpp:delay'
from='coven@chat.shakespeare.lit'
stamp='2004-09-29T01:55:21Z'/>
</message>
]]></example>
</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; 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'
id='jw81b36f'
to='coven@chat.shakespeare.lit'
type='get'>
<query xmlns='jabber:iq:register'/>
</iq>
]]></example>
<p>If the room does not exist, the service MUST return an &notfound; error.</p>
<example caption='Room Does Not Exist'><![CDATA[
<iq from='coven@chat.shakespeare.lit'
id='jw81b36f'
to='hag66@shakespeare.lit/pda'
type='error'>
<error type='cancel'>
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the user requesting registration requirements is not allowed to register with the room (e.g., because that privilege has been restricted), the room MUST return a &notallowed; error to the user.</p>
<example caption='User Is Not Allowed to Register'><![CDATA[
<iq from='coven@chat.shakespeare.lit'
id='jw81b36f'
to='hag66@shakespeare.lit/pda'
type='error'>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the user is already registered, as described in <cite>XEP-0077</cite> the room MUST reply with an IQ stanza of type "result", which MUST contain an empty &lt;registered/&gt; element and SHOULD contain at least a &lt;username/&gt; element that specifies the user's registered nickname in the room.</p>
<example caption='User Is Already Registered'><![CDATA[
<iq from='coven@chat.shakespeare.lit'
id='jw81b36f'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='jabber:iq:register'>
<registered/>
<username>thirdwitch</username>
</query>
</iq>
]]></example>
<p>Otherwise, the room MUST then return a Data Form to the user (as described in &xep0004;). The information required to register might vary by implementation or deployment and is not fully specified in this document (e.g., the fields registered by this document for the 'http://jabber.org/protocol/muc#register' FORM_TYPE might be supplemented in the future via the mechanisms described in the <link url="#registrar-formtype">Field Standardization</link> section of this document). The following can be taken as a fairly typical example:</p>
<example caption='Service Returns Registration Form'><![CDATA[
<iq from='coven@chat.shakespeare.lit'
id='jw81b36f'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='jabber:iq:register'>
<instructions>
To register on the web, visit http://shakespeare.lit/
</instructions>
<x xmlns='jabber:x:data' type='form'>
<title>Dark Cave Registration</title>
<instructions>
Please provide the following information
to register with this room.
</instructions>
<field
type='hidden'
var='FORM_TYPE'>
<value>http://jabber.org/protocol/muc#register</value>
</field>
<field
label='Given Name'
type='text-single'
var='muc#register_first'>
<required/>
</field>
<field
label='Family Name'
type='text-single'
var='muc#register_last'>
<required/>
</field>
<field
label='Desired Nickname'
type='text-single'
var='muc#register_roomnick'>
<required/>
</field>
<field
label='Your URL'
type='text-single'
var='muc#register_url'/>
<field
label='Email Address'
type='text-single'
var='muc#register_email'/>
<field
label='FAQ Entry'
type='text-multi'
var='muc#register_faqentry'/>
</x>
</query>
</iq>
]]></example>
<p>The user SHOULD then submit the form:</p>
<example caption='User Submits Registration Form'><![CDATA[
<iq from='hag66@shakespeare.lit/pda'
id='nv71va54'
to='coven@chat.shakespeare.lit'
type='set'>
<query xmlns='jabber:iq:register'>
<x xmlns='jabber:x:data' type='submit'>
<field var='FORM_TYPE'>
<value>http://jabber.org/protocol/muc#register</value>
</field>
<field var='muc#register_first'>
<value>Brunhilde</value>
</field>
<field var='muc#register_last'>
<value>Entwhistle-Throckmorton</value>
</field>
<field var='muc#register_roomnick'>
<value>thirdwitch</value>
</field>
<field var='muc#register_url'>
<value>http://witchesonline/~hag66/</value>
</field>
<field var='muc#register_email'>
<value>hag66@witchesonline</value>
</field>
<field var='muc#register_faqentry'>
<value>Just another witch.</value>
</field>
</x>
</query>
</iq>
]]></example>
<p>If the desired room nickname is already reserved for that room, the room MUST return a &conflict; error to the user:</p>
<example caption='Room Returns Conflict Error to User'><![CDATA[
<iq from='coven@chat.shakespeare.lit'
id='nv71va54'
to='hag66@shakespeare.lit/pda'
type='error'>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the room or service does not support registration, it MUST return a &unavailable; error to the user:</p>
<example caption='Room Returns Service Unavailable Error to User'><![CDATA[
<iq from='coven@chat.shakespeare.lit'
id='nv71va54'
to='hag66@shakespeare.lit/pda'