7. Occupant Use Cases
The main actor in a multi-user chat environment is the occupant, who can be said to be located "in" a multi-user chat room and to participate in the discussions held in that room (for the purposes of this specification, participants and visitors are considered to be "mere" occupants, since they possess no administrative privileges). As will become clear, the protocol elements proposed in this document to fulfill the occupant use cases fall into three categories:
在群聊的環境里,每個人都稱得上是一個occupant,所以occupant很重要,我們可以說他是“在”一個聊天室的,可以參與這個房間的討論。
-
existing "groupchat 1.0" protocol for minimal functionality
-
straightforward applications of the "groupchat 1.0" protocol, for example to handle some of the errors related to new room types
-
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
Note: All client-generated examples herein are presented from the perspective of the service, with the result that all stanzas received by a service contain a 'from' attribute corresponding to the sender's full JID as added by a normal Jabber router or session manager. In addition, normal IQ result stanzas sent upon successful completion of a request (as required by RFC 3920 [10]) are not shown.
7.1 Entering a Room 進入一個房間
7.1.1 Groupchat 1.0 Protocol
In order to participate in the discussions held in a multi-user chat room, a Jabber user MUST first become an occupant by entering the room. In the old "groupchat 1.0" protocol, this was done by sending presence to <room@service/nick>, where "room" is the room ID, "service" is the hostname of the chat service, and "nick" is the user's desired nickname within the room:
為了參與一個房間的聊天,一個用戶必須首先進入這個房間,成為一個occupant,我們用向roomjid : room@service/nikd 發送presence協議這種方式實現,這里的room是一個roomid,service是服務器的host,nick是用戶希望在這個房間里顯示的昵稱。
一個用戶請求進入一個房間
<presence
from='hag66@shakespeare.lit/pda' jid
to='darkcave@chat.shakespeare.lit/thirdwitch'/> roomjid
In this example, a user with a full JID of "hag66@shakespeare.lit/pda" has requested to enter the room "darkcave" on the "chat.shakespeare.lit" chat service with a room nickname of "thirdwitch".
在這個例子中,一個帶有full jid 的用戶 xx 已經請求進入 在服務chat.shakespeare.lit 上的 darkcave這個房間,並希望有一個thirdwith這個昵稱
If the user does not specify a room nickname, the service MUST return a <jid-malformed/> error:
如果這個用戶沒有指定昵稱, 服務器必須要返回error
Example 17. No Nickname Specified
<presence
from='darkcave@chat.shakespeare.lit'
to='hag66@shakespeare.lit/pda'
type='error'>
<error type='modify'>
<jid-malformed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
7.1.2 Basic MUC Protocol
Compliant multi-user chat services MUST accept the foregoing as a request to enter a room from any Jabber client that knows either the "groupchat 1.0" (GC) protocol or the multi-user chat (MUC) protocol; however, MUC clients SHOULD signal their ability to speak the MUC protocol by including in the initial presence stanza an empty <x/> element qualified by the 'http://jabber.org/protocol/muc' namespace (note the absence of the '#user' fragment):
客戶端要讓服務器知道他們能夠接受群聊服務,方法是加入一個x節,xmlns ='http://jabber.org/protocol/muc'/
Example 18. Jabber User Seeks to Enter a Room (Multi-User Chat)
<presence
from='hag66@shakespeare.lit/pda' jid
to='darkcave@chat.shakespeare.lit/thirdwitch'> roomjid
<x xmlns='http://jabber.org/protocol/muc'/>
</presence>
Note: If an error occurs in relation to joining a room, the service SHOULD include the MUC child element (i.e., <x xmlns='http://jabber.org/protocol/muc'/>) in the <presence/> stanza of type "error".
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 Discovering Reserved Room Nickname section of this document.
要對昵稱進行檢查
7.1.3 Presence Broadcast
presence 廣播
If the service is able to add the user to the room, it MUST send presence from all the existing occupants' room JIDs to the new occupant's full JID, including extended presence information about roles in an <x/> element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an <item/> child with the 'role' attribute set to a value of "moderator", "participant", or "visitor", and with the 'affiliation' attribute set to a value of "owner", "admin", "member", or "none" as appropriate:
如果服務器允許這個用戶進入房間的話,服務器必須發送 from=roomjids to=加入用戶的jid 的presence協議,包含擴展的用來包含role的信息的presence協議的x節,在muc#user這個namespace里面,包含在item這個節內的role屬性還有affiliation屬性。
Example 19. Service Sends Presence from Existing Occupants to New Occupant
服務器
<presence
from='darkcave@chat.shakespeare.lit/firstwitch' existing roomjid
to='hag66@shakespeare.lit/pda'> new jid
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='owner' role='moderator'/>
</x>
</presence>
<presence
from='darkcave@chat.shakespeare.lit/secondwitch'
to='hag66@shakespeare.lit/pda'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='admin' role='moderator'/>
</x>
</presence>
In this example, the user from the previous example has entered the room, by which time two other people had already entered the room: a user with a room nickname of "firstwitch" (who is a room owner) and a user with a room nickname of "secondwitch" (who is a room admin).
在這個例子里面,用戶從前一個例子已經進入了這個房間,這個房間里面已經有了兩個人了,一個的昵稱是firstwitch,是一個owner,另外一個的昵稱是secondwitch,是一個房間管理員。
The service MUST also send presence from the new occupant's room JID to the full JIDs of all the occupants (including the new occupant):
服務端也必須發送一個presence協議,from=new roomjid to=existing full jid
Example 20. Service Sends New Occupant's Presence to All Occupants
服務器向所有在房間內部的人發送消息,通知新用戶進來了。
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch' new roomjid
to='crone1@shakespeare.lit/desktop'> existing jid
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='participant'/>
</x>
</presence>
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='wiccarocks@shakespeare.lit/laptop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='participant'/>
</x>
</presence>
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='hag66@shakespeare.lit/pda'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='participant'/>
<status code='110'/>
</x>
</presence>
In this example, initial room presence is being sent from the new occupant (thirdwitch) to all occupants, including the new occupant. As shown in the last stanza, the presence sent by the room to a user from itself as an occupant SHOULD include a status code of 110 so that the user knows this presence refers to itself as an occupant.
在這個例子里面,開始,presence 已經發送給了所有的occupants,包括這個新用戶自己,而且是在最后一個presence 節,一個presence從一個roomjid 發送給一個jid,這兩個是相同的用戶,應該包含110這個狀態碼,讓客戶端知道,這個presence讓他自己知道,這個presence是來自作為occupant的他自己的。
The service MAY rewrite the new occupant's roomnick (e.g., if roomnicks are locked down). If the service does not accept the new occupant's requested roomnick but instead assigns a new roomnick, it MUST include a status code of "210" in the presence broadcast that it sends to the new occupant.
服務端或許要記錄下這個occupant的昵稱,如果服務器不接受這個occupant的昵稱,要自己重新給一個昵稱的話,一定要包含一個210的狀態碼。(這個也是發給自己的)
Example 21. Service Sends New Occupant's Presence to New Occupant
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
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>
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".
注意 : 這個presence協議的發送順序是需要注意的,很重要,首先服務器必須完成existing 到 new 的通知,然后發送new到new的通知,這樣可以幫助客戶端知道什么時候他收完了房間列表。
After sending the presence broadcast (and only after doing so), the service may then send discussion history, live messages, presence updates, and other in-room traffic.
在發完presence廣播以后,服務端或許會發送聊天記錄,
7.1.4 Default Roles
默認的role
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).
下面的表格說明了,根據用戶的affiliation來set用戶的role的默認的規則
Table 7: Initial Role Based on Affiliation
Room Type | None | Member | Admin | Owner |
---|---|---|---|---|
Moderated | Visitor | Participant | Moderator | Moderator |
Unmoderated | Participant | Participant | Moderator | Moderator |
Members-Only | N/A * | Participant | Moderator | Moderator |
Open | Participant | Participant | Moderator | Moderator |
* Entry is not permitted.
7.1.5 Non-Anonymous Rooms
If the room is non-anonymous, the service MUST send the new occupant's full JID to all occupants using extended presence information in an <x/> element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an <item/> child with a 'jid' attribute specifying the occupant's full JID:
如果一個房間是一個不匿名的房間,服務器必須發送新進來的用戶的fulljid 給所有的existing occupant。在item里面加入一個jid的屬性
Example 22. Service Sends Full JID to All Occupants
服務器發送全jid給所有的occupant
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch' new roomjid
to='crone1@shakespeare.lit/desktop'> existing jid
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='none'
jid='hag66@shakespeare.lit/pda'
role='participant'/>
</x>
</presence>
[ ... ]
If the user is entering a room that is non-anonymous (i.e., which informs all occupants of each occupant's full JID as shown above), the service SHOULD allow the user to enter the room but MUST also warn the user that the room is not anonymous. This SHOULD be done by including a status code of "100" in the initial presence that the room sends to the new occupant:
如果這個用戶進入的是一個非匿名的房間,服務器必須要告訴他,他進入的是一個非匿名的房間。可以包含一個100的status code,可以在自己通知自己的時候包含進去
Example 23. Service Sends New Occupant's Presence to New Occupant
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='hag66@shakespeare.lit/pda'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='participant'/>
<status code='100'/> 非匿名的
<status code='110'/> 作為結束收roster的標志
<status code='210'/> 服務器可以改變他的昵稱,改變了這個用戶的昵稱
</x>
</presence>
However, it MAY be done by sending a message of type "groupchat" to the new occupant containing an <x/> child with a <status/> element that has the 'code' attribute set to a value of "100":
也可以發送一個message消息,在x節里面包含status節,並設置code屬性,表明100碼
Example 24. Service Warns New Occupant About Lack of Anonymity
<message
from='darkcave@chat.shakespeare.lit' roomid
to='hag66@shakespeare.lit/pda' new jid
type='groupchat'>
<body>This room is not anonymous.</body>
<x xmlns='http://jabber.org/protocol/muc#user'>
<status code='100'/>
</x>
</message>
The inclusion of the status code assists clients in presenting their own notification messages (e.g., information appropriate to the user's locality).
7.1.6 Semi-Anonymous Rooms
If the room is semi-anonymous, the service MUST send presence from the new occupant to all occupants as specified above, 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.
如果是半匿名的房間,新進來的用戶只發送給moderator,不發送給非moderator的用戶
(Note: All subsequent examples include the 'jid' attribute for each <item/> element, even though this information is not sent to non-moderators in semi-anonymous rooms.)
7.1.7 Password-Protected Rooms
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 <not-authorized/> error:
如果這個用戶沒有輸入正確的密碼,服務器應該通知他。
Example 25. Service Denies Access Because No Password Provided
<presence
from='darkcave@chat.shakespeare.lit' roomid
to='hag66@shakespeare.lit/pda' new jid
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error type='auth'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
Passwords SHOULD be supplied with the presence stanza sent when entering the room, contained within an <x/> element qualified by the 'http://jabber.org/protocol/muc' namespace and containing a <password/> child. Passwords are to be sent as cleartext; no other authentication methods are supported at this time, and any such authentication or authorization methods shall be defined in a separate specification (see the Security Considerations section of this document).
密碼應該發送在protocol/muc這個xmlns下,並且在password節里面用明碼發送。
Example 26. User Provides Password On Entering a Room
<presence
from='hag66@shakespeare.lit/pda'
to='darkcave@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<password>cauldronburn</password>
</x>
</presence>
7.1.8 Members-Only Rooms
If the room is members-only but the user is not on the member list, the service MUST deny access to the room and inform the user that they are not allowed to enter the room; this is done by returning a presence stanza of type "error" specifying a <registration-required/> error condition:
在member-only房間里,如果這個新進入的用戶,服務器必須駁回,然后通知用戶這個房間不允許其進入。包含一個registration-required的error節
Example 27. Service Denies Access Because User Is Not on Member List
<presence
from='darkcave@chat.shakespeare.lit'
to='hag66@shakespeare.lit/pda'
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error type='auth'>
<registration-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
7.1.9 Banned Users
If the user has been banned from the room (i.e., has an affiliation of "outcast"), the service MUST deny access to the room and inform the user of the fact that he or she is banned; this is done by returning a presence stanza of type "error" specifying a <forbidden/> error condition:
如果一個用戶已經被驅逐了,被放入了黑名單,那么,服務不應該讓他進入這個房間,返回一個
Example 28. Service Denies Access Because User is Banned
<presence
from='darkcave@chat.shakespeare.lit' roomid
to='hag66@shakespeare.lit/pda' newjid
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error type='auth'>
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
7.1.10 Nickname Conflict
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:
如果這個房間已經存在一個其他的用戶,和這個用戶的昵稱相同的話,或者已經和其他用戶的保留的昵稱相同,服務器不應該允許他進入房間,應該返回conflict
Example 29. Service Denies Access Because of Nick Conflict
<presence
from='darkcave@chat.shakespeare.lit'
to='hag66@shakespeare.lit/pda'
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
However, if the bare JID <localpart@domain.tld> 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 SHOULD 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 to determine how to appropriately handle presence from the user's resources and how to route private messages to all or only one resource (based on presence priority or some other algorithm).
但是,如果這個userid和自己沖突了,如果服務器允許多副本,應該允許其進入,並處理相應的信息。
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.).
7.1.11 Max Users
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 <service-unavailable/> error condition:
如果這個房間已經進入了上線用戶。服務器應該不允許其進入,返回一個error,包含一個service-unavailable節
Example 30. Service Informs User that Room Occupant Limit Has Been Reached
<presence
from='darkcave@chat.shakespeare.lit'
to='hag66@shakespeare.lit/pda'
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error type='wait'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
Alternatively, the room could kick an "idle user" in order to free up space.
If the room has reached its maximum number of occupants and a room admin or owner attempts to join, the room SHOULD allow the admin or owner to join, up to some reasonable number of additional occupants, which number MAY be configurable.
7.1.12 Locked Room
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 <item-not-found/> error to the user:
在一個房間沒有被完全創建之前,也就是一個被鎖住的房間,這個房間的主人沒有設置完這個房間的配置,服務器不應該讓其進入,返回一個item-not-found錯誤節
Example 31. Service Denies Access Because Room Does Not Exist
<presence
from='darkcave@chat.shakespeare.lit'
to='hag66@shakespeare.lit/pda'
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error type='cancel'>
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
7.1.13 Nonexistent Room
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 Creating a Room section of this document.
7.1.14 Room Logging
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 SHOULD be done by including a status code of "170" in the initial presence that the room sends to the new occupant:
如果這個房間的聊天記錄是被記錄的, 應該發170提醒用戶
Example 32. Service Sends New Occupant's Presence to New Occupant
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
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>
7.1.15 Discussion History
After sending initial presence as shown above, 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 Presence Broadcast 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.
在發送完畢presence后,服務器可以選擇發送聊天記錄給這個新用戶。一定要在發送完了所有的presence之后。但是聊天記錄是否發送,發送多少由服務器決定
Example 33. Delivery of Discussion History
<message
from='darkcave@chat.shakespeare.lit/firstwitch'
to='hecate@shakespeare.lit/broom'
type='groupchat'>
<body>Thrice the brinded cat hath mew'd.</body>
<delay xmlns='urn:xmpp:delay'
from='crone1@shakespeare.lit/desktop'
stamp='2002-10-13T23:58:37Z'/>
</message>
<message
from='darkcave@chat.shakespeare.lit/secondwitch'
to='hecate@shakespeare.lit/broom'
type='groupchat'>
<body>Thrice and once the hedge-pig whined.</body>
<delay xmlns='urn:xmpp:delay'
from='wiccarocks@shakespeare.lit/laptop'
stamp='2002-10-13T23:58:43Z'/>
</message>
<message
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='hecate@shakespeare.lit/broom'
type='groupchat'>
<body>Harpier cries 'Tis time, 'tis time.</body>
<delay xmlns='urn:xmpp:delay'
from='hag66@shakespeare.lit/pda'
stamp='2002-10-13T23:58:49Z'/>
</message>
Discussion history messages MUST be stamped with Delayed Delivery [11] 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. (Note: The 'urn:xmpp:delay' namespace defined in XEP-0203 supersedes the older 'jabber:x:delay' namespace defined in Legacy Delayed Delivery [12]; until the status of XEP-0091 is changed to Obsolete, implementations SHOULD include both datetime formats.) The 'from' attribute SHOULD be the full JID of the original sender in non-anonymous rooms, but MUST NOT be in semi-anonymous rooms (where the 'from' attribute SHOULD be set to the JID of the room itself). The service SHOULD send all discussion history messages before delivering any "live" messages sent after the user enters the room.
7.1.16 Managing Discussion History
A user MAY want to manage the amount of discussion history provided on entering a room (perhaps because the user is on a low-bandwidth connection or is using a small-footprint client). This MUST be accomplished by including a <history/> child in the initial presence stanza sent when joining the room. There are four allowable attributes for this element:
Table 8: History Management Attributes
Attribute | Datatype | Meaning |
---|---|---|
maxchars | int | 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). |
maxstanzas | int | Limit the total number of messages in the history to "X". |
seconds | int | Send only the messages received in the last "X" seconds. |
since | dateTime | Send only the messages received since the datetime specified (which MUST conform to the DateTime profile specified in XMPP Date and Time Profiles [13]). |
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).
The following examples illustrate the use of this protocol.
Example 34. User Requests Limit on Number of Messages in History
<presence
from='hag66@shakespeare.lit/pda'
to='darkcave@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history maxstanzas='20'/>
</x>
</presence>
Example 35. User Requests History in Last 3 Minutes
<presence
from='hag66@shakespeare.lit/pda'
to='darkcave@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history seconds='180'/>
</x>
</presence>
Example 36. User Requests All History Since the Beginning of the Unix Era
<presence
from='hag66@shakespeare.lit/pda'
to='darkcave@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history since='1970-01-01T00:00:00Z'/>
</x>
</presence>
Obviously the service SHOULD NOT return all messages sent in the room since the beginning of the Unix era, and SHOULD appropriately limit the amount of history sent to the user based on service or room defaults.
Example 37. User Requests No History
<presence
from='hag66@shakespeare.lit/pda'
to='darkcave@chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history maxchars='0'/>
</x>
</presence>
7.2 Exiting a Room
In order to exit a multi-user chat room, an occupant sends a presence stanza of type "unavailable" to the <room@service/nick> it is currently using in the room.
Example 38. Occupant Exits a Room
<presence
from='hag66@shakespeare.lit/pda'
to='darkcave@chat.shakespeare.lit/thirdwitch'
type='unavailable'/>
The service MUST then send presence stanzas of type "unavailable" from the departing occupant's room JID to the full JIDs of the departing occupant and of the remaining occupants:
Example 39. Service Sends Presence Related to Departure of Occupant
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='hag66@shakespeare.lit/pda'
type='unavailable'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='none'/>
<status code='110'/>
</x>
</presence>
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='crone1@shakespeare.lit/desktop'
type='unavailable'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='none'/>
</x>
</presence>
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='wiccarocks@shakespeare.lit/laptop'
type='unavailable'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member' role='none'/>
</x>
</presence>
Presence stanzas of type "unavailable" reflected by the room MUST contain extended presence information about roles and affiliations; the 'role' attribute SHOULD be set to a value of "none" to denote that the individual is no longer an occupant.
The occupant MAY include normal <status/> information in the unavailable presence stanzas; this enables the occupant to provide a custom exit message if desired:
Example 40. Custom Exit Message
<presence
from='wiccarocks@shakespeare.lit/laptop'
to='darkcave@chat.shakespeare.lit/oldhag'
type='unavailable'>
<status>gone where the goblins go</status>
</presence>
Normal presence stanza generation rules apply as defined in XMPP IM [14], so that if the user sends a general unavailable presence stanza, the user's server will broadcast that stanza to the <room@service/nick> to which the user's client has sent directed presence.
It is possible that a user may not be able to gracefully exit the room by sending unavailable presence directly to the room. If the user goes offline without sending unavailable presence, the user's server is responsible for sending unavailable presence on behalf of the user (in accordance with RFC 3921). If the user's server goes offline or connectivity is lost between the user's server and the MUC service to which the user is connected (e.g., in federated communications), the MUC service is responsible for monitoring error stanzas it receives in order to determine if the user has gone offline. If the MUC service determines that the user has gone offline, it must treat the user as if the user had itself sent unavailable presence.
Note: If the room is not persistent and this occupant is the last to exit, the service is responsible for destroying the room.
7.3 Changing Nickname
A common feature of multi-user chat rooms is the ability for an occupant to change his or her nickname within the room. In MUC this is done by sending updated presence information to the room, specifically by sending presence to a new room JID in the same room (changing only the resource identifier in the room JID).
Example 41. Occupant Changes Nickname
<presence
from='hag66@shakespeare.lit/pda'
to='darkcave@chat.shakespeare.lit/oldhag'/>
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.
The unavailable presence MUST contain the following as extended presence information in an <x/> element qualified by the 'http://jabber.org/protocol/muc#user' namespace:
- The new nickname (in this case, nick='oldhag')
- A status code of 303
This enables the recipients to correlate the old roomnick with the new roomnick.
Example 42. Service Updates Nick
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='crone1@shakespeare.lit/desktop'
type='unavailable'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
nick='oldhag'
role='participant'/>
<status code='303'/>
</x>
</presence>
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='wiccarocks@shakespeare.lit/laptop'
type='unavailable'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
nick='oldhag'
role='participant'/>
<status code='303'/>
</x>
</presence>
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='hag66@shakespeare.lit/pda'
type='unavailable'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
nick='oldhag'
role='participant'/>
<status code='303'/>
<status code='110'/>
</x>
</presence>
<presence
from='darkcave@chat.shakespeare.lit/oldhag'
to='crone1@shakespeare.lit/desktop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
role='participant'/>
</x>
</presence>
<presence
from='darkcave@chat.shakespeare.lit/oldhag'
to='wiccarocks@shakespeare.lit/laptop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
role='participant'/>
</x>
</presence>
<presence
from='darkcave@chat.shakespeare.lit/oldhag'
to='hag66@shakespeare.lit/pda'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
role='participant'/>
<status code='110'/>
</x>
</presence>
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:
Example 43. Service Denies Nickname Change Because of Nick Conflict
<presence
from='darkcave@chat.shakespeare.lit'
to='hag66@shakespeare.lit/pda'
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
However, if the bare JID <localpart@domain.tld> 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 Nickname Conflict section of this document for details.
If the user attempts to change his or her room nickname but room nicknames are "locked down", the service MUST deny the nickname change request and return a presence stanza of type "error" specifying a <not-acceptable/> error condition:
Example 44. Service Denies Nickname Change Because Roomnicks Are Locked Down
<presence
from='darkcave@chat.shakespeare.lit'
to='hag66@shakespeare.lit/pda'
type='error'>
<x xmlns='http://jabber.org/protocol/muc'/>
<error type='cancel'>
<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</presence>
The user SHOULD then discover its reserved nickname as specified in the Discovering Reserved Room Nickname section of this document.
7.4 Changing Availability Status
In multi-user chat systems such as IRC, one common use for changing one's room nickname is to indicate a change in one's availability (e.g., changing one's room nickname to "thirdwitch|away"). In Jabber, availability is of course noted by a change in presence (specifically the <show/> and <status/> elements), which can provide important context within a chatroom. An occupant changes availability status within the room by sending the updated presence to its <room@service/nick>.
Example 45. Occupant Changes Availability Status
<presence
from='wiccarocks@shakespeare.lit/laptop'
to='darkcave@chat.shakespeare.lit/oldhag'>
<show>xa</show>
<status>gone where the goblins go</status>
</presence>
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:
Example 46. Service Passes Along Changed Presence to All Occupants
<presence
from='darkcave@chat.shakespeare.lit/secondwitch'
to='crone1@shakespeare.lit/desktop'>
<show>xa</show>
<status>gone where the goblins go</status>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='admin'
jid='wiccarocks@shakespeare.lit/laptop'
role='moderator'/>
</x>
</presence>
[ ... ]
7.5 Inviting Another User to a Room
7.5.1 Direct Invitation
A method for sending a direct invitation (not mediated by the room itself) is defined in Direct MUC Invitations [15]. Sending the invitation directly can help to work around communications blocking on the part of the invitee (which might refuse communication with entities not in its roster).
7.5.2 Mediated Invitation
It can be useful to invite another user to a room in which one is an occupant. To do this, a MUC client MUST send XML of the following form to the <room@service> itself (the reason is OPTIONAL and the message MUST be explicitly or implicitly of type "normal"):
Example 47. Occupant Sends an Invitation by Way of Room
<message
from='crone1@shakespeare.lit/desktop'
to='darkcave@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>
The <room@service> itself MUST then add a 'from' address to the <invite/> element whose value is the bare JID, full JID, or room JID of the invitor and send the invitation to the invitee specified in the 'to' address (the service MAY include a message body explaining the invitation or containing the reason, for the sake of older clients; in addition, the room SHOULD add the password if the room is password-protected):
Example 48. Room Sends Invitation to Invitee on Behalf of Invitor
<message
from='darkcave@chat.shakespeare.lit'
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>
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 theModifying the Member List section of this document.)
If the invitor supplies a non-existent JID, the room SHOULD return an <item-not-found/> error to the invitor.
The invitee MAY choose to formally decline (as opposed to ignore) the invitation; and this is something that the sender may want to be informed about. In order to decline the invitation, the invitee MUST send a message of the following form to the <room@service> itself:
Example 49. Invitee Declines Invitation
<message
from='hecate@shakespeare.lit/broom'
to='darkcave@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 50. Room Informs Invitor that Invitation Was Declined
<message
from='darkcave@chat.shakespeare.lit'
to='crone1@shakespeare.lit/desktop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<decline from='hecate@shakespeare.lit'>
<reason>
Sorry, I'm too busy right now.
</reason>
</decline>
</x>
</message>
It may be wondered why the invitee does not send the decline message directly to the invitor. The main reason is that certain implementations MAY choose to base invitations on room JIDs rather than bare JIDs (so that, for example, an occupant could invite someone from one room to another without knowing that person's bare JID). Thus the service MUST handle both the invites and declines.
7.6 Converting a One-to-One Chat Into a Multi-User Conference
Sometimes it is desirable to convert a one-to-one chat into a multi-user conference. The process flow is shown in the following examples.
First, two users begin a one-to-one chat.
<message
from='crone1@shakespeare.lit/desktop'
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'
to='crone1@shakespeare.lit/desktop'
type='chat'>
<thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread>
<body>Thrice and once the hedge-pig whined.</body>
</message>
Now the first person decides to include a third person in the discussion, so she (or, more precisely, her client) does the following:
- Creates a new multi-user chatroom
- Optionally sends history of the one-to-one chat to the room
- Sends an invitation to the second person and the third person, including a <continue/> element (optionally including a 'thread' attribute).
Note: The new room SHOULD be non-anonymous, MAY be an instant room as specified in the Creating an Instant Room section of this document, and MAY have a unique room name received from the service as specified in the Requesting a Unique Room Name section of this document.
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 <continue/> 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.
Example 52. Continuing the Discussion I: User Creates Room
<presence
from='crone1@shakespeare.lit/desktop'
to='darkcave@chat.shakespeare.lit/firstwitch'>
<x xmlns='http://jabber.org/protocol/muc'/>
</presence>
<presence
from='darkcave@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 53. Continuing the Discussion II: Owner Sends History to Room
<message
from='crone1@shakespeare.lit/desktop'
to='darkcave@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'
to='darkcave@chat.shakespeare.lit'
type='groupchat'>
<thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread>
<body>Thrice and once the hedge-pig whined.</body>
<delay xmlns='urn:xmpp:delay'
from='wiccarocks@shakespeare.lit/laptop'
stamp='2004-09-29T01:55:21Z'/>
</message>
Note: Use of the Delayed Delivery protocol enables the room creator to specify the datetime of each message from the one-to-one chat history (via the 'stamp' attribute), as well as the JID of the original sender of each message (via the 'from' attribute). The room creator SHOULD send the complete one-to-one chat history before inviting additional users to the room, and SHOULD also send as history any messages appearing in the one-to-one chat interface after joining the room and before the second person joins the room; if the one-to-one history is especially large, the sending client may want to send the history over a few seconds rather than all at once (to avoid triggering rate limits). The service SHOULD NOT add its own delay elements (as described in the Discussion History section of this document) to prior chat history messages received from the room owner.
Example 54. Continuing the Discussion III: Owner Sends Invitations, Including Continue Flag
<message
from='crone1@shakespeare.lit/desktop'
to='darkcave@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>
Note: Since the invitor's client knows the full JID of the person with whom the invitor was having a one-to-one chat, it SHOULD include the full JID (rather than the bare JID) in the invitation.
The invitations are delivered to the invitees:
Example 55. Invitations Delivered
<message
from='darkcave@chat.shakespeare.lit'>
to='wiccarocks@shakespeare.lit/laptop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<invite from='crone1@shakespeare.lit'>
<reason>This coven needs both wiccarocks and hag66.</reason>
<continue thread='e0ffe42b28561960c6b12b944a092794b9683a38'/>
</invite>
</x>
</message>
<message
from='darkcave@chat.shakespeare.lit'>
to='hag66@shakespeare.lit'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<invite from='crone1@shakespeare.lit'>
<reason>This coven needs both wiccarocks and hag66.</reason>
<continue thread='e0ffe42b28561960c6b12b944a092794b9683a38'/>
</invite>
</x>
</message>
When the client being used by <wiccarocks@shakespeare.lit/laptop> receives the invitation, it SHOULD auto-join the room or prompt the user whether to join (subject to user preferences) and then seamlessly convert the existing one-to-one chat window into a multi-user conferencing window:
Example 56. Invitee Accepts Invitation, Joins Room, and Receives Presence and History
<presence
from='wiccarocks@shakespeare.lit/laptop'
to='darkcave@chat.shakespeare.lit/secondwitch'>
<x xmlns='http://jabber.org/protocol/muc'/>
</presence>
<presence
from='darkcave@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='darkcave@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='darkcave@chat.shakespeare.lit'
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='crone1@shakespeare.lit/desktop'
stamp='2004-09-29T01:54:37Z'/>
</message>
<message
from='darkcave@chat.shakespeare.lit'
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='wiccarocks@shakespeare.lit/laptop'
stamp='2004-09-29T01:55:21Z'/>
</message>
Note: The fact that the messages come from the <room@service> itself rather than <room@service/nick> is a clue to the receiving client that these messages are prior chat history, since any message from a room occupant will have a 'from' address equal to the sender's room JID.
7.7 Occupant Modification of the Room Subject
If allowed in accordance with room configuration, a mere occupant MAY be allowed to change the subject in a room. For details, see the Modifying the Room Subject section of this document.
7.8 Sending a Private Message
Since each occupant has a unique room JID, an occupant MAY send a "private message" to a selected occupant via the service by sending a message to the occupant's room JID. The message type SHOULD be "chat" and MUST NOT be "groupchat", but MAY be left unspecified (i.e., a normal message). This privilege SHOULD be allowed to any occupant (even a visitor in a moderated room).
Example 57. Occupant Sends Private Message
<message
from='wiccarocks@shakespeare.lit/laptop'
to='darkcave@chat.shakespeare.lit/firstwitch'
type='chat'>
<body>I'll give thee a wind.</body>
</message>
The service is responsible for changing the 'from' address to the sender's room JID and delivering the message to the intended recipient's full JID.
Example 58. Recipient Receives the Private Message
<message
from='darkcave@chat.shakespeare.lit/secondwitch'
to='crone1@shakespeare.lit/desktop'
type='chat'>
<body>I'll give thee a wind.</body>
</message>
If the sender attempts to send a private message of type "groupchat" to a particular occupant, the service MUST refuse to deliver the message (since the recipient's client would expect in-room messages to be of type "groupchat") and return a <bad-request/> error to the sender:
Example 59. Occupant Attempts to Send a Message of Type "Groupchat" to a Particular Occupant
<message
from='wiccarocks@shakespeare.lit/laptop'
to='darkcave@chat.shakespeare.lit/firstwitch'
type='groupchat'>
<body>I'll give thee a wind.</body>
</message>
<message
from='darkcave@chat.shakespeare.lit'
to='wiccarocks@shakespeare.lit/laptop'
type='error'>
<body>I'll give thee a wind.</body>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</message>
If the sender attempts to send a private message to a room JID that does not exist, the service MUST return an <item-not-found/> error to the sender.
If the sender is not an occupant of the room in which the intended recipient is visiting, the service MUST return a <not-acceptable/> error to the sender.
7.9 Sending a Message to All Occupants
An occupant sends a message to all other occupants in the room by sending a message of type "groupchat" to the <room@service> 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.
Example 60. Occupant Sends a Message to All Occupants
<message
from='hag66@shakespeare.lit/pda'
to='darkcave@chat.shakespeare.lit'
type='groupchat'>
<body>Harpier cries: 'tis time, 'tis time.</body>
</message>
If the sender has voice in the room (this is the default except in moderated rooms), the service MUST change the 'from' attribute to the sender's room JID and reflect the message out to the full JID of each occupant.
Example 61. Service Reflects Message to All Occupants
<message
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='crone1@shakespeare.lit/desktop'
type='groupchat'>
<body>Harpier cries: 'tis time, 'tis time.</body>
</message>
<message
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='wiccarocks@shakespeare.lit/laptop'
type='groupchat'>
<body>Harpier cries: 'tis time, 'tis time.</body>
</message>
<message
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='hag66@shakespeare.lit/pda'
type='groupchat'>
<body>Harpier cries: 'tis time, 'tis time.</body>
</message>
If the sender is a visitor (i.e., does not have voice in a moderated room), the service MAY return a <forbidden/> error to the sender and MUST NOT reflect the message to all occupants. If the sender is not an occupant of the room, the service SHOULD return a <not-acceptable/> error to the sender and SHOULD NOT reflect the message to all occupants; 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.
7.10 Registering with a Room
An implementation MAY allow an unaffiliated user (in a moderated room, normally a participant) to register with a room and thus become a member of the room (conversely, an implementation MAY restrict this privilege and allow only room admins to add new members). In particular, it is not possible to join a members-only room without being on the member list, so an entity may need to request membership in order to join such a room.
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 In-Band Registration [16]:
Example 62. User Requests Registration Requirements
<iq from='hag66@shakespeare.lit/pda'
id='reg1'
to='darkcave@chat.shakespeare.lit'
type='get'>
<query xmlns='jabber:iq:register'/>
</iq>
If the user requesting registration requirements is not allowed to register with the room (e.g., because that privilege has been restricted), the room MUST return a <not-allowed/> error to the user. If the user is already registered, the room MUST reply with an IQ stanza of type "result" that contains an empty <register/> element as described in XEP-0077. If the room does not exist, the service MUST return an <item-not-found/> error.
Otherwise, the room MUST then return a Data Form to the user (as described in Data Forms [17]). The information required to register MAY 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 may be supplemented in the future via the mechanisms described in the Field Standardization section of this document). The following can be taken as a fairly typical example:
Example 63. Service Returns Registration Form
<iq from='darkcave@chat.shakespeare.lit'
id='reg1'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='jabber:iq:register'>
<instructions>
To register on the web, visit http://shakespeare.lit/
</instructions>
<x xmlns='jabber:x:data' type='form'>
<title>Dark Cave Registration</title>
<instructions>
Please provide the following information
to register with this room.
</instructions>
<field
type='hidden'
var='FORM_TYPE'>
<value>http://jabber.org/protocol/muc#register</value>
</field>
<field
label='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>
The user SHOULD then submit the form:
Example 64. User Submits Registration Form
<iq from='hag66@shakespeare.lit/pda'
id='reg2'
to='darkcave@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>
If the desired room nickname is already reserved for that room, the room MUST return a <conflict/> error to the user:
Example 65. Room Returns Conflict Error to User
<iq from='darkcave@chat.shakespeare.lit'
id='reg2'
to='hag66@shakespeare.lit/pda'
type='error'>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
If the room or service does not support registration, it MUST return a <service-unavailable/> error to the user:
Example 66. Room Returns Service Unavailable Error to User
<iq from='darkcave@chat.shakespeare.lit'
id='reg2'
to='hag66@shakespeare.lit/pda'
type='error'>
<error type='cancel'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
If the user did not include a valid data form, the room MUST return a <bad-request/> error to the user:
Example 67. Room Returns Service Bad Request Error to User
<iq from='darkcave@chat.shakespeare.lit'
id='reg2'
to='hag66@shakespeare.lit/pda'
type='error'>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
Otherwise, the room MUST inform the user that the registration request was successfully received:
Example 68. Room Informs User that Registration Request Has Been Processed
<iq from='darkcave@chat.shakespeare.lit'
id='reg2'
to='hag66@shakespeare.lit/pda'
type='result'/>
After the user submits the form, the service MAY request that the submission be approved by a room admin/owner (see the Approving Registration Requests section of this document) or MAY immediately add the user to the member list by changing the user's affiliation from "none" to "member". If the service changes the user's affiliation and the user is in the room, it MUST send updated presence from this individual to all occupants, indicating the change in affiliation by including an <x/> element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an <item/> child with the 'affiliation' attribute set to a value of "member".
Example 69. Service Sends Notice of Membership to All Occupants
<presence
from='darkcave@chat.shakespeare.lit/thirdwitch'
to='crone1@shakespeare.lit/desktop'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<item affiliation='member'
jid='hag66@shakespeare.lit/pda'
role='participant'/>
</x>
</presence>
[ ... ]
If a user has registered with a room, the room MAY choose to restrict the user to use of the registered nickname only in that room. If it does so, it SHOULD return a <not-acceptable/> error to the user if the user attempts to join the room with a roomnick other than the user's registered roomnick (this enables a room to "lock down" roomnicks for consistent identification of occupants).
7.11 Getting Member List
If allowed in accordance with room configuration, an occupant MAY be allowed to retrieve the list of room members. For details, see the Modifying the Member List section of this document.
7.12 Discovering Reserved Room Nickname
A user MAY have a reserved room nickname, for example through explicit room registration, database integration, or nickname "lockdown". A user SHOULD discover his or her reserved nickname before attempting to enter the room. This is done by sending a Service Discovery information request to the room JID while specifying a well-known Service Discovery node of "x-roomuser-item".
Example 70. User Requests Reserved Nickname
<iq from='hag66@shakespeare.lit/pda'
id='getnick1'
to='darkcave@chat.shakespeare.lit'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='x-roomuser-item'/>
</iq>
It is OPTIONAL for a multi-user chat service to support the foregoing service discovery node. If the room or service does not support the foregoing service discovery node, it MUST return a <feature-not-implemented/> error to the user. If it does and the user has a registered nickname, it MUST return the nickname to the user as the value of the 'name' attribute of a Service Discovery <identity/> element (for which the category/type SHOULD be "conference/text"):
Example 71. Room Returns Nickname
<iq from='darkcave@chat.shakespeare.lit'
id='getnick1'
to='hag66@shakespeare.lit/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'
node='x-roomuser-item'>
<identity
category='conference'
name='thirdwitch'
type='text'/>
</query>
</iq>
If the user does not have a registered nickname, the room MUST return a service discovery <query/> element that is empty (in accordance with XEP-0030).
Even if a user has registered one room nickname, the service SHOULD allow the user to specify a different nickname on entering the room (e.g., in order to join from different client resources), although the service MAY choose to "lock down" nicknames and therefore deny entry to the user, including a <not-acceptable/> error. The service MUST NOT return an error to the user if his or her client sends the foregoing request after having already joined the room, but instead SHOULD reply as described above.
If another user attempts to join the room with a nickname reserved by the first user, the service MUST deny entry to the second user and return a <conflict/> error as previously described.
7.13 Requesting Voice
It is not possible for a visitor to speak (i.e., send a message to all occupants) in a moderated room. To request voice, a visitor SHOULD send a <message/> stanza containing a data form to the room itself, where data form contains only a 'muc#role' field with a value of "participant".
Example 72. Occupant Requests Voice
<message from='hag66@shakespeare.lit/pda'
to='darkcave@chat.shakespeare.lit'>
<x xmlns='jabber:x:data' type='submit'>
<field var='FORM_TYPE'>
<value>http://jabber.org/protocol/muc#request</value>
</field>
<field var='muc#role'
type='text-single'
label='Requested role'>
<value>participant</value>
</field>
</x>
</message>
The service then SHOULD forward the request to the room moderator(s) as described in the Approving Voice Requests section of this document.