轉自: https://blog.csdn.net/devinteng/article/details/44807957
XEP-0045
來自Jabber/XMPP中文翻譯計劃
本文的英文原文來自XEP-0045
XEP-0045: 多使用者聊天
摘要: 本文定義了一個XMPP協定擴充用于多使用者文本會議.即多個XMPP可以在一個房間或頻道互相交流資訊, 類似網際網路中繼聊天系統(IRC).還有标準聊天室功能如聊天室的主題和邀請,本協定定義了一個強有力的房間控制模型,包括能夠踢和禁止使用者,任命主持人和管理者,要求會員或密碼才能加入房間,等等。
作者: Peter Saint-Andre
XMPP擴充協定的版權(1999-2008)歸XMPP标準化基金會(XSF)所有
版權: © 1999 - 2010 XMPP标準化基金會(XSF). 參見法律通告.
狀态: 草案
類型: 标準跟蹤
版本: 1.24
最後更新日期: 2008-07-16
注意: 這裡定義的協定是XMPP标準化基金會的一個草案标準.對本協定的執行是被鼓勵的,也适于部署到生産系統,但是在它成為最終标準之前可能還會有一些變動.
目錄
|
緒論
傳統上, 即時消息被視為由一對一的聊天構成而不是多對多聊天(即所謂"群聊"或"文本會議"). 群聊功能常見于一些系統如 Internet Relay Chat (IRC) 和 流行的IM服務所提供的聊天室功能. Jabber社群早在1999年開發和實施了一個基本的群聊協定. 這個 "groupchat 1.0" 協定為聊天室提供了一個最小功能集但是範圍很有限. 本協定(多使用者聊天或簡稱MUC)建立在向後相容舊的"groupchat 1.0"協定的基礎上但是提供進階功能如邀請, 房間主持和管理, 以及專門的房間類型.
範圍
本文着重于和配置,參與以及管理一個獨立的基于文本的會議室相關的通用需求. 這裡所指出的需求是應用于單個房間級别的并且是"通用的", 某種意義上它們是在Jabber社群廣泛讨論的或在現有的Jabber之外的基于文本的會議環境(例如, 定義在RFC 1459 1中的Internet Relay Chat 和它的繼承者: RFC 2810 2, RFC 2811 3, RFC 2812 4, RFC 2813 5)中已經存在的.
本文明确地不涉及以下需求:
- 房間之間的關系(例如, 房間的層次結構)
- 多使用者聊天服務的管理(例如, 管理跨越整個服務級别的權限或注冊一個全局可用的房間昵稱);這些用例定義在Service Administration6
- 個别消息的主持
- 通過房間發送的消息的加密
- 進階特性, 如附加檔案給一個房間, 內建白闆, 以及和語音或視訊聊天服務的接口
- MUC部署和外來的聊天系統(例如, 和IRC網關或現有的其他IM系統)之間的互動
- 在多個MUC部署之間進行鏡像或複制
這一受限的範圍并非蔑視這些都很有用的主題; 無論如何, 這意味着本文專注于讨論和介紹一個易于了解的協定能夠被類似的Jabber用戶端群組件開發者實作. 将來的協定當然可能涉及以上提到的這些主題.
需求
本文描述了由Jabber現有的多使用者聊天服務提供的最小功能集. 為了向後相容性起見, 本文使用原來的"groupchat 1.0"協定作為基本功能, 包括以下這些:
- 每個房間被辨別為 <[email protected]> (例如, <[email protected]>), 這裡 "room" 是房間的名稱而 "service" 是多使用者聊天服務運作所在的主機名.
- 在一個房間裡每個房客被辨別為 <[email protected]/nick>, 這裡 "nick" 是這個房客在這個房間裡的昵稱,定義于剛加入這個房間的時候,也可以在房客駐留改房間期間修改.
- 一個使用者通過發送出席資訊給 <[email protected]/nick> 來加入一個房間(也就是成為房客).
- 在多使用者聊天房間裡發送的消息使用特殊的類型"groupchat"并且被尋址于房間本身 ([email protected]), 然後反映給所有房客.
- 通過發送出席資訊給 <[email protected]/newnick>,一個房客可以改變他或她的房間昵稱以及在房間中的可用性狀态 .
- 通過發送一個類型為"unavailable"的出席資訊給目前的<[email protected]/nick>,一個房客可以退出房間.
本文追加的特性和功能包括以下這些:
- 本地會話日志(不需要房間内的機器人)
- 允許使用者申請房間成員
- 在一個非匿名房間裡, 允許房客可以察看(另)一個房客的全JID
- 在一個半匿名房間裡, 允許主持人可以察看一個房客的全JID
- 允許隻有主持人修改房間主題
- 允許主持人從房間裡踢出與會者和遊客
- 在一個被主持的房間裡,主持人可以授予和撤銷發言權(也就是說, 發言的權力), 并且管理發言權清單
- 允許管理者授權和取消主持人權力, 并且管理主持人清單
- 允許管理者在房間禁止使用者, 并管理黑名單
- 允許管理者授予和撤銷成員權力, 并且管理一個僅限成員的房間的成員清單
- 允許所有者限制房客的數量
- 允許所有者指定其他的所有者(們)
- 允許所有者授予或撤銷管理特權, 并管理管理者清單
- 允許所有者銷毀房間
另外, 本文提供了協定元素用于支援以下房間類型:
- 公共的或隐藏的
- 持久的或臨時的
- 密碼保護的或不安全的
- 僅限成員的或開放的
- 主持的或非主持的
- 非匿名的或半匿名的
為了實作這些需求, 本擴充協定需要滿足 '術語
通用術語
Affiliation(崗位) -- 一個長期存在的和房間之間的聯系或連接配接; 可能的崗位有 "owner"(所有者), "admin"(管理者), "member"(成員), 以及 "outcast"(被排斥者) (當然也可能沒有崗位); 崗位(affiliation)和角色(role)是有差別的. 一個崗位跨越了使用者對一個房間的通路期間.
Ban(禁止) -- 從一個房間移除一個使用者以使這個使用者不能夠再進入這個房間 (直到這個禁令被廢除為止). 一個被禁止的使用者的崗位(affiliation)為 "outcast"(被排斥者).
Bare JID(純JID) -- 一個使用者的辨別符 <[email protected]>, 不同于任何已有會話或資源的上下文, 與之相對的是全JID和房間JID.
Full JID(全JID) -- 一個線上使用者的辨別符 <[email protected]/resource> , 不同于一個房間的上下文; 與之相對的是純JID和房間JID.
GC -- 最小的 "groupchat 1.0" 協定[7], Jabber社群于1999年開發; MUC 向後相容GC.
History(曆史) -- 有限數量的消息節, 由目前讨論的上下文提供發送給一個新的房客.
Invitation(邀請) -- 從一個使用者發出的特殊消息給另一個使用者, 邀請對方加入房間.; the invitation can be sent directly (see Direct MUC Invitations [8]) or mediated through the room (as described under Inviting Another User to a Room).
IRC -- Internet Relay Chat.
Kick(踢人) -- 臨時從一個房間移除一個與會者或遊客; 這個使用者任何時候都可以再次進入這個房間. 一個被踢的使用者的角色是"none".
Logging(記錄) -- 存儲發生在一個房間的讨論内容用于公開釋出到房間上下文之外的地方.
Member(成員) -- 一個使用者在一個僅限會員的房間内處于"white list"(白名單)内,或已經注冊到一個公開的房間. 一個成員的崗位是"member".
Moderator(主持人) -- 一個房間角色,通常和房間的管理有關但是這個角色可以被賦予非管理者; 可以踢人, 可以授予和撤銷發言權, 等等. 一個主持人的角色是"moderator".
MUC -- 本文所定義的基于文本會議的多使用者聊天協定.
Occupant(房客) -- 一個房間裡的任何Jabber使用者 (這是一個 "抽象類" 并且不對應任何特定的角色).
Occupant JID(房客JID) -- 在一個房間上下文中的一個房客,以 <[email protected]/nick> 來辨別; 與之相對的是純JID和全JID.
Outcast(被排斥者) -- 一個被某個房間禁止的使用者. 一個被排斥者的崗位是 "outcast".
Participant(與會者) -- 一個沒有管理權限的房客; 在一個被主持的房間裡, 參與者更多地被定義為有發言權的 (與之相反的是遊客). 一個與會者的角色是"participant".
Private Message(私有消息) -- 從一個房客直接發給另一個房間JID的消息(不是房間本身廣播給所有房客的消息).
Role(角色) -- 在一個房間裡的一個臨時的地位或者權限級别, 對于這個房間中的使用者的長期崗位來說是唯一的; 可能的角色有 "moderator"(主持人), "participant"(與會者), 和 "visitor"(遊客) (也可能沒有預定義的角色). 一個角色僅僅存在于一個房客通路一個房間的期間.
Room(房間) -- 一個虛拟的地方, Jabber使用者象征性地加入它, 來和其他使用者一起參與一個實時的基于文本的會議.
Room Administrator(房間管理者) -- 一個由房間所有者授權的使用者, 可以執行管理功能, 如禁止使用者等等; 無論如何, 不允許改變定義的房間特性. 一個管理者的崗位是"admin" .
Room ID(房間ID) -- 一個房間JID的節點辨別符部分, 它可以是不透明的因而對人類使用者沒有什麼含義(見 文法的商業規則Business Rules for syntax); 與之相對的是房間名.
Room JID(房間JID) -- 房間位址,如 <[email protected]>
Room Name(房間名) -- 一個使用者友好的, 自然語言的房間名字, 由房間所有者配置并在服務查詢中展示; 與之相對的是房間ID.
Room Nickname(房間昵稱) -- 房間JID的資源辨別符部分(見文法的商業規則); 這是一個房客在這個房間中所呈現的"友好的名字".
Room Owner(房間所有者) -- 建立某個房間的Jabber使用者或一個被房間建立者或所有者指派擁有所有者權限(如果允許的話)的Jabber使用者; 它被允許改變定義好的房間特性, 也可以執行全部的管理功能. 一個所有者的崗位為"owner".
Room Roster(房間名冊) -- 一個房間中的所有房客在一個Jabber用戶端的展現.
Server(伺服器) -- 一個Jabber伺服器,可以關聯或不關聯一個基于文本的會議服務.
Service(服務) -- 一個主機, 提供基于文本的會議的能力; 通常但不必須是一個Jabber伺服器的子域(例如, conference.jabber.org).
Subject(主題) -- 一個房間的臨時讨論标題.
Visit(通路) -- 一個房間的一個使用者的"session"(會話), 當使用者進入這個房間時開始(也就是說, 成為一個房客) , 結束于使用者離開房間之時.
Visitor(遊客) -- 在一個被主持的房間裡的一個沒有發言權的房客(相反則是一個與會者). 一個遊客的角色是"visitor".
Voice(發言權) -- 在一個被主持的房間裡, 發送消息給全部房客的權限.
房間類型
Hidden Room(隐藏房間) -- 一個無法被任何使用者以普通方法如搜尋和服務查詢來發現的房間; 反義詞: 公開(public)房間.
Members-Only Room(僅限會員的房間) -- 如果一個使用者不在成員清單中則無法加入的一個房間; 反義詞: 開放(open)房間.
Moderated Room(被主持的房間) -- 隻有有"發言權"的使用者才可以發送消息給所有房客的房間; 反義詞: 非主持的(Unmoderated)房間.
Non-Anonymous Room(非匿名房間) -- 一個房客的全JID會暴露給所有其他房客的房間, 盡管房客可以選擇任何期望的房間昵稱; 相對的是半匿名(Semi-Anonymous)房間.
Open Room(開放房間) -- 任何人可以加入而不需要在成員清單中的房間; 反義詞: 僅限會員的房間.
Password-Protected Room(密碼保護房間) -- 一個使用者必須提供正确密碼才能加入的房間; 反義詞: 非保密房間.
Persistent Room(持久房間) -- 如果最後一個房客退出也不會被銷毀的房間; 反義詞: 臨時房間.
Public Room(公開房間) -- 使用者可以通過普通方法如搜尋和服務查詢來發現的房間; 反義詞: 隐藏房間.
Semi-Anonymous Room(半匿名房間) -- 一個房客的全JID隻能被房間管理者發現的房間; 相對的是非匿名(Non-Anonymous)房間.
Temporary Room(臨時房間) -- 如果最後一個房客退出就會被銷毀的房間; 反義詞: 持久房間.
Unmoderated Room(非主持的房間) -- 任何房客都被允許發送消息給所有房客的房間; 反義詞: 被主持的房間.
Unsecured Room(非保密房間) -- 任何人不需要提供密碼就可以進入的房間; 反義詞: 密碼保護房間.
登場人物
本文的大部分例子使用了莎士比亞的《麥克白》中第四幕第一場開頭女巫在黑洞中開會的場景,在這裡使用"[email protected]"代表聊天室. 人物如下:
表1: 劇中人
Room Nickname | Full JID | Affiliation |
---|---|---|
firstwitch | [email protected]/desktop | Owner |
secondwitch | [email protected]/laptop | Admin |
thirdwitch | [email protected]/pda | None |
角色(Roles),崗位(Affiliations)和權限(Privileges)
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:
1. Define each privilege atomically and explicitly define each user's particular privileges; this is flexible but can be confusing to manage.
2. Define bundles of privileges that are generally applicable and assign a user-friendly "shortcut" to each bundle (e.g., "moderator" or "admin").
MUC使用第2種方式。
有兩個尺度我們可以用來衡量一個使用者的連接配接或在一個房間的地位. 一個是使用者和一個房間的長期的聯系 -- 例如, 使用者的狀态是一個所有者或一個被排斥者. 另一個是當使用者駐留于一個聊天室的時候的角色 -- 例如, 一個房客的地位是主持人,有權踢出遊客和與會者. 這兩個尺度各自都是唯一的, 因為一個崗位是跨越通路的, 而一個角色隻存在于一次通路期間. 另外, 在角色和崗位之間沒有一對一的對應關系; 例如, 某個不從屬于某房間的人可能成為一個(臨時的)主持人, 一個成員可能在一個被主持的房間中是一個與會者或遊客者. 這些概念以下全面解釋.
角色
以下是已定義的角色:
表2: 角色
名稱 | 支援 |
---|---|
主持人Moderator | 必需的 |
無None | 缺少角色 |
與會者Participant | 必需的 |
遊客Visitor | 推薦的 |
角色是臨時的,它不一定要在使用者對房間的通路中持久化,它可以(MAY)在一個房客通路房間期間改變. 一個實作可以(MAY)在一次通路期間持久化角色并且應該(SHOULD)在被主持的房間這樣做 (因為在遊客和與會者之間,唯一性對一個被主持的房間是很關鍵的).
在角色和崗位之間沒有一對一的映射(例如, 一個成員可以是一個與會者或一個遊客).
在房間會話中,一個主持人是最有權力的房客, 它能在某種程度走上管理房間的其他房客的角色. 一個與會者的權力小于一個主持人, 盡管他或她有權發言. 在一個被主持的房間會話中遊客是一個更受限制的角色, 因為通路者不允許發送消息給所有房客.
角色的授予,撤銷, 和維護是基于房客的房間昵稱或全JID,而不是純JID. 和這些角色相關的權限,還有角色改變觸發的動作, 定義在下文中.
所有在房間中生成或反射的出席資訊中關于角色的資訊必須(MUST)被發送,進而發送給房客們.
權限
大部分情況下, 角色存在于一個層次中. 例如, 一個與會者可以做任何遊客能做的事, 而一個主持人可以做任何與會者能做的事. 每個角色擁有下一級角色所沒有的權限; 這些權限定義于下表作為預設值(一個實作可以(MAY)提供配置選項來重載這些預設值).
表3: 和角色相關的權限
權限 | 無 | 遊客 | 與會者 | 主持人 |
---|---|---|---|---|
在房間中出席 | 否 | 是 | 是 | 是 |
接收消息 | 否 | 是 | 是 | 是 |
接收房客出席資訊 | 否 | 是* | 是 | 是 |
出席資訊廣播到房間 | 否 | 是* | 是 | 是 |
改變可用性狀态 | 否 | 是 | 是 | 是 |
改變房間昵稱 | 否 | 是* | 是 | 是 |
發送私人消息 | 否 | 是* | 是 | 是 |
邀請其他使用者 | 否 | 是* | 是* | 是 |
發送消息給所有人 | 否 | 否** | 是 | 是 |
修改标題 | 否 | 否* | 是* | 是 |
踢出與會者和遊客 | 否 | 否 | 否 | 是 |
授予發言權 | 否 | 否 | 否 | 是 |
撤銷發言權 | 否 | 否 | 否 | 是*** |
- 預設; 設定配置時可以(MAY)修改這個權限.
-
- 一個實作可以(MAY)在非主持的房間裡預設地授予發言權給遊客.
-
-
- 主持人不能(MUST NOT)從一個管理者或所有者收回發言權.
-
預設角色
服務必須(SHOULD)根據使用者的崗位資訊來設定房客在房間裡的預設角色(沒有與崗位(“outcast”)關聯的預設角色,因為outcast使用者不允許進入房間)。下表對與每個崗位關聯的預設角色進行了總結。
表4: 基于崗位的預設角色
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.
變更角色
一個房客的角色變更方法是定義好的. 有時候房客自己的動作導緻變更 (例如, 加入或退出房間), 反之有時候由主持人,管理者或所有者的動作導緻變更. 如果一個房客的角色改變了, 一個 MUC 服務實作必須(MUST)變更這個房客的角色來反映這個變更并且傳達這個變更給所有房客. 角色的變更和它們觸發的動作定義于下表.
表4: 角色狀态表
> | 無 | 遊客 | 與會者 | 主持人 |
---|---|---|---|---|
無 | -- | 進入被主持的房間 | 進入非主持的房間 | 管理者或所有者進入房間 |
遊客 | 退出房間或被主持人踢出房間 | -- | 主持人授予發言權 | 管理者或所有者授予主持人權限 |
與會者 | 退出房間或被主持人踢出房間 | 主持人撤銷發言權 | -- | 管理者或所有者授予主持人權限 |
主持人 | 退出房間 | 管理者或所有者改變角色成為遊客* | 管理者或所有者改變角色成為與會者或撤銷主持人權限* | -- |
- 一個主持人不能(MUST NOT)從一個崗位等于或高于主持人的房客那裡收回主持人權限.
注意: 特定的角色一般暗含特定的權限. 例如, 一個管理者或所有者自動成為一個主持人, 是以如果一個房客被授予管理者地位那麼這個房客事實上将被授予主持人權限; 類似的, 當一個房客成為一個被主持的房間的成員, 這個房客自動擁有一個與會者的角色. 無論如何, 失去管理者地位并不足以意味這個房客不再是主持人 (因為隻要是與會者就可能成為一個主持人). 是以, 當一個房客被授予特定的崗位的時候所擁有的角色是固定的, 反之當一個房客失去一個特定的崗位時它的角色是不确定的并取決于(服務的)實作. 因為一個用戶端無法預料是否在撤銷某個崗位之後這個角色成為什麼, 如果它不想同時移除管理者/所有者權限和主持人角色, 那麼除了崗位變更之外它還必須特意請求角色變更.
崗位
已定義了以下崗位:
- 所有者
- 管理者
- 成員
- 被排斥者
- 無 (缺少崗位)
必須支援"所有者"這個崗位,推薦支援"管理者","成員","被排斥者"的崗位.("無"表示缺少崗位)
這些崗位是長時間的跨越一個使用者對這個房間的通路期間的并且不受房間裡事件的影響. 而且, 這些崗位和一個房客在房間中的角色之間沒有一對一的映射關系. 崗位被授予,撤銷, 和維護都是基于這個使用者的純 JID.
如果一個沒有已定義的崗位的使用者進入一個房間, 這個使用者的崗位被定義為"無"; 無論如何, 這個崗位不能跨越(多次的)通路 (也就是說, 一個服務不會跨越通路維護一個 "無 清單").
"成員"崗位為房間所有者或管理者提供了一個方法來指定一個"白名單",其中的使用者被允許加入一個僅供會員的房間. 當一個成員加入了一個僅供會員的房間, 他或她的崗位不會改變, 無論他或她的角色是什麼. 成員崗位也為使用者提供一個方法來高效地注冊一個開放的房間并在某種方式意義上保持和那個房間的聯系(例如可能在房間裡預留那個使用者的昵稱).
一個被排斥者就是一個被從房間踢出來并且不允許進入那個房間的使用者.
關于崗位的資訊必須(MUST)由房間生成或反射到所有的出席資訊節之中發送給房客們.
權限
大部分情況下, 崗位存在一個層次結構. 例如, 一個所有者可以做任何管理者能做的事情, 而一個管理者可以做任何成員能做的事情. 每個崗位擁有其下一級崗位所沒有的權限; 這些權限定義在下表中.
表5: 和崗位相關的權限
權限 | Outcast(被排斥者) | None(無) | Member(成員) | Admin(管理者) | Owner(所有者) |
---|---|---|---|---|---|
進入房間 | 否 | 是* | 是 | 是 | 是 |
注冊一個開放的房間 | 否 | 是 | N/A | N/A | N/A |
接收成員清單 | 否 | 否** | 是 | 是 | 是 |
加入一個僅限會員的房間 | 否 | 否 | 是* | 是 | 是 |
禁止成員并把使用者的崗位删除 | 否 | 否 | 否 | 是 | 是 |
編輯成員清單 | 否 | 否 | 否 | 是 | 是 |
編輯主持人清單 | 否 | 否 | 否 | 是** | 是** |
編輯管理者清單 | 否 | 否 | 否 | 否 | 是 |
編輯所有者清單 | 否 | 否 | 否 | 否 | 是 |
變更房間定義 | 否 | 否 | 否 | 否 | 是 |
銷毀房間 | 否 | 否 | 否 | 否 | 是 |
- 作為預設值, 一個無崗位的使用者進入一個被主持的房間的角色是一個遊客, 而進入一個開放的房間的角色是一個與會者. 一個成員進入一個房間的角色是與會者. 一個管理者或所有者進入房間的角色是一個主持人.
-
- 一個管理者或所有者不能(MUST NOT)撤銷另一個管理者或所有者的權限.
變更崗位
一個使用者的崗位變更方法已經定義得很完善. 有時使用者自己的動作導緻這些變更(例如, 注冊為一個房間的新成員), 反之有時候一個管理者或所有者的動作導緻了這些變更. 如果一個使用者的崗位改變了, 一個MUC服務實作必須(MUST)變更這個使用者的崗位來反射這一變更并通知所有房客. 崗位變更和他們觸發的動作定義在下表中.
表6: 崗位狀态表
被排斥者(Outcast) | 無(None) | 成員(Member) | 管理者(Admin) | 所有者(Owner) | |
被排斥者(Outcast) | -- | 管理者或所有者移除屏蔽 | 管理者或所有者增加使用者到成員清單 | 所有者增加使用者到管理者清單 | 所有者增加使用者到所有者清單 |
無(None) | 管理者或所有者使用屏蔽 | -- | 管理者或所有者增加使用者到成員清單, 或使用者注冊一個成員(如果允許) | 所有者增加使用者到管理者清單 | 所有者增加使用者到所有者清單 |
成員(Member) | 管理者或所有者使用屏蔽 | 管理者或所有者變更崗位為"none" | -- | 所有者增加使用者到管理者清單 | 所有者增加使用者到所有者清單 |
管理者(Admin) | 所有者使用屏蔽 | 所有者變更崗位為"none" | 所有者變更崗位為"member" | -- | 所有者增加使用者到所有者清單 |
所有者(Owner) | 所有者使用屏蔽 | 所有者變更崗位為"none" | 所有者變更崗位為"member" | 所有者變更崗位為"admin" | -- |
實體用例
一個MUC實作必須(MUST)支援服務發現7.
MUC的發現元件支援
一個Jabber實體可能希望發現是否一個服務實作了多使用者聊天協定; 為了達到這個目的, 它發送一個服務發現資訊("disco#info")查詢給這元件的JID:
例子 1. 使用者通過Disco查詢聊天服務是否支援MUC
<iq from='[email protected]/pda'
id='disco1'
to='macbeth.shakespeare.lit'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
服務必須(MUST)傳回它的的身份和它所支援的特性:
例子 2. 服務傳回Disco Info結果
<iq from='macbeth.shakespeare.lit'
id='disco1'
to='[email protected]/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity
category='conference'
name='Macbeth Chat Service'
type='text'/>
<feature var='http://jabber.org/protocol/muc'/>
</query>
</iq>
注意: 因為MUC是舊的"groupchat 1.0"協定的超集, 一個MUC服務不應該(SHOULD NOT)傳回一個<feature var='gc-1.0'/>條目在一個disco#info結果中.
發現房間
發現服務條目("disco#items")協定使得一個使用者可以向一個服務查詢相關的條目清單, 在一個聊天服務中這包含這個服務所承載的所有特定房間的集合.
例子 3. 使用者向聊天服務查詢房間
<iq from='[email protected]/pda'
id='disco2'
to='macbeth.shakespeare.lit'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
服務應該(SHOULD)傳回它承載的所有房間的清單.
例子 4. 服務傳回Disco Item結果
<iq from='macbeth.shakespeare.lit'
id='disco2'
to='[email protected]/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item jid='[email protected]'
name='A Lonely Heath'/>
<item jid='[email protected]'
name='A Dark Cave'/>
<item jid='[email protected]'
name='The Palace'/>
<item jid='[email protected]'
name='Macbeth's Castle'/>
</query>
</iq>
如果全部房間的清單太大(詳見XEP-0030), 服務可以(MAY)隻傳回部分的房間清單.如果這樣做了, 它應該 SHOULD 包含一個 <set/> 元素 (定義在Result Set Management 8) 以表明這個清單不是全部的結果集.
例子 5. 服務傳回Disco Item結果的部分清單
<iq from='rooms.shakespeare.lit'
id='disco-rsm-1'
to='[email protected]/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item jid='[email protected]'/>
<item jid='[email protected]'/>
<item jid='[email protected]'/>
<item jid='[email protected]'/>
<item jid='[email protected]'/>
<item jid='[email protected]'/>
<item jid='[email protected]'/>
<item jid='[email protected]'/>
<item jid='[email protected]'/>
<item jid='[email protected]'/>
<set xmlns='http://jabber.org/protocol/rsm'>
<first index='0'>[email protected]</first>
<last>[email protected]</last>
<count>37</count>
</set>
</query>
</iq>
查詢房間資訊
使用 disco#info 協定, 一個使用者也可以查詢一個特定房間的詳情. 為了在進入房間之間确定這個房間的隐私和安全配置使用者應該(SHOULD)這樣做(詳見安全事項).
例子 6. 使用者查詢特定聊天室的資訊
<iq from='[email protected]/pda'
id='disco3'
to='[email protected]'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
房間必須(MUST)傳回它的辨別并且應該(SHOULD)傳回它支援的特性:
例子 7. 房間傳回查詢資訊結果
<iq from='[email protected]'
id='disco3'
to='[email protected]/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<identity
category='conference'
name='A Dark Cave'
type='text'/>
<feature var='http://jabber.org/protocol/muc'/>
<feature var='muc_passwordprotected'/>
<feature var='muc_hidden'/>
<feature var='muc_temporary'/>
<feature var='muc_open'/>
<feature var='muc_unmoderated'/>
<feature var='muc_nonanonymous'/>
</query>
</iq>
注意: 因為 MUC 是舊的 "groupchat 1.0" 協定的超集, 一個 MUC 房間不應該(SHOULD NOT)在一個disco#info結果中傳回<feature var='gc-1.0'/>條目. 房間應該(SHOULD)傳回它支援的實質的有意義的特性, 例如密碼保護和房間主持(這些特性被完整地列入了特性注冊, 由XMPP Registrar維護; 也見于本文的XMPP注冊 章節).
一個聊天室可以(MAY)使用服務查詢擴充9在它的disco#info應答中傳回更詳細的資訊, 通過包含一個隐含的FORM_TYPE屬性值"http://jabber.org/protocol/muc#roominfo"來辨別. 這些資訊可能包括關于一個房間的更詳細的描述, 目前的房間标題, 以及這個房間目前的房客數量:
例子 8. 房間傳回擴充的查詢資訊結果
<iq from='[email protected]'
id='disco3a'
to='[email protected]/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='Whether Occupants May Change the Subject'>
<value>true</value>
</field>
<field var='muc#roominfo_contactjid' label='Contact Addresses'>
<value>[email protected]</value>
</field>
<field var='muc#roominfo_subject' label='Subject'>
<value>Spells</value>
</field>
<field var='muc#roominfo_occupants' label='Number of occupants'>
<value>3</value>
</field>
<field var='muc#roominfo_lang' label='Language of discussion'>
<value>en</value>
</field>
<field var='muc#roominfo_logs' label='URL for discussion logs'>
<value>http://www.shakespeare.lit/chatlogs/darkcave/</value>
</field>
<field var='muc#roominfo_pubsub' label='Associated pubsub node'>
<value>xmpp:pubsub.shakespeare.lit?node=chatrooms/darkcave</value>
</field>
</x>
</query>
</iq>
某些擴充的房間資訊可能是動态生成的(例如, 讨論記錄的URL位址, 它可能取決于伺服器那一層的配置); 反之另一些資訊則可能基于房間那一層的配置,任何定義在muc#roomconfig FORM_TYPE 裡的字段都可以用于擴充服務發現的字段(如上文所示的 muc#roomconfig_changesubject 字段).
注意: 前述 '字段标準化章節描述的機制).
查詢房間條目
一個使用者也可以(MAY)向一個特定的聊天室查詢和它相關的條目:
例子 9. 使用者查詢和一個特定聊天室相關的條目
<iq from='[email protected]/pda'
id='disco4'
to='[email protected]'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
一個實作可以(MAY)傳回現有房客的清單(如果那資訊是可公開的), 或不傳回清單(如果那資訊是私有的).
例子 10. 房間傳回查詢條目結果(條目是公開的)
<iq from='[email protected]'
id='disco4'
to='[email protected]/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<item jid='[email protected]/firstwitch'/>
<item jid='[email protected]/secondwitch'/>
</query>
</iq>
注意: 這些 <item/> 元素由 disco#items 名字空間限定, 而不是 muc 名字空間; 這意味着他們不能擁有 'affiliation' 或 'role' 屬性, 例如.
例子 11. 房間傳回空的查詢條目結果(條目是私有的)
<iq from='[email protected]'
id='disco4'
to='[email protected]/pda'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
查詢一個房間的房客
如果一個非房客試圖發送一個查詢請求給一個<[email protected]/nick>類型的位址, 一個 MUC 服務應該(SHOULD)傳回這個請求給這個實體并指明一個<bad-request/>錯誤條件. 如果一個房客發送這樣一個請求, 服務可以(MAY)把它傳遞給指定的接收者; 詳見本文的實作注意事項章節.
發現用戶端對MUC的支援
一個 Jabber 使用者可能想發現這個使用者的某個聯系人是否支援多使用者聊天協定. 這可以使用服務發現(協定)來完成.
例子 12. 使用者查詢聯系人對于 MUC 的支援
<iq from='[email protected]/pda'
id='disco5'
to='[email protected]/laptop'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
用戶端應該(SHOULD)傳回它的辨別和它支援的特性:
例子 13. 聯系人傳回發現資訊結果
<iq from='[email protected]/laptop'
id='disco5'
to='[email protected]/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>
一個使用者也可能查詢一個聯系人在哪個房間. 這可以通過特定服務發現節點 '房客用例
在一個多使用者聊天環境中主要的行為者是房客, 它可以被認為存在于一個多使用者聊天室"之内"并且參與那個房間的讨論 (在本協定中, 與會者和遊客"僅僅"被認為是房客, 因為他們不擁有管理者權限). 為了更加清晰起見, 本文中的協定元素中涉及到駐留者的用例分為以下三類:
- 現存于 "groupchat 1.0" 協定的最小功能集
- 對于 "groupchat 1.0" 協定直接的應用, 如處理一些和新房間類型有關的錯誤
- 用來處理"groupchat 1.0"協定未涉及的功能的額外的協定元素(房間邀請, 房間密碼, 和房間角色及崗位相關的擴充出席資訊); 在'RFC 3920 [10]中所要求的)未顯示在這裡.
進入一個房間
Groupchat 1.0協定
為了參加一個多使用者聊天室的讨論, 一個Jabber使用者必須(MUST)首先進入一個房間成為一個房客. 在舊的"groupchat 1.0"協定中, 這是通過發送出席資訊<[email protected]/nick>來實作的, 這裡"room"是房間的 ID, "service" 是聊天服務的主機名, "nick" 是這個使用者在這房間裡預期的昵稱:
例子 16. Jabber使用者進入一個房間(Groupchat 1.0)
<presence from='[email protected]/pda' to='[email protected]/thirdwitch'/>
在這個例子中, 一個全JID為"[email protected]/pda"的使用者請求用昵稱"thirdwitch"進入位于"macbeth.shakespeare.lit"聊天服務的房間"darkcave".
如果使用者未指定一個房間昵稱, 服務應該(SHOULD)傳回一個<jid-malformed/>錯誤:
例子 17. Jabber使用者進入一個房間(Groupchat 1.0)
<presence from='[email protected]' to='[email protected]/pda' type='error'> <error code='400' type='modify'> <jid-malformed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </presence>
基本MUC協定
相容的多使用者聊天服務必須(MUST)接受知道"groupchat 1.0" (GC)協定或multi-user chat (MUC)協定的任何用戶端發出上述請求進入會議室; 無論如何, MUC 用戶端應該(SHOULD)聲明他們的有能力支援 MUC 協定, 方法是在出席資訊節裡面包含一個空的 <x/> 元素, 滿足名字空間 '
注意: 如果發生了一個和加入房間有關的錯誤, 服務應該 SHOULD 傳回一個包含 MUC 子元素 (i.e., <x xmlns='
在嘗試進入房間之間, 一個相容MUC的用戶端應該(SHOULD)首先查詢它的保留的房間昵稱 (如果有的話), 接下來的協定本文中的 發現保留的房間昵稱 章節對此作了定義.
出席資訊廣播
如果服務能夠添加使用者到房間, 它必須(MUST)從所有現存的房客的房間JID發送出席資訊給新的房客的全JID, 包括擴充的關于角色的出席資訊, 一個滿足 '
例子 19. 服務從現有的房客發送出席資訊給新的房客
<presence from='[email protected]/firstwitch' to='[email protected]/pda'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='owner' role='moderator'/> </x> </presence> <presence from='[email protected]/secondwitch' to='hag[email protected]/pda'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='admin' role='moderator'/> </x> </presence>
這個示例中, 使用者已從前一個例子進入房間, 有兩個人已經在房間裡: 一個是昵稱為"firstwitch"的(房間擁有者), 另一個是昵稱為"secondwitch"的(房間管理者).
服務也必須(MUST)從新進入的房客的房間JID向所有房客的全JID發送出席資訊(含新房客):
例子 20. 服務發送新房客的出席資訊給所有房客
<presence from='[email protected]/thirdwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' role='participant'/> </x> </presence> <presence from='[email protected]/thirdwitch' to='[email protected]/laptop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' role='participant'/> </x> </presence> <presence from='[email protected]/thirdwitch' to='[email protected]/pda'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' role='participant'/> <status code='110'/> </x> </presence>
在這個例子裡, 初始的房間出席資訊從新房客(thirdwitch)發送給所有房客, 包括這個新房客自己. 看看上面最後一個節, 由房間以房客的名義發送給使用者自己的出席資訊,應該 SHOULD 包含一個 110 狀态碼,這樣使用者就知道這個出席資訊來自于作為房客的那個他自己.
服務可以 MAY 重寫新房客的房間昵稱 (例如, 如果房間昵稱被鎖定). 如果服務不接受新房客請求的房間昵稱,而是配置設定一個新的房間昵稱, 它必須 MUST 包含一個 "210" 狀态碼在發送給這個新房客的出席資訊廣播裡.
例子 21. 服務發送新房客的出席資訊給新房客
<presence from='[email protected]/thirdwitch' to='[email protected]/pda'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' role='participant'/> <status code='110'/> <status code='210'/> </x> </presence>
注意: 發送給新房客的出席資訊的順序是很重要的. 服務必須 MUST 首先發送現有房客的完整清單給這個新房客,然後隻發送新房客自己的出席資訊給新房客. 這有助于用戶端知道什麼時候它收到了完整的房間名冊( "room roster").
發送出席資訊廣播之後(并且隻在這之後), 服務可以發送讨論曆史, 即時消息, 出席資訊更新, 以及其他房間内的流量.
預設角色
下表總結了初始預設的角色,一個服務應該根據使用者的崗位來設定它們(沒有和 被排斥者 "outcast" 崗位相關的角色, 因為這些使用者不允許進入房間).
表7: 基于崗位的初始角色
房間類型 無 成員 管理者 所有者 被主持的 遊客 與會者 主持人 主持人 非主持的 與會者 與會者 主持人 主持人 僅限會員的 N/A * 與會者 主持人 主持人 開放的 與會者 與會者 主持人 主持人 - 實體不被允許.
非匿名房間
如果房間是非匿名的, 服務必須 MUST 發送新房客的全JID給所有房客,使用滿足 '
例子 23. 服務發送新房客的出席資訊給新房客
<presence from='[email protected]/thirdwitch' to='[email protected]/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>
無論如何, 也可以 MAY 發送一個 "groupchat" 類型的消息給新房客來達到上述目的,這個消息應該包含一個 <x/> 子元素,并擁有 <status/> 子元素,并且其'code'屬性值為"100":
例子 24. 服務警告新房客(該房間)非匿名
<message from='[email protected]' to='[email protected]/pda' type='groupchat'> <body>This room is not anonymous.</body> <x xmlns='http://jabber.org/protocol/muc#user'> <status code='100'/> </x> </message>
附帶的狀态碼協助用戶端展示它們自己的通知消息 (例如, 和使用者所在地方有關的資訊).
半匿名房間
如果房間是半匿名的, 服務必須 MUST 如上文所述從新房客發送出席資訊給所有房客, 但是必須 MUST 隻在發給"主持人"的時候發送新房客的全JID,而非主持人則不發(全JID).
(注意: 所有随後的例子中,涉及的<item/>元素都帶有'jid'屬性, 即使這個資訊在半匿名房間裡不被發送給非主持人.)
密碼保護房間
如果房間要求密碼驗證而使用者不能提供(或密碼錯誤), 服務必須 MUST 拒絕通路這個房間并且通知該使用者它們是未被授權的; 具體方法是傳回一個類型為"error"的出席資訊節并标明 <not-authorized/> 錯誤:
例子 25. 服務拒絕通路,因為(使用者)未提供密碼
<presence from='[email protected]' to='[email protected]/pda' type='error'> <x xmlns='http://jabber.org/protocol/muc'/> <error type='auth'> <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </presence>
密碼應該 SHOULD 通過進入房間時發送的出席資訊節來提供, 包含在滿足 '安全事項章節).
例子 26. 使用者進入房間時提供密碼
<presence from='[email protected]/pda' to='[email protected]/thirdwitch'> <x xmlns='http://jabber.org/protocol/muc'> <password>cauldronburn</password> </x> </presence>
僅限會員房間
如果房間是僅限會員的,但使用者不是(該房間的)成員, 服務必須 MUST 拒絕通路這個房間并通知使用者它們不被允許進入房間; 具體方法是傳回一個"error"類型的出席資訊節,并包含一個 <registration-required/> 錯誤條件:
例子 27. 服務拒絕通路,因為使用者不在成員清單中
<presence from='[email protected]' to='[email protected]/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>
被禁止的使用者
如果使用者已經被房間禁止(即, 其崗位為被排斥者 "outcast"), 服務必須 MUST 拒絕通路這個房間并通知使用者他(她)被禁止了; 具體方法是傳回一個出席資訊節,類型為"error",标明 <forbidden/> 錯誤條件:
例子 28. 服務拒絕通路,因為使用者被禁止了
<presence from='[email protected]' to='[email protected]/pda' type='error'> <x xmlns='http://jabber.org/protocol/muc'/> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </presence>
昵稱沖突
如果房間裡已經有别的使用者使用了準備進入房間的新使用者預期的昵稱(或如果這個昵稱被保留給另一個成員清單裡面的使用者), 服務必須 MUST 拒絕通路這個房間并通知使用者這個沖突; 具體方法是傳回一個出席資訊節,類型為"error",标明 <conflict/> 錯誤條件:
例子 29. 服務拒絕通路,因為昵稱沖突
<presence from='[email protected]' to='[email protected]/pda' type='error'> <x xmlns='http://jabber.org/protocol/muc'/> <error type='cancel'> <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </presence>
無論如何, 如果現有房客的純 JID <[email protected]> 和準備進入房間的使用者的純 JID 相同, 那麼服務應該 SHOULD 允許這個使用者的進入, 是以這個使用者就有兩個(或更多) 房間内的會話 "sessions" 使用同一個房間昵稱, 每一個對應一個資源. 如果一個服務允許相同純JID可以同時存在多個房客并使用同一個房間的房間昵稱, 它應該 SHOULD 路由房間内的消息給該使用者的所有資源并允許使用者的所有資源發送消息給房間; 視實作而定,服務來決定如何适當的處理從使用者的資源發送的出席資訊以及如何路由私有消息到所有或某個資源(基于出席資訊優先級或其他機制).
如何确定昵稱沖突取決于實作(例如, 該服務是否應用于一個特定的慣例, 一個 stringprep 規則如 Resourceprep 或 Nodeprep, 等等).
最大使用者數
如果房間達到它的最大房客數量, 服務應該 SHOULD 拒絕通路這個房間并通知該使用者這個限制; 方法是傳回一個出席資訊節,類型為"error",标明 <service-unavailable/> 錯誤條件:
例子 30. 服務通知使用者該房間已達到房客數量極限
<presence from='[email protected]' to='[email protected]/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>
另外, 房間可以踢出空閑使用者("idle user")以騰出空間.
如果房間的房客數量已達到最大值但是一個房間管理者或所有者試圖進入,該房間應該允許管理者或所有者加入,為了使得額外的房客達到一個合理的數目,該數量可以 MAY 做成可配置的。
鎖住的房間
如果一個使用者嘗試進入一個房間而該房間是鎖住的 "locked" (即, 在房間建立者提供初始的配置之前以及也就是在房間正式存在之前), 服務必須 MUST 拒絕進入并傳回一個 <item-not-found/> 錯誤給該使用者:
例子 31. 服務拒絕通路,因為房間不存在
<presence from='[email protected]' to='[email protected]/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>
不存在的房間
如果使用者準備進入房間時,該房間已經不存在了, 服務應該 SHOULD 建立它; 無論如何, 這不是必需的, 因為一個實作或部署可以 MAY 選擇限制建立房間的權限. 詳見本文的建立房間章節.
房間記錄
如果使用者進入一個房間,該房間的讨論是被記錄到一個公開的存檔裡面(經常可以通過HTTP通路的), 服務應該 SHOULD 允許該使用者加入該房間但是必須 MUST 同時警告該使用者讨論已被記錄. 方法是應該 SHOULD 在房間發送給該新房客的初始出席資訊中包含一個狀态碼 "170":
例子 32. 服務發送新房客的出席資訊給新房客
<presence from='[email protected]/thirdwitch' to='[email protected]/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>
讨論曆史
如上發送完初始出席資訊之後, 一個房間可以 MAY 發送讨論曆史給這個新房客. (在完成按照本文出席資訊廣播章節規定的發送房間出席資訊之前,該房間不能 MUST NOT 發送任何讨論曆史.) 是否這個曆史要被發送, 以及這個曆史裡面包含多少條消息, 将由聊天服務實作或特定的部署來決定.
例子 33. 讨論曆史的發送
<message from='[email protected]/firstwitch' to='[email protected]/broom' type='groupchat'> <body>Thrice the brinded cat hath mew'd.</body> <delay xmlns='urn:xmpp:delay' from='[email protected]/desktop' stamp='2002-10-13T23:58:37Z'/> </message> <message from='[email protected]/secondwitch' to='[email protected]/broom' type='groupchat'> <body>Thrice and once the hedge-pig whined.</body> <delay xmlns='urn:xmpp:delay' from='[email protected]/laptop' stamp='2002-10-13T23:58:43Z'/> </message> <message from='[email protected]/thirdwitch' to='[email protected]/broom' type='groupchat'> <body>Harpier cries 'Tis time, 'tis time.</body> <delay xmlns='urn:xmpp:delay' from='[email protected]/pda' stamp='2002-10-13T23:58:49Z'/> </message>
讨論曆史消息必須 MUST 标為Delayed Delivery11資訊,滿足'urn:xmpp:delay' 名字空間,以表明它們是被延遲發送的并且标明它們最初發出的時間. (注意: 'urn:xmpp:delay' 名字空間定義在 XEP-0203 裡面,取代了舊的定義在Legacy Delayed Delivery 12 裡的 'jabber:x:delay' 名字空間 ; XEP-0091狀态更改為已過時之前, 實作應該 SHOULD 包含兩種日期時間(datetime)格式.). 在非匿名房間裡,'from'屬性應該 SHOULD 是原始發送者的全JID, 但不能 MUST NOT 在半匿名房間裡(在那裡'from'屬性應該 SHOULD 設定為房間本身的JID). 服務應該 SHOULD 在進入該房間之後,發送任何即時("live")消息之前,發送完所有讨論曆史消息.
管理讨論曆史
使用者可能 MAY 希望管理進入房間時(由房間)提供的讨論曆史(可能因為使用者帶寬比較低或正在使用迷你用戶端). 他必須 MUST 在加入房間時發出的初始出席資訊節裡包含一個 <history/> 子元素. 這個元素有四個可用的屬性:
表8: 曆史管理屬性
屬性 資料類型 含義 maxchars int 限制曆史中的字元總數為"X" (這裡的字元數量是全部 XML 節的字元數, 不隻是它們的 XML 字元資料). maxstanzas int 限制曆史中的消息總數為"X". seconds int 僅發送最後 "X" 秒收到的消息. since dateTime 僅發送從指定日期時間 datetime 之後收到的消息 (這個datatime必須 MUST 符合XMPP Date and Time Profiles13 定義的DateTime 規則,). 服務必須 MUST 發送滿足以上條件組合的最小數量的消息, 還要顧及服務級别和房間級别的預設設定. 服務必須 MUST 隻發送完整的消息節(即, 它不能 MUST not 按特定字元數把曆史從字面上截斷, 但是必須 MUST 發送最大數量的完整節,這使得字元數小于或等于 'maxchars' 屬性的值). 如果用戶端不希望收到曆史, 它必須 MUST 把'maxchars' 屬性值設為"0" (zero).
以下例子展示如何使用這個協定.
例子 34. 使用者請求在曆史中限制消息數量
例子 35. 使用者請求最後三分鐘的曆史<presence from='[email protected]/pda' to='[email protected]/thirdwitch'> <x xmlns='http://jabber.org/protocol/muc'> <history maxstanzas='20'/> </x> </presence>
例子 36. 使用者請求從Unix時代到現在的所有曆史<presence from='[email protected]/pda' to='[email protected]/thirdwitch'> <x xmlns='http://jabber.org/protocol/muc'> <history seconds='180'/> </x> </presence>
<presence from='[email protected]/pda' to='[email protected]/thirdwitch'> <x xmlns='http://jabber.org/protocol/muc'> <history since='1970-01-01T00:00:00Z'/> </x> </presence>
服務絕對不應該 SHOULD NOT 傳回從Unix時代開始到現在的所有消息, 而應該 SHOULD 基于服務或房間的預設值傳回适當的有限數量的曆史給使用者.
例子 37. 使用者請求不發送曆史
<presence from='[email protected]/pda' to='[email protected]/thirdwitch'> <x xmlns='http://jabber.org/protocol/muc'> <history maxchars='0'/> </x> </presence>
退出一個房間
為了退出一個多使用者聊天房間, 一個房客發送一個類型為"unavailable"的出席資訊節給正在使用這個房間的 <[email protected]/nick> .
例子 38. 房客退出一個房間
<presence from='[email protected]/pda' to='[email protected]/thirdwitch' type='unavailable'/>
服務必須 MUST 接着從要離開的房客的房間JID發送"unavailable"類型的出席資訊節給這個要離開的房客的全JID們以及留在房間的房客們:
例子 39. 服務發送和離開的房客有關的出席資訊
<presence from='[email protected]/thirdwitch' to='[email protected]/pda' type='unavailable'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' role='none'/> <status code='110'/> </x> </presence> <presence from='[email protected]/thirdwitch' to='[email protected]/desktop' type='unavailable'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' role='none'/> </x> </presence> <presence from='[email protected]/thirdwitch' to='[email protected]/laptop' type='unavailable'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' role='none'/> </x> </presence>
由房間反射的類型為"unavailable"的出席資訊節必須 MUST 包含擴充的關于角色和崗位的出席資訊; 'role'屬性值應該 SHOULD 被設為 "none" 以表示這個人不再是一個房客了.
房客可以 MAY 在出席資訊節包含一個正常的 <status/> 資訊; 這使房客能在必要的情況下提供一個自定的退出消息:
例子 40. 自定的退出消息
<presence from='[email protected]/laptop' to='[email protected]/oldhag' type='unavailable'> <status>gone where the goblins go</status> </presence>
正常的出席資訊節生成規則定義在 XMPP IM 14, 是以如果使用者發送一個一般的不可用出席資訊節, 使用者的伺服器将廣播那個節到 <[email protected]/nick> ,而該使用者之前曾經發送過直接出席資訊給這個<[email protected]/nick>.
有可能一個使用者不能正常地通過直接發送不可用資訊給一個房間來退出該房間. 如果該使用者沒有發送不可用出席資訊就下線了, 使用者的伺服器負責代替該使用者發送不可用出席資訊 (依據RFC 3921). 如果該使用者的伺服器下線或該使用者的伺服器和該使用者連接配接的MUC服務失去連接配接(例如, 在聯邦通信), 這個MUC服務負責監視它收到的錯誤資訊節以确定該使用者是否下線. 如果該MUC服務确定該使用者已下線, 它必須 must 當成該使用者自己發送了不可用資訊一樣地處理這個使用者.
注意: 如果房間不是持久的并且該房客是最後一個退出的, 服務負責銷毀這個房間.
更改昵稱
多使用者聊天室的一個常用功能是一個房客能修改自己在房間裡的昵稱. 在 MUC 裡這需要發送一個更新出席資訊給房間, 具體來說是在相同的房間裡發送出席資訊給一個新的房間JID (變更的隻是這個房間JID的資源).
例子 41. 房客修改昵稱
<presence from='[email protected]/pda' to='[email protected]/oldhag'/>
服務接着發送兩個出席資訊節給每個房客的全JID(包括修改自己昵稱的房客本身), 一個是類型為"unavailable"的用于舊的昵稱另一個指明新昵稱可用了.
這個不可用出席資訊必須 MUST 在一個滿足'
例子 43. 服務拒絕昵稱修改,因為昵稱沖突
<presence from='[email protected]' to='[email protected]/pda' type='error'> <x xmlns='http://jabber.org/protocol/muc'/> <error type='cancel'> <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </presence>
無論如何, 如果現有房客的純JID <[email protected]> 和嘗試變更昵稱的房客的純JID相同, 那麼服務可以 MAY 允許昵稱變更. 詳見本文的昵稱沖突章節.
如果該使用者嘗試變更自己的昵稱但是房間昵稱被鎖定了("locked down"), 服務必須 MUST 拒絕這個昵稱變更請求并傳回一個"error"類型的出席資訊節,指明一個 <not-acceptable/> 錯誤條件:
例子 44. 服務拒絕昵稱變更,因為房間昵稱被鎖定
使用者應該 SHOULD 接着發現它的保留昵稱,如本文的 發現保留的房間昵稱章節所述.<presence from='[email protected]' to='[email protected]/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>
更改可用性狀态
在一個多使用者聊天系統裡例如IRC, 一個常用的修改某人房間昵稱的行為也意味着變更某人的可用性(例如, 變更某人的房間昵稱為"thirdwitch|away"). 在Jabber裡面, 可用性當然是通過出席資訊 (中 <show/> 和 <status/> 元素)的變更來通知的, 這能提供重要的上下文給聊天室. 一個房客通過發送更新的出席資訊給它自己的<[email protected]/nick>來改變他在房間内的可用性狀态.
例子 45. 房客變更可用性狀态
<presence from='[email protected]/laptop' to='[email protected]/oldhag'> <show>xa</show> <status>gone where the goblins go</status> </presence>
服務然後從該房客發送一個出席資訊節來修改他或她的出席資訊給每個房客的全JID, 包含擴充的出席資訊,包括這個房客的角色和全JID(給那些有權知道的人):
例子 46. 服務傳遞修改的出席資訊給所有房客
<presence from='[email protected]/secondwitch' to='[email protected]/desktop'> <show>xa</show> <status>gone where the goblins go</status> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='admin' jid='wicc[email protected]/laptop' role='moderator'/> </x> </presence> [ ... ]
邀請其他使用者進入一個房間
直接邀請
一個辦法是發送一個直接的邀請(而不是由房間本身來間接邀請),定義在Direct MUC Invitations15. 直接發送邀請有助于适應被邀請者那一邊的通信阻塞(對方可能拒絕和和不在好友名單中的實體通信).
間接邀請
邀請别的使用者到一個房間成為房客是很有用的. 為了做到這一點, 一個 MUC 用戶端必須 MUST 發送以下格式的 XML 給 <[email protected]> 本身 (原因(reason)是可選的 OPTIONAL 而消息(message)的類型必須 MUST 是顯式或隐式的"normal"類型):
例子 47. 房客通過房間發送一個邀請
<message from='[email protected]/desktop' to='[email protected]'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite to='[email protected]'> <reason> Hey Hecate, this is the place for all good witches! </reason> </invite> </x> </message>
<[email protected]> 本身必須 MUST 接着增加一個 'from' 位址到 <invite/> 元素,其值為邀請者的純JID, 全JID, 或房間JID,并發送邀請給 'to' 位址所指明的被邀請者(為了舊的用戶端,服務可以 MAY 包含一個消息主體"message body"解釋這個邀請或包含一個原因"reason"(子元素); 另外, 房間應該 SHOULD 增加 password 如果該房間是密碼保護的):
例子 48. 房間代表邀請者發送邀請給被邀請者
<message from='[email protected]' to='[email protected]'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite from='[email protected]/desktop'> <reason> Hey Hecate, this is the place for all good witches! </reason> </invite> <password>cauldronburn</password> </x> </message>
如果房間是僅限成員的, 服務可以 MAY 同時把這個被邀請者加入成員清單. (注意: 在僅限成員的房間裡邀請的權力應該 SHOULD 由房間管理者限定; 如果一個沒有權限的成員修改成員清單試圖邀請别的使用者, 服務應該 SHOULD 傳回一個 <forbidden/> 錯誤給該房客; 詳見本文的修改成員清單章節.)
如果邀請者提供了一個不存在的JID, 房間應該 SHOULD 傳回一個 <item-not-found/> 錯誤給邀請者.
被邀請者可以 MAY 選擇正式地拒絕 (反之則忽略) 邀請; 這是發送者希望看到的正式的通知. 為了拒絕這個邀請, 被邀請者必須 MUST 發送以下格式的消息給 <[email protected]> 本身:
例子 49. 被邀請者謝絕邀請
例子 50. 房間通知邀請者邀請被拒絕了<message from='[email protected]/broom' to='[email protected]'> <x xmlns='http://jabber.org/protocol/muc#user'> <decline to='[email protected]'> <reason> Sorry, I'm too busy right now. </reason> </decline> </x> </message>
可能(有人)想知道為什麼被邀請者不直接發送拒絕消息給通路者. 主要原因是特定的實作可能 MAY 選擇讓邀請基于房間JIDs而不是純JIDs (是以, 例如, 一個房客可能從一個房間邀請某人到另一個房間而不需要知道這個人的純JID). 因而服務必須 MUST 同時處理邀請和拒絕.<message from='[email protected]' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <decline from='[email protected]'> <reason> Sorry, I'm too busy right now. </reason> </decline> </x> </message>
把一對一聊天轉為多使用者會議
有時候人們需要把一個一對一的聊天轉成一個多使用者的會議. 以下例子展示了這個流程.
首先, 兩個使用者開始一個一對一聊天.
例子 51. 一個一對一聊天
現在第一個使用者決定加入第三個人到這個讨論, 是以她 (或, 更準确地說, 她的用戶端) 做以下事情:<message from='[email protected]/desktop' to='[email protected]/laptop' type='chat'> <thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread> <body>Thrice the brinded cat hath mew'd.</body> </message> <message from='[email protected]/laptop' to='[email protected]/desktop' type='chat'> <thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread> <body>Thrice and once the hedge-pig whined.</body> </message>
- 建立一個多使用者聊天室
- 可選地發送一對一聊天的曆史到房間
- 發送一個邀請給第二個人和第三個人, 包含一個 <continue/> 元素 (可選地包含一個 'thread' 屬性).
注意: 新房間應該 SHOULD 是非匿名的, 可以 MAY 是一個即時房間(定義于本文的建立即時房間章節), 也可以 MAY 有一個從服務接收的唯一房間名(定義于本文的請求唯一的房間名章節.
注意: 如果這個一對一的聊天消息包含了一個 <thread/> 元素, 這個建立房間的人應該 SHOULD 在曆史消息中包含這個 ThreadID, 在邀請中把這個 ThreadID 的值賦予 <continue/> 元素的 'thread' 屬性, 并把這 ThreadID 包含在任何新的消息中發送到房間. ThreadIDs 的使用是推薦的 RECOMMENDED ,因為它幫助提供一對一聊天和多使用者聊天的連續性.
例子 52. 繼續讨論 I: 使用者建立房間
例子 53. 繼續讨論 II: 所有者發送曆史到房間<presence from='[email protected]/desktop' to='[email protected]/firstwitch'> <x xmlns='http://jabber.org/protocol/muc'/> </presence> <presence from='[email protected]/firstwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='owner' role='moderator'/> <status code='110'/> </x> </presence>
<message from='[email protected]/desktop' to='[email protected]' type='groupchat'> <thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread> <body>Thrice the brinded cat hath mew'd.</body> <delay xmlns='urn:xmpp:delay' from='[email protected]/desktop' stamp='2004-09-29T01:54:37Z'/> </message> <message from='[email protected]/desktop' to='[email protected]' type='groupchat'> <thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread> <body>Thrice and once the hedge-pig whined.</body> <delay xmlns='urn:xmpp:delay' from='[email protected]/laptop' stamp='2004-09-29T01:55:21Z'/> </message>
注意: 使用 Delayed Delivery 協定使房間建立者能夠從他一對一聊天曆史指明每個消息的日期時間 datetime (通過 'stamp' 屬性), 以及每個消息的原始發送者的 JID (通過'from' 屬性). 房間建立者應該 SHOULD 在邀請額外的使用者到房間之前發送完整的一對一聊天曆史, 并且也應該 SHOULD 把第二個人加入該房間之前和第一個人在一對一聊天界面中出現的任何消息當成曆史來發送; 如果這個一對一曆史特别的大, 發送的用戶端可能希望在數秒内發送這個曆史而不是一次性發送所有曆史(以to 避免觸發頻率限制). 服務不應該 SHOULD NOT 在從房間所有者接收的曆史消息之前添加它自己的延遲元素"delay elements" (見本文的讨論曆史章節) .
例子 54. 繼續讨論 III: 所有者發送邀請(們), 包含 Continue 标志
<message from='[email protected]/desktop' to='[email protected]'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite to='[email protected]/laptop'> <reason>This coven needs both wiccarocks and hag66.</reason> <continue thread='e0ffe42b28561960c6b12b944a092794b9683a38'/> </invite> <invite to='[email protected]'> <reason>This coven needs both wiccarocks and hag66.</reason> <continue thread='e0ffe42b28561960c6b12b944a092794b9683a38'/> </invite> </x> </message>
注意: 當邀請者的用戶端一知道和它一對一聊天的那個人的全JID之後, 它就應該 SHOULD 在邀請中包含這個全JID (而不是純JID).
邀請被遞送到被邀請者:
例子 55. 邀請被遞送
<message from='[email protected]'> to='[email protected]/laptop'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite from='[email protected]'> <reason>This coven needs both wiccarocks and hag66.</reason> <continue thread='e0ffe42b28561960c6b12b944a092794b9683a38'/> </invite> </x> </message> <message from='[email protected]'> to='[email protected]'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite from='[email protected]'> <reason>This coven needs both wiccarocks and hag66.</reason> <continue thread='e0ffe42b28561960c6b12b944a092794b9683a38'/> </invite> </x> </message>
當用戶端被 <[email protected]/laptop> 用來接收邀請, 它應該 SHOULD 自動加入或提示使用者是否加入 (取決于使用者的選項配置) 并且随後無縫地把現有的一對一聊天視窗轉到一個多使用者會議的視窗:
例子 56. 被邀請者接受邀請, 加入房間, 并接收出席資訊和曆史
注意: 事實上,這些消息從 <[email protected]> 本身而不是 <[email protected]/nick> 發出,告訴這些接收的用戶端這些消息是優先的聊天曆史, 因為任何來自房客的消息的 'from' 位址應該等于發送者的房間JID.<presence from='[email protected]/laptop' to='[email protected]/secondwitch'> <x xmlns='http://jabber.org/protocol/muc'/> </presence> <presence from='[email protected]/firstwitch' to='[email protected]/laptop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='owner' role='moderator'/> </x> </presence> <presence from='[email protected]/secondwitch' to='[email protected]/laptop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' role='participant'/> </x> </presence> <message from='[email protected]' to='[email protected]/laptop' type='groupchat'> <thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread> <body>Thrice the brinded cat hath mew'd.</body> <delay xmlns='urn:xmpp:delay' from='[email protected]/desktop' stamp='2004-09-29T01:54:37Z'/> </message> <message from='[email protected]' to='[email protected]/laptop' type='groupchat'> <thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread> <body>Thrice and once the hedge-pig whined.</body> <delay xmlns='urn:xmpp:delay' from='[email protected]/laptop' stamp='2004-09-29T01:55:21Z'/> </message>
房客修改房間标題
如果房間配置允許, 一個房客可以 MAY 被允許修改一個房間的主題. 詳見本文的修改房間主題章節.發送私有消息
因為每個房客有一個唯一的房間JID, 一個房客可以 MAY 發送一個私有消息 "private message" 給標明的房客,即通過服務發送一個消息給那房客的房間JID. 這個消息類型應該 SHOULD 是 "chat" 并且不能 MUST NOT 是 "groupchat", 但是可以 MAY 不表明 (即, 一個正常"normal"消息). 這個權力應該 SHOULD 被任何房客允許 (甚至在一個被主持的房間裡的遊客).
例子 57. 房客發送私有消息
<message from='[email protected]/laptop' to='[email protected]/firstwitch' type='chat'> <body>I'll give thee a wind.</body> </message>
服務負責把'from'位址改為發送者的房間JID并遞送這個消息到預期的接收者的全JID.
例子 58. 接收者接收私有消息
<message from='[email protected]/secondwitch' to='[email protected]/desktop' type='chat'> <body>I'll give thee a wind.</body> </message>
如果發送者嘗試發送一個類型為 "groupchat" 的私有消息給特定的房客, 服務必須 MUST 拒絕遞送這個消息 (因為接收者的用戶端期望的房間内的消息類型為"groupchat") 并且傳回一個 <bad-request/> 錯誤給發送者:
例子 59. 房客嘗試發送類型為"Groupchat"的私有消息給特定的房客
<message from='[email protected]/laptop' to='[email protected]/firstwitch' type='groupchat'> <body>I'll give thee a wind.</body> </message> <message from='[email protected]' to='[email protected]/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>
如果發送者嘗試發送一個私有消息給一個不存在的房間JID, 服務必須 MUST 傳回一個 <item-not-found/> 錯誤給發送者.
如果發送者不是預期的接收者正在通路的那個房間的房客, 服務必須 MUST 傳回一個 <not-acceptable/> 錯誤給發送者.
發送消息給所有房客
房客發送一個消息給所有房間内的房客的方法,是發送一個類型為 "groupchat" 的消息到 <[email protected]> 本身 (服務可以 MAY 忽略或拒絕類型不是 "groupchat" 的消息). 在一個被主持的房間, 這個權力限于角色為與會者或更高的房客擁有.
例子 60. 房客發送一個消息給所有房客
<message from='[email protected]/pda' to='[email protected]' type='groupchat'> <body>Harpier cries: 'tis time, 'tis time.</body> </message>
如果發送者在這個房間有發言權 (在被主持的房間裡預設是這樣期望), 服務必須 MUST 修改發送者的 'from' 屬性成為房間JID并反射這個消息到每個房客的全JID.
例子 61. 服務反射消息給所有房客
如果發送者是個遊客 即, 在一個被主持的房間裡沒有發言權), 服務可以 MAY 傳回一個 <forbidden/> 錯誤給發送者并且不能 MUST NOT 反射這個消息給所有房客. 如果發送者不是該房間的房客, 服務應該 SHOULD 傳回一個 <not-acceptable/> 錯誤給發送者并且不應該 SHOULD NOT 反射這個消息給所有房客; 這個規則的唯一的例外是,一個實作可以 MAY 允許使用者們擁有特定的權限 (例如, 一個房間擁有者, 房間管理者, 或服務級别的管理者) 發送消息到這個房間,即使那些使用者不是房客.<message from='[email protected]/thirdwitch' to='[email protected]/desktop' type='groupchat'> <body>Harpier cries: 'tis time, 'tis time.</body> </message> <message from='[email protected]/thirdwitch' to='[email protected]/laptop' type='groupchat'> <body>Harpier cries: 'tis time, 'tis time.</body> </message> <message from='[email protected]/thirdwitch' to='[email protected]/pda' type='groupchat'> <body>Harpier cries: 'tis time, 'tis time.</body> </message>
注冊到房間
一個實作可以 MAY 允許一個無崗位的使用者(在一個被主持的房間裡, 通常是一個與會者) 注冊一個房間進而成為該房間的一個成員 (反之, 一個實作也可以 MAY 限制這個權力并且隻允許房間管理者添加新的成員). 特别是, 不在成員清單的人是無法加入一個僅限會員的房間的, 是以為了加入這樣一個房間,實體需要申請會籍.
如果允許, 這個功能應該 SHOULD 這樣被實作。讓使用者使用 'jabber:iq:register' 名字空間帶内注冊16提出注冊申請給房間,:
例子 62. 使用者提出注冊申請
<iq from='[email protected]/pda' id='reg1' to='[email protected]' type='get'> <query xmlns='jabber:iq:register'/> </iq>
如果使用者提出的注冊申請不被允許注冊該房間 (例如, 因為那個權限被限制了), 該房間必須 MUST 傳回一個 <not-allowed/> 錯誤給該使用者. 如果該使用者已經注冊過了, 房間必須 MUST 傳回一個類型為"result"的IQ節并包含一個空的<register/>元素(定義于XEP-0077). 如果該房間不存在, 服務必須 MUST 傳回一個 <item-not-found/> 錯誤.
否則, 房間必須 MUST 接着傳回一個資料表單"Data Form"給該使用者 (定義于資料表單17). 注冊需要的資訊可以 MAY 根據實作和部署的不同而不同并且沒有完全定義在本文中 (例如, 本文根據 '字段标準化章節裡描述的得到補充,). 以下是一個典型的例子:
例子 63. 服務傳回系統資料庫單
<iq from='[email protected]' id='reg1' to='[email protected]/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>
使用者應該 SHOULD 接着送出這個表單:
例子 64. 使用者送出系統資料庫單
<iq from='[email protected]/pda' id='reg2' to='[email protected]' 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>[email protected]</value> </field> <field var='muc#register_faqentry'> <value>Just another witch.</value> </field> </x> </query> </iq>
如果期望的房間昵稱已經被那個房間保留, 房間必須 MUST 傳回一個 <conflict/> 錯誤給該使用者:
例子 65. 房間傳回沖突錯誤給使用者
<iq from='[email protected]' id='reg2' to='[email protected]/pda' type='error'> <error type='cancel'> <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
如果該房間或服務不支援注冊, 它必須 MUST 傳回一個 <service-unavailable/> 錯誤給使用者:
例子 66. 房間傳回服務不可用錯誤給使用者
<iq from='[email protected]' id='reg2' to='[email protected]/pda' type='error'> <error type='cancel'> <service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
如果使用者沒有送出合法的資料表格, 房間必須 MUST 傳回一個 <bad-request/> 錯誤給使用者:
例子 67. 房間傳回"服務錯誤的請求"錯誤給使用者
<iq from='[email protected]' id='reg2' to='[email protected]/pda' type='error'> <error type='modify'> <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
否則, 該房間必須 MUST 通知使用者注冊請求被成功地接收到了:
例子 68. 房間通知使用者注冊請求已經被處理了
<iq from='[email protected]' id='reg2' to='[email protected]/pda' type='result'/>
使用者送出表單之後, 服務可以 MAY 向一個房間 管理者/所有者 請求準許該申請 (參見本文的準許注冊申請章節) 或也可以 MAY 立刻把該使用者的崗位從"none"變更為"member"來添加此使用者到成員清單. 如果服務變更了該使用者的崗位并且該使用者在房間裡, 它必須 MUST 從這個使用者發送更新的出席資訊給所有房客, 聲明崗位的變更,這個更新的出席資訊應包含一個滿足 '
例子 69. 服務發送成員變更通知給所有房客
如果一個使用者已經注冊到一個房間, 該房間可以 MAY 選擇限制這個使用者在那個房間僅能使用已注冊的昵稱. 如果它這樣做, 當使用者嘗試以不同于該使用者之前已注冊的房間昵稱來加入該房間 (這使房間鎖定"lock down"房間昵稱以保證房客身份的一緻性)的時候,它應該 SHOULD 傳回一個 <not-acceptable/> 錯誤給該使用者.<presence from='[email protected]/thirdwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' jid='[email protected]/pda' role='participant'/> </x> </presence> [ ... ]
擷取成員清單
根據房間配置如果允許的話, 一個房客可以 MAY 被允許接收房間成員的清單. 詳見本文的修改成員清單章節.發現保留的房間昵稱
一個使用者可以 MAY 有一個保留的房間昵稱, 例如通過顯式的房間注冊, 資料庫內建, 或昵稱鎖定 "lockdown". 使用者應該 SHOULD 在嘗試進入該房間之前發現自己的保留昵稱. 這可以通過發送一個發現服務資訊請求并指定一個服務發現節點"x-roomuser-item"給房間JID來做到.
例子 70. 使用者請求保留的昵稱
<iq from='[email protected]/pda' id='getnick1' to='[email protected]' type='get'> <query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'/> </iq>
對一個多使用者聊天服務來說,對上述的服務發現節點的支援是可選的 OPTIONAL . 如果房間或服務不支援上述的服務發現節點, 它必須 MUST 傳回一個 <feature-not-implemented/> 錯誤給使用者. 如果它支援這個特性并且該使用者有一個已注冊的昵稱, 它必須 MUST 傳回這個昵稱給這個使用者,方法是發送一個服務發現的<identity/>元素,其'name'屬性值為這個昵稱 (此處 category/type 應該 SHOULD 是 "conference/text"):
例子 71. 房間傳回昵稱
<iq from='[email protected]' id='getnick1' to='[email protected]/pda' type='result'> <query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'> <identity category='conference' name='thirdwitch' type='text'/> </query> </iq>
如果該使用者沒有已注冊的昵稱, 房間必須 MUST 傳回一個空的服務發現 <query/> 元素 (根據 XEP-0030).
即使一個使用者已經注冊了一個房間昵稱, 服務應該 SHOULD 允許該使用者在加入該房間時指定一個不同的昵稱 (例如, 為了從不同的用戶端資源加入), 盡管該服務可以 MAY 選擇通過一個 <not-acceptable/> 錯誤來鎖定 "lock down" 昵稱并拒絕該使用者 . 如果該使用者的用戶端在加入該房間之後發送上述請求,服務不能 MUST NOT 傳回一個錯誤給該使用者, 而應該 SHOULD 傳回上文所述.
如果另一個使用者嘗試以第一個使用者保留的房間昵稱來加入房間, 服務必須 MUST 拒絕第二個使用者并傳回一個前文所述的 <conflict/> 錯誤.
申請發言權
在一個被主持的房間裡遊客是不能發言的 (即, 發送一個消息給所有房客). 為了申請發言權, 一個遊客應該 SHOULD 發送包含一個資料表格的 <message/> 節給房間本身, 這個資料表格僅僅是一個 'muc#role' 字段,值為 "participant".
例子 72. 房客申請發言權
服務接着應該 SHOULD 轉發這個請求給房間主持人(們) ,定義于本文的準許發言權申請.<message from='[email protected]/pda' to='[email protected]'> <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>
主持人用例
一個主持人有權在房間裡執行特定的動作 (例如, 變更某些房客的角色) 但無權變更崗位的持久資訊 (它隻能被管理者或所有者) 或定義關于這個房間的資訊. 具體哪些動作可由主持人執行,取決于配置. 無論如何, 對于 MUC 架構來說, 主持人被規定有權執行以下動作:- 在一個半匿名的房間裡發現一個房客的全JID(如上文所述預設會發生)
- 修改主題
- 從該房間踢出一個與會者或遊客
- 在一個被主持的房間裡授予或撤銷發言權
- 在一個被主持的房間裡修改擁有發言權的房客清單
這些特性将通過一個基于 <iq/> 元素的 請求/應答 交換來實作,這個IQ元素包含一個滿足 '修改房間主題
多使用者聊天室的一個常用特性是變更房間主題的能力. 預設地, 一個房間裡隻有角色為主持人 "moderator" 的使用者應該 SHOULD 被允許變更主題 (盡管這應該 SHOULD 是可配置的, 結果是如果需要的話,僅僅與會者或甚至遊客都被允許修改主題). 主題變更是通過發送一個類型為 "groupchat" 的消息給 <[email protected]>來實作的, 在這裡 <message/> 必須 MUST 包含一個 <subject/> 元素以指定新的主題,但不應該 SHOULD NOT 包含其他元素 (例如, 不應該有 <body/> 元素或 <thread/> 元素).
例子 73. 主持人變更主題
<message from='[email protected]/laptop' to='[email protected]' type='groupchat'> <subject>Fire Burn and Cauldron Bubble!</subject> </message>
如果一個 MUC 服務接收到這樣一個消息, 它必須 MUST 以發送這個變更主題消息的那個使用者的房間JID作為'from'位址來反射這個消息給所有其他房客:
例子 74. 服務通知所有房客主題變更
<message from='[email protected]/secondwitch' to='[email protected]/desktop' type='groupchat'> <subject>Fire Burn and Cauldron Bubble!</subject> </message> [ ... ]
另外, 當一個新的房客加入房間時,該房間應該 SHOULD 在被發送的讨論曆史中包含最後的主題變更.
一個接收到這類資訊的 MUC 用戶端可以 MAY 選擇顯示一個房間内的消息, 如下:
例子 75. 用戶端顯式房間主題變更消息
* secondwitch has changed the subject to: Fire Burn and Cauldron Bubble!
如果一些沒有适當權限的人嘗試變更房間主題, 服務必須 MUST 傳回一個 "error" 類型的消息指明一個 <forbidden/> 錯誤條件:
例子 76. 服務傳回未被授權變更主題的錯誤
<message from='[email protected]' to='[email protected]/pda' type='error'> <subject>Fire Burn and Cauldron Bubble!</subject> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </message>
為了移除現有的主題而不是提供一個新主題 (即, 設定主題為空), 用戶端應該發送一個空的 <subject/> 元素 (即, "<subject/>" 或 "<subject></subject>").
例子 77. 主持人設定空的主題
<message from='[email protected]/laptop' to='[email protected]' type='groupchat'> <subject></subject> </message>
踢出房客
主持人有權從一個房間踢出特定種類的房客 (哪些房客是可被踢的 "kickable" 取決于服務規定, 房間配置, 以及主持人的崗位 -- 見下文). 踢人通常基于房客的房間昵稱來執行 (盡管可以 MAY 基于全JID) 并且完全是通過把與會者或遊客的角色設為 "none" 來實作的.
例子 78. 主持人踢出房客
<iq from='[email protected]/pda' id='kick1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='pistol' role='none'> <reason>Avaunt, you cullion!</reason> </item> </query> </iq>
服務必須 MUST 移除被踢的使用者,通過發送一個類型為 "unavailable" 的出席資訊節給每個被踢的房客, 這個出席資訊應在其擴充出席資訊中包含狀态碼 307 , 或(可選地)包含 reason 子元素(如果提供了) 以及踢人的執行者的純JID.
例子 79. 服務移除被踢的房客
<presence from='[email protected]/pistol' to='[email protected]/harfleur' type='unavailable'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='none' role='none'> <actor jid='[email protected]'/> <reason>Avaunt, you cullion!</reason> </item> <status code='307'/> </x> </presence>
包含狀态碼可使用戶端能夠送出他們自己的通知消息 (例如, 适當的使用者位置的資訊). 可選的包含原因 reason 元素以及執行者 actor 使得被踢的使用者能了解為什麼他或她被踢了, 以及被踢的使用者可以找誰去理論.18
移除被踢的房客(們)之後, 服務必須 MUST 接着通知主持人成功了:
例子 80. 服務通知主持人成功了
<iq from='[email protected]' id='kick1' to='[email protected]/pda' type='result'/>
通知主持人之後, 服務必須 MUST 接着通知剩餘的房客那個被踢的房客已經不在房間裡了,即從被踢者的房間昵稱(<[email protected]/nick>)發送 "unavailable" 類型的出席資訊節給所有剩餘的房客 (就像房客自願退出房間時所做的一樣), 包含狀态碼 status 以及可選的原因 reason 和執行者 actor.
例子 81. 服務通知剩餘的房客
<presence from='[email protected]/pistol' to='[email protected]/cell' type='unavailable'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='none' role='none'/> <status code='307'/> </x> </presence> [ ... ]
一個使用者不能被比自己崗位低的主持人踢出. 是以, 如果一個身為與會者的主持人嘗試踢出一個管理者,或一個身為與會者的主持人或管理者嘗試踢出一個所有者, 服務必須 MUST 拒絕這個請求并傳回一個 <not-allowed/> 錯誤給發送者:
例子 82. 服務對于嘗試踢出更高崗位的使用者傳回錯誤
如果一個主持人嘗試踢出他自己, 服務可以 MAY 拒絕這個請求并傳回一個 <conflict/> 錯誤給發送者. (盡管這個踢出自己的行為可能看起來怪異, 它在 IRC 裡很常見,用于在房間裡為某人的行為道歉.)<iq from='[email protected]' id='kicktest' to='[email protected]/laptop' type='error'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='firstwitch' role='none'> <reason>Be gone!</reason> </item> </query> <error type='cancel'> <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
授予遊客發言權
在一個被主持的房間裡, 主持人可能希望管理房間内誰有水沒有發言權 "voice" (即, 發送消息給所有房客的能力). 發言權的授予是基于遊客的房間昵稱來的, 服務将從内部把這個房間昵稱轉成遊客的全JID. 主持人通過把遊客的角色變更為與會者 "participant"來給一個遊客授予權限.
例子 83. 主持人授予權限給一個遊客
<iq from='[email protected]/desktop' id='voice1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='thirdwitch' role='participant'/> </query> </iq>
<reason/> 元素是可選的 OPTIONAL:
例子 84. 主持人授予權限給一個遊客(包含一個原因 Reason)
<iq from='[email protected]/desktop' id='voice1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='thirdwitch' role='participant'> <reason>A worthy witch indeed!</reason> </item> </query> </iq>
服務必須 MUST 接着通知主持人成功了:
例子 85. 服務通知主持人成功了
<iq from='[email protected]' id='voice1' to='[email protected]/desktop' type='result'/>
服務必須 MUST 接着以這個人的<[email protected]/nick>發送更新的出席資訊給所有房客, 在這個出席資訊裡包含了一個滿足'
例子 86. 服務發送發言權通知給所有房客
<presence from='[email protected]/thirdwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' nick='thirdwitch' role='participant'> <reason>A worthy witch indeed!</reason> </item> </x> </presence> [ ... ]
撤銷與會者發言權
在一個被主持的房間裡, 主持人可能希望撤銷一個與會者發言的權力,主持人通過把與會者的角色變更為遊客 "visitor"來撤銷一個遊客的發言權:
例子 87. 主持人撤銷一個與會者的發言權
<iq from='[email protected]/desktop' id='voice2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='thirdwitch' role='visitor'/> </query> </iq>
<reason/> 元素是可選的 OPTIONAL:
例子 88. 主持人撤銷一個與會者的發言權(包含一個原因Reason)
<iq from='[email protected]/desktop' id='voice2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='thirdwitch' role='visitor'> <reason>Not so worthy after all!</reason> </item> </query> </iq>
服務必須 MUST 接着通知主持人成功了:
例子 89. 服務通知主持人成功了
<iq from='[email protected]' id='voice2' to='[email protected]/desktop' type='result'/>
服務必須 MUST 接着以這個人的<[email protected]/nick>發送更新的出席資訊給所有房客, 在這個出席資訊裡包含了一個滿足'
例子 90. 服務通知失去發言權
<presence from='[email protected]/thirdwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' jid='[email protected]/pda' role='visitor'/> </x> </presence> [ ... ]
一個主持人不能 MUST NOT 從一個崗位等于或高于主持人崗位的使用者撤銷發言權. 另外, 服務不能 MUST NOT 允許一個管理者或所有者的發言權被任何人撤銷. 如果一個主持人嘗試撤銷這些人的發言權, 服務必須 MUST 拒絕這個請求并傳回一個 <not-allowed/> 的錯誤給發送者(通過以下的違規條目):
例子 91. 服務對于嘗試從管理者,所有者或更高崗位的使用者撤銷權限傳回錯誤
<iq from='[email protected]' id='voicetest' to='[email protected]/desktop' type='error'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='secondwitch' role='visitor'/> </query> <error type='cancel'> <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
修改發言權清單
在一個被主持的房間裡主持人可能希望管理發言權清單. 為了達到這個目的, 主持人首先查詢房間所有角色為'participant'的房客清單來請求發言權清單.
例子 92. 主持人請求發言權清單
<iq from='[email protected]/globe' id='voice3' to='[email protected]' type='get'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item role='participant'/> </query> </iq>
服務必須 MUST 接着傳回發言權清單給主持人; 每個條目必須 MUST 包含 'nick' 和 'role' 屬性并且應該 SHOULD 包含 'affiliation' 和 'jid' 屬性:
例子 93. 服務發送發言權清單給主持人
<iq from='[email protected]' id='voice3' to='[email protected]/globe' type='result'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='none' jid='[email protected]/castle' nick='Polo' role='participant'/> <item affiliation='none' jid='[email protected]/castle' nick='horotoro' role='participant'/> <item affiliation='member' jid='[email protected]/broom' nick='Hecate' role='participant'/> </query> </iq>
主持人可以 MAY 接着修改發言權清單. 為了達到這個目的, 主持人必須 MUST 發送變更了的條目 (即, 隻有 "delta") 給服務; 每個條目必須 MUST 包含 'nick' 屬性和 'role' 屬性 (通常設定值為 "participant" 或 "visitor") 但是不應該 SHOULD NOT 包含 'jid' 屬性并且不能 MUST NOT 包含 'affiliation' 屬性 (它用于管理如所有者那樣的崗位而不是與會者那樣的角色):
例子 94. 主持人發送修改的發言權清單給服務
<iq from='[email protected]/globe' id='voice4' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='Hecate' role='visitor'/> <item nick='rosencrantz' role='participant'> <reason>A worthy fellow.</reason> </item> <item nick='guildenstern' role='participant'> <reason>A worthy fellow.</reason> </item> </query> </iq>
服務必須 MUST 接着通知主持人成功了:
例子 95. 服務通知主持人成功了
<iq from='[email protected]' id='voice1' to='[email protected]/globe' type='result'/>
服務必須 MUST 接着為任何受影響的人發送更新的出席資訊給所有房客, 如前文的用例所述,發送适當的擴充出席資訊來指明發言權的變更.
大家知道, 不能撤銷一個房間所有者或管理者的發言權, 也不能撤銷比送出請求的主持人崗位高的使用者的發言權. 如果一個房間管理者嘗試通過修改發言權清單來撤銷這類使用者的發言權, 服務必須 MUST 拒絕請求并傳回一個 <not-allowed/> 錯誤給發送者:
例子 96. 服務傳回錯誤給試圖撤銷管理者,所有者或比發送者崗位更高的使用者的發言權的發送者
<iq from='[email protected]' id='voicetest' to='[email protected]/globe' type='error'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item jid='[email protected]' nick='Hecate' role='visitor'/> </query> <error type='cancel'> <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
準許發言權申請
在本文的申請發言權章節提到, 當服務接受到一個來自房客的請求,它應該 SHOULD 轉發那個請求給房間的主持人(們). 為了達到這個目的, 服務應該 SHOULD 發送一個 <message/> 節給房間主持人(們), 這裡 <message/> 節包含一個資料表格data form來準許或拒絕這個申請, 如下所示.
'例子 97. 申請準許發言權表格
<message from='[email protected]' id='approve' to='[email protected]/pda'> <x xmlns='jabber:x:data' type='form'> <title>Voice request</title> <instructions> To approve this request for voice, select the "Grant voice to this person?" checkbox and click OK. To skip this request, click the cancel button. </instructions> <field var='FORM_TYPE' type='hidden'> <value>http://jabber.org/protocol/muc#request</value> </field> <field var='muc#role' type='text-single' label='Requested role'> <value>participant</value> </field> <field var='muc#jid' type='text-single' label='User ID'> <value>[email protected]/pda</value> </field> <field var='muc#roomnick' type='text-single' label='Room Nickname'> <value>thirdwitch</value> </field> <field var='muc#request_allow' type='boolean' label='Grant voice to this person?'> <value>false</value> </field> </x> </message>
為了準許這個申請, 主持人将送出此表格:
例子 98. 準許發言權申請
如果主持人準許了這個發言權申請, 服務将授予發言權給該房客并發送一個出席資訊更新,如本文授予遊客發言權章節所述.<message from='[email protected]/pda' id='approve' to='[email protected]'> <x xmlns='jabber:x:data' type='submit'> <field var='FORM_TYPE' type='hidden'> <value>http://jabber.org/protocol/muc#request</value> </field> <field var='muc#role'> <value>participant</value> </field> <field var='muc#jid'> <value>[email protected]/pda</value> </field> <field var='muc#roomnick'> <value>thirdwitch</value> </field> <field var='muc#request_allow'> <value>true</value> </field> </x> </message>
管理者用例
一個房間管理者有權修改使用者崗位的持久資訊 (例如, 通過禁止使用者) 并授予和撤銷主持人權限, 但是無權修改房間的定義, 那是唯一屬于房間所有者(們)的權力. 具體哪些動作是管理者可以執行的則取決于配置. 無論如何, 在 MUC 架構中的用途, 規定房間管理者最少擁有執行以下操作的權限:- 在房間裡禁止一個使用者
- 在房間裡修改黑名單
- 授予或撤銷成員資格
- 修改成員清單
- 授予或撤銷主持人權力
- 修改主持人清單
這些特性将由一個 請求/應答 request/response 式的交換來實作,使用 <iq/> 元素,包含滿足 '禁止使用者
在房間裡一個管理者或所有者可以禁止一個或多個使用者. 這動作必須 MUST 基于房客的純JID來執行. 為了禁止一個使用者, 管理者必須 MUST 把該使用者的崗位改為"outcast".
例子 99. 管理者禁止使用者
<iq from='[email protected]/throne' id='ban1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='outcast' jid='[email protected]'/> </query> </iq>
<reason/> 元素是可選的 OPTIONAL.
例子 100. 管理者禁止使用者(包含一個原因 Reason)
<iq from='[email protected]/throne' id='ban1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='outcast' jid='[email protected]'> <reason>Treason</reason> </item> </query> </iq>
服務必須 MUST 把那個純JID添加到黑名單, 應該 SHOULD 把被排斥者的昵稱從已注冊的昵稱清單中移除, 并且必須 MUST 通知管理者或所有者成功了:
例子 101. 服務通知管理者或所有者成功了
<iq from='[email protected]' id='ban1' to='[email protected]/throne' type='result'/>
服務必須 MUST 也移除任何還在房間中的被禁止的使用者,通過發送 "unavailable" 類型的出席資訊節給每個被禁止的房客, 在擴充的出席資訊中包含一個狀态碼 301 , 可選地帶上 reason (如果服務提供的話) 以及執行這個禁止動作的使用者的純JID.
例子 102. 服務移除被禁止的使用者
<presence from='[email protected]/cambridge' to='[email protected]/stabber' type='unavailable'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='outcast' role='none'> <actor jid='[email protected]'/> <reason>Treason</reason> </item> <status code='301'/> </x> </presence>
包含狀态碼可使用戶端能夠送出他們自己的通知消息 (例如, 适當的使用者位置的資訊). 可選的包含原因 reason 元素以及執行者 actor 使得被踢的使用者能了解為什麼他或她被踢了, 以及被踢的使用者可以找誰去理論.
通知主持人之後, 服務必須 MUST 接着通知剩餘的房客那個被禁止的房客已經不在房間裡了,即從被禁止使用者發送 "unavailable" 類型的出席資訊節給所有剩餘的房客 (就像房客自願退出房間時所做的一樣), 包含狀态碼 status 以及可選的原因 reason 和執行者 actor.
例子 103. 服務通知剩餘的房客
<presence type='unavailable' from='[email protected]/cambridge' to='[email protected]/pda'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='outcast' jid='[email protected]/stabber' role='none'/> <status code='301'/> </x> </presence> [ ... ]
就像踢出房客一樣, 一個使用者不能被自己崗位低的管理者禁止. 是以, 如果一個管理者嘗試禁止一個所有者, 服務必須 MUST 拒絕這個請求并傳回一個 <not-allowed/> 錯誤給發送者:
例子 104. 服務對嘗試禁止更高崗位使用者傳回錯誤
如果一個管理者或所有者嘗試禁止他自己, 服務必須 MUST 拒絕這個請求并傳回一個 <conflict/> 錯誤給發送者. (注意:這和踢出自己時推薦的服務行為不同, 踢自己的行為服務是允許的.)<iq from='[email protected]/throne' id='ban1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='outcast' jid='[email protected]'> <reason>Treason</reason> </item> </query> <error type='cancel'> <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
修改黑名單
房間管理者可能希望修改黑名單. 注意: 黑名單總是基于使用者的純JID. 要修改黑名單, 管理者首先向房間查詢所有崗位為'outcast'的使用者以得到黑名單.
例子 105. 管理者請求黑名單
<iq from='[email protected]/throne' id='ban2' to='[email protected]' type='get'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='outcast'/> </query> </iq>
服務必須 MUST 接着傳回黑名單給管理者; 每個條目必須 MUST 包含 'affiliation' 和 'jid' 屬性但不應該 SHOULD NOT 包含 'nick' 和 'role' 屬性:
例子 106. 服務發送黑名單給管理者
<iq from='[email protected]' id='ban2' to='[email protected]/throne' type='result'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='outcast' jid='[email protected]'> <reason>Treason</reason> </item> </query> </iq>
管理者可以 MAY 接着修改黑名單. 為此, 管理者必須 MUST 發送變更的條目 (即, 僅是 "delta") 給服務; 每個條目必須 MUST 包含 'affiliation' 屬性 (通常設為"outcast"來禁止或"none"來取消禁止) 和 'jid' 屬性,但不應該 SHOULD NOT 包含 'nick' 屬性,不能 MUST NOT 包含 'role' 屬性 (它用來管理角色,例如與會者,而不是被排斥者崗位); 另外, reason 和 actor 元素是可選的 OPTIONAL:
例子 107. 管理者發送修改的黑名單給服務
<iq from='[email protected]/throne' id='ban3' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='outcast' jid='[email protected]'> <reason>Treason</reason> </item> <item affiliation='outcast'> jid='[email protected]'> <reason>Treason</reason> </item> <item affiliation='outcast' jid='[email protected]'> <reason>Treason</reason> </item> </query> </iq>
更新黑名單之後, 服務必須 MUST 通知管理者成功了:
例子 108. 服務通知管理者成功了
<iq from='[email protected]' id='ban3' to='[email protected]/throne' type='result'/>
服務必須 MUST 接着移除受影響的房客 (如果他們在房間裡) 并從他們發送更新的出席資訊 (包含适當的狀态碼) 給所有剩餘的房客,如 "禁止使用者" 用例所述. (服務應該 SHOULD 也移除從保留房間昵稱清單中移除每個被禁止的使用者的保留昵稱, 如果必要.)
當一個實體被一個房間禁止, 實作應該 SHOULD 按以下順序比對 JIDs (這些比對規則和RFC 3921中定義的隐私清單的比對規則是相同的):
- <[email protected]/resource> (僅比對特定的資源)
- <[email protected]> (比對任何資源)
- <domain/resource> (僅比對特定資源)
- <domain> (比對域名本身, 就像任何 [email protected] 或 domain/resource 一樣)
授予成員資格
管理者可以授予成員資格給一個使用者; 方法是把使用者的崗位改為 "member" (通常如果使用者在房間裡,基于昵稱,如果使用者不在房間裡,則基于純JID; 在這兩種情況下如果提供了昵稱, 那麼這個昵稱就是使用者在這個房間的預設昵稱,如果實作支援那個功能的話):
例子 109. 管理者授予成員資格
<iq from='[email protected]/desktop' id='member1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='member' jid='[email protected]'/> </query> </iq>
<reason/> 元素是可選的 OPTIONAL.
例子 110. 管理者授予成員資格(包含一個原因Reason)
<iq from='[email protected]/desktop' id='member1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='member' jid='[email protected]'> <reason>A worthy witch indeed!</reason> </item> </query> </iq>
服務必須 MUST 把這個使用者添加到成員清單,然後通知管理者成功了:
例子 111. 服務通知管理者成功了
<iq from='[email protected]' id='member1' to='[email protected]shakespeare.lit/desktop' type='result'/>
如果該使用者在房間裡, 服務必須 MUST 接着以這個使用者的名義發送更新的出席資訊給所有房客, 在這個出席資訊裡包含了一個滿足'
例子 112. 服務發送成員資格通知給所有房客
<presence from='[email protected]/thirdwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' jid='[email protected]/pda' role='participant'/> </x> </presence> [ ... ]
如果該使用者不在房間裡, 服務可以 MAY 從房間本身發送一個消息給房間的房客們, 在這個消息裡包含了一個滿足'
例子 113. 服務發送成員資格通知給所有房客
<message from='chat.shakespeare.lit' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' jid='[email protected]' role='none'/> </x> </message> [ ... ]
撤銷成員資格
一個管理者可能想撤銷一個使用者的成員資格; 通過把該使用者的崗位改為"none":
例子 114. 管理者撤銷成員資格
<iq from='[email protected]/desktop' id='member2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='none' jid='[email protected]'/> </query> </iq>
<reason/> 元素是可選的 OPTIONAL.
例子 115. 管理者撤銷成員資格(包含一個原因Reason)
<iq from='[email protected]/desktop' id='member2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='none' jid='[email protected]'> <reason>Not so worthy after all!</reason> </item> </query> </iq>
服務必須 MUST 從成員清單中移除該使用者然後通知主持人成功了:
例子 116. 服務通知主持人成功了
<iq from='[email protected]' id='member2' to='[email protected]/desktop' type='result'/>
服務必須 MUST 接着以這個使用者的名義發送更新的出席資訊節給所有房客, 在這個出席資訊裡包含了一個滿足'
例子 117. 服務通知失去成員資格
<presence from='[email protected]/thirdwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='none' jid='[email protected]/pda' role='participant'/> </x> </presence> [ ... ]
如果房間是僅限會員的, 服務必須 MUST 從房間移除這個使用者, 包含一個狀态碼 321 來指明使用者被移除是因為崗位變更, 并通知所有剩餘的房客:
例子 118. 服務移除非會員
<presence from='[email protected]/thirdwitch' to='[email protected]/desktop'> type='unavailable'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='none' role='none'> <actor jid='[email protected]'/> </item> <status code='321'/> </x> </presence> <presence from='[email protected]/thirdwitch' to='[email protected]/desktop'> type='unavailable'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='none' role='none'/> <status code='321'/> </x> </presence> [ ... ]
修改成員清單
在一個僅限會員的房間的上下文裡, 成員清單本質上是一個允許人們加入房間的白名單 "whitelist". 任何不是成員的人等于是被禁止加入該房間, 即使他們的崗位不是"outcast".
在一個開放房間的上下文裡, 成員清單隻是一個注冊了這個房間的使用者 (純JID和保留的昵稱) 的清單. 這些使用者可以出現在一個房間名冊裡, 有他們自己的保留房間昵稱, 在搜尋結果或類似FAQ裡被傳回給(查詢者).
推薦 RECOMMENDED 在僅限會員的房間裡隻讓房間管理者擁有修改成員清單的權力. 為此, 管理者首先請求成員清單,通過查詢房間裡所有崗位為"member"的使用者來實作:
例子 119. 管理者請求成員清單
<iq from='[email protected]/desktop' id='member3' to='[email protected]' type='get'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='member'/> </query> </iq>
注意: 在一個僅限會員的房間裡,服務也應該 SHOULD 傳回成員清單給任何房客; 即, 當一個房間的成員請求房間清單時,它不應該 SHOULD NOT 生成一個 <forbidden/> 錯誤. 這個功能可幫助用戶端展示所有現有的成員,即使他們中的一些人不在房間裡, 例如. 幫助成員确定是否另一個使用者應該被邀請. 服務也應該 SHOULD 允許任何成員接收成員清單,即使還不是一個房客(譯注:即未進入房間).
服務必須 MUST 接着傳回全部的成員清單給管理者,遵循 '
例子 121. 管理者發送修改的成員清單給服務
<iq from='[email protected]/desktop' id='member4' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='none' jid='[email protected]'/> <item affiliation='member' jid='[email protected]'/> </query> </iq>
服務必須 MUST 修改成員清單然後通知主持人成功了:
例子 122. 服務通知主持人成功了
<iq from='[email protected]' id='member4' to='[email protected]/desktop' type='result'/>
服務必須 MUST 變更任何受影響的使用者的崗位. 如果該使用者已經從成員清單中移除了, 服務必須 MUST 把該使用者的崗位從 "member" 變更為 "none". 如果該使用者已經被加入到成員清單, 服務必須 MUST 把該使用者的崗位改成 "member".
如果一個被移除的成員正在一個僅限會員的房間, 服務應該 SHOULD 踢出這個房客,如前文所述,通過把被移除的成員的角色改成 "none" 并發送适當的出席資訊給這個被移除的成員來實作. 無論是否被移除的那個使用者在或不在一個僅限會員的房間裡, 服務必須 MUST 随後拒絕這個使用者的進入.
對所有的房間類型來說, 服務必須 MUST 以這個使用者的名義發送更新的出席資訊給所有的房客, 這個出席資訊擁有一個滿足 '
例子 123. 服務發送失去成員資格的通知給所有房客
<presence from='[email protected]/thirdwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='none' jid='[email protected]/pda' role='participant'/> </x> </presence> [ ... ]
另外, 服務必須 SHOULD 發送一個邀請給任何已加入到僅限會員的房間裡的成員名單中的使用者,如果該使用者目前在該房間還沒有崗位, 例如作為一個管理者或所有者(這類使用者在定義時不在房間裡; 同時要注意這個例子裡使用了一個密碼password而不是原因reason -- 這兩個子元素都是可選的 OPTIONAL):
例子 124. 房間發送邀請給新成員
<message from='[email protected]' to='[email protected]'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite from='[email protected]'/> <password>cauldronburn</password> </x> </message>
因為隻有管理者們和所有者們應該 SHOULD 被允許修改成員清單, 一個實作可以 MAY 提供一個配置選項,在僅限會員的房間裡開放邀請權限給任何成員. 這種情況下, 任何被發送的邀請都應該 SHOULD 自動觸發被邀請者加入成員清單. 無論如何, 如果邀請權限被限于管理者們,而普通成員嘗試發送邀請, 服務必須 MUST 拒絕這個邀請的的請求并傳回一個 <forbidden/> 錯誤給發送者:
例子 125. 服務在普通成員嘗試邀請其他人加入僅限會員的房間時傳回錯誤
<message from='[email protected]' to='[email protected]/pda' type='error'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite to='[email protected]'> <reason> Hey Hecate, this is the place for all good witches! </reason> </invite> </x> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </message>
從開放房間發送的邀請不能 MUST NOT 觸發被邀請者加入成員清單.
如果一個使用者被加入一個開放房間的成員清單并且該使用者在該房間内, 服務必須 MUST 以該使用者的名義發送更新的出席資訊給所有房客, 這個出席資訊擁有一個滿足 '
例子 126. 服務發送成員資格通知給所有房客
<presence from='[email protected]/hecate' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' jid='[email protected]/broom' role='participant'/> </x> </presence> [ ... ]
授予主持人權限
管理者可能想授予主持人權限給一個與會者或遊客; 通過把使用者的角色改為 "moderator":
例子 127. 管理者授予主持人權限
<iq from='[email protected]/desktop' id='mod1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='thirdwitch' role='moderator'/> </query> </iq>
<reason/> 元素是可選的 OPTIONAL.
例子 128. 管理者授予主持人權限(包含一個原因Reason)
<iq from='[email protected]/desktop' id='mod1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='thirdwitch' role='moderator'> <reason>A worthy witch indeed!</reason> </item> </query> </iq>
服務必須 MUST 添加這個使用者到主持人清單然後通知管理者成功了:
例子 129. 服務通知管理者成功了
<iq from='[email protected]' id='mod1' to='[email protected]/desktop' type='result'/>
服務必須 MUST 接着以該使用者的名義發送更新的出席資訊給所有的房客, 這個出席資訊擁有一個滿足 '
例子 130. 服務發送主持人權限通知給所有房客
<presence from='[email protected]/thirdwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' jid='[email protected]/pda' role='moderator'/> </x> </presence> [ ... ]
撤銷主持人權限
管理者可能想撤銷使用者的主持人權限. 一個管理者隻可以 MAY 撤銷崗位為"member" 或 "none" (也就是, 非管理者和所有者)的使用者的主持人權限. 權限的撤銷是通過把使用者的角色改為 "participant"實作的:
例子 131. 管理者撤銷主持人權限
<iq from='[email protected]/desktop' id='mod2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='thirdwitch' role='participant'/> </query> </iq>
<reason/> 元素是可選的 OPTIONAL.
例子 132. 管理者撤銷主持人權限(包含一個原因Reason)
<iq from='[email protected]/desktop' id='mod2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='thirdwitch' role='participant'> <reason>Not so worthy after all!</reason> </item> </query> </iq>
服務必須 MUST 從主持人清單移除這個使用者然後通知管理者成功了:
例子 133. 服務通知管理者成功了
<iq from='[email protected]' id='mod2' to='[email protected]/desktop' type='result'/>
服務必須 MUST 接着以該使用者的名義發送更新的出席資訊給所有的房客, 這個出席資訊擁有一個滿足 '
例子 134. 服務通知失去了主持人權限
<presence from='[email protected]/thirdwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' jid='[email protected]/pda' role='participant'/> </x> </presence> [ ... ]
大家知道, 管理者不 MUST NOT 被允許從崗位為 "owner" 或 "admin"的使用者撤銷主持人權限. 如果一個管理者嘗試撤銷這類使用者的權限, 服務必須MUST 拒絕這個請求并傳回一個 <not-allowed/> 錯誤給發送者:
例子 135. 服務在使用者嘗試撤銷管理者或所有者的主持人權限時傳回錯誤
<iq from='[email protected]' id='modtest' to='[email protected]/desktop' type='error'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='secondwitch' role='participant'/> </query> <error type='cancel'> <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
修改主持人清單
管理者可能希望修改主持人清單. 為此, 管理者首先通過請求房間内所有角色為'moderator'的使用者來請求主持人清單.
例子 136. 管理者請求主持人清單
<iq from='[email protected]/desktop' id='mod3' to='[email protected]' type='get'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item role='moderator'/> </query> </iq>
服務必須 MUST 接着傳回主持人清單給管理者; 每個條目必須 MUST 包含 'jid', 'nick', 'role' 屬性并應該 SHOULD 包含 'affiliation' 屬性:
例子 137. 服務發送主持人清單給管理者
<iq from='[email protected]' id='mod3' to='[email protected]/desktop' type='result'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='member' jid='[email protected]/pda' nick='thirdwitch' role='moderator'/> </query> </iq>
管理者可以 MAY 接着修改主持人清單. 為此, 管理者必須 MUST發送修改的條目(即, 僅"delta") 給服務; 每個條目必須 MUST 包含 'jid' 屬性和'role' 屬性(通常值設為 "member" 或 "participant") 但不應該 SHOULD NOT 包含 'nick' 屬性并且不能 MUST NOT 包含 'affiliation' 屬性(它被用于管理類似管理者這樣的崗位而不是主持人這樣的角色):
例子 138. 管理者發送修改了的主持人清單給服務
<iq from='[email protected]/desktop' id='mod4' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item jid='[email protected]/pda' role='participant'/> <item jid='[email protected]/broom' role='moderator'/> </query> </iq>
服務必須 MUST 修改主持人清單并通知管理者成功了:
例子 139. 服務通知管理者成功了
<iq from='[email protected]' id='mod4' to='[email protected]/desktop' type='result'/>
服務必須 MUST 随後以所有受影響的使用者發送更新的出席資訊給所有的房客, 支出主持人權限的變更,通過發送前面用例所述的适當的擴充出席資訊.
顯然, 房間所有者或房間管理者的主持人權限不能被撤銷. 如果一個房間管理者嘗試通過修改主持人清單來撤銷這類使用者的主持人權限, 服務必須 MUST 拒絕請求并傳回一個 <not-allowed/> 錯誤給發送者:
例子 140. 服務在使用者嘗試撤銷管理者或所有者的主持人權限時傳回錯誤
<iq from='[email protected]' id='modtest' to='[email protected]/pda' type='error'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item jid='[email protected]/broom' nick='Hecate' role='participant'/> </query> <error type='cancel'> <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
準許注冊申請
如果一個服務不自動接受注冊到房間的請求, 它可以 MAY 為房間管理者提供一個方法來準許或拒絕來自 Jabber 的注冊請求(替代方案是, 它可能提供一個 web 接口或一些其他管理工具). 對這個服務來說,最簡單的辦法就是,當接收到注冊請求時發送一個 <message/> 節給房間管理者(們), 這裡的<message/> 節包含一個資料表格 Data Form asking 用來詢問管理者是否準許使用者的注冊申請. 推薦 RECOMMENDED 以下資料表格 Data Form,但是實作可以 MAY 使用完全不同的表格, 或or 在下面的表格基礎上補充字段.
例子 141. 注冊申請準許表格
<message from='[email protected]' id='approve' to='[email protected]/pda'> <x xmlns='jabber:x:data' type='form'> <title>Registration request</title> <instructions> To approve this registration request, select the "Allow this person to register with the room?" checkbox and click OK. To skip this request, click the cancel button. </instructions> <field var='FORM_TYPE' type='hidden'> <value>http://jabber.org/protocol/muc#register</value> </field> <field var='muc#register_first' type='text-single' label='Given Name'> <value>Brunhilde</value> </field> <field var='muc#register_last' type="text-single" label="Family Name"> <value>Entwhistle-Throckmorton</value> </field> <field var='muc#register_roomnick' type="text-single" label="Desired Nickname"> <value>thirdwitch</value> </field> <field var='muc#register_url' type="text-single" label="User URL"> <value>http://witchesonline/~hag66/</value> </field> <field var='muc#register_email' type="text-single" label="Email Address"> <value>[email protected]</value> </field> <field var='muc#register_faqentry' type="text-single" label="FAQ Entry"> <value>Just another witch.</value> </field> <field var='muc#register_allow' type='boolean' label='Allow this person to register with the room?'> <value>0</value> </field> </x> </message>
如果管理者準許了注冊申請, 服務将把該使用者注冊到房間.
更多進階的準許機制(例如, 使用特定指令Ad-Hoc Commands19來接收注冊申請清單,就像 Publish-Subscribe 20裡所做的一樣) 超出了本文的範圍.
所有者用例
每個房間必須 MUST 至少有一個所有者, 而所有者(或一個成功者)在一個房間的生命周期裡是這個房間長期存在的屬性(例如, 所有者在退出一個持久性的房間時不會失去所有權). 本文假定(初始的) 房間所有者是那個建立了該房間的使用者并且有一個房間所有者有權修改房間配置選項的定義,例如房間類型. 理想情況下, 房間所有者不僅能指定房間類型(密碼保護的, 僅限會員的, 等等) 而且包括如本文的 [XEP-0045#需求|需求]章節所述的房間特定屬性. 另外, 如果所有者能指定其他所有者們的JID也是不錯的, 但那将取決于具體實作.
為了讓配置選項更加廣泛提供必要的伸縮性, 房間配置将使用 Data Forms (XEP-0004), 通過使用由 '
注意: 以下展示的配置選項列出了本文的需求章節的所有特性和房間類型; 無論如何, 實際的配置選項和表格布局将取決于實作和具體的布署. 而且, 這些隻是例子,不代表這些就是房間可以擁有的所有允許或需要的配置選項. 一個特定的實作或布署可以 MAY 選擇提供額外的配置選項(敏感詞過濾, 設定房間的預設語言, 消息記錄, 等等), 這就是為什麼在這裡使用 'jabber:x:data' 協定是很有價值的.
建立房間
一般注意事項
建立房間的權限可以 MAY 限制在特定的使用者群或可以 MAY 保留給一個服務級别的管理者. 如果通路被拒絕而一個使用者試圖建立一個房間, 服務必須MUST 傳回一個 <not-allowed/> 錯誤:
例子 142. 服務通知使用者不能建立房間
<presence from='[email protected]/thirdwitch' to='[email protected]/pda' type='error'> <x xmlns='http://jabber.org/protocol/muc'/> <error type='cancel'> <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </presence>
如果通路不限制, 服務必須 MUST 允許使用者按以下步驟建立房間.
從房間建立的視角來看, 本質上有兩種房間:
- 即時房間"Instant rooms" -- 可以立刻通路并基于某些預設配置自動建立.
- 保留房間"Reserved rooms" -- 在任何人通路之前由房間配置者手動建立.
- 使用者必須 MUST 發送出席資訊到 <[email protected]/nick> 并聲明他或她對MUC協定的支援,通過包含一個擴充的出席資訊,并包含在一個空的滿足'
- 如果初始的房間所有者想建立和配置一個保留房間, 房間所有者必須 MUST 接着請求一個配置,通過發送類型為"get"的IQ節并包含一個空的滿足'
- 如果房間所有者請求了一個配置表格, 服務必須 MUST 發送一個包含配置表格并遵循 'jabber:x:data'名字空間的 IQ 給房間擁有者. 如果沒有配置選項可用, 房間必須 MUST 傳回一個空的 query 元素給房間所有者.
-
- 初始的房間所有者應該 SHOULD 為該房間提供一個開始的配置(或接受預設配置),通過發送"set"類型并包含完整的配置表格的 IQ . 另外, 房間所有者可以 MAY 取消配置過程. (實作可以 MAY 設定一個初始化配置的逾時, 這樣如果房間所有者再給定的逾時時間内不配置房間, 房間所有者就被假定已經接受了預設得配置或取消了配置過程.)
- 一旦服務從初始房間所有者接收了完整的配置表格(或接收到了一個即時房間的請求), 服務必須 MUST 解鎖 "unlock" 這個房間 (即, 允許其他使用者進入此房間) 并發送"result"類型的 IQ 給房間所有者. 如果服務接收到了取消(指令), 它必須 MUST 銷毀這個房間.
以下例子展示了這個協定流程.
首先, Jabber使用者必須 MUST 發送出席資訊給房間, 包含空的 <x/> 元素,遵循 '
注意: 如果如上的發送到一個不存在的房間裡的出席資訊節沒有包含一個遵循 '
建立即時房間
如果初始的房間所有者想接受預設的房間配置(即, 建立一個即時房間"instant room"), 房間所有者必須 MUST 拒絕初始配置表格,通過發送一個 IQ set 給 <[email protected]> 本身,包含一個遵循'
例子 145. 所有者請求即時房間
<iq from='[email protected]/desktop' id='create1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#owner'> <x xmlns='jabber:x:data' type='submit'/> </query> </iq>
服務必須 MUST 接着解鎖該房間并允許其他實體加入它.
建立保留房間
如果初始的房間所有者想建立并配置一個保留房間, 這個房間所有者必須 MUST 請求初始配置表格,通過發送一個 IQ get 給 <[email protected]> 本身,包含一個空的遵循 'XMPP注冊項事項 章節.)
例子 147. 服務發送配置表單
<iq from='[email protected]' id='create1' to='[email protected]/desktop' type='result'> <query xmlns='http://jabber.org/protocol/muc#owner'> <x xmlns='jabber:x:data' type='form'> <title>Configuration for "darkcave" Room</title> <instructions> Your room [email protected] has been created! The default configuration is as follows: - No logging - No moderation - Up to 20 occupants - No password required - No invitation required - Room is not persistent - Only admins may change the subject - Presence broadcasted for all users To accept the default configuration, click OK. To select a different configuration, please complete this form. </instructions> <field type='hidden' var='FORM_TYPE'> <value>http://jabber.org/protocol/muc#roomconfig</value> </field> <field label='Natural-Language Room Name' type='text-single' var='muc#roomconfig_roomname'/> <field label='Short Description of Room' type='text-single' var='muc#roomconfig_roomdesc'/> <field label='Natural Language for Room Discussions' type='text-single' var='muc#roomconfig_lang'/> <field label='Enable Public Logging?' type='boolean' var='muc#roomconfig_enablelogging'> <value>0</value> </field> <field label='Allow Occupants to Change Subject?' type='boolean' var='muc#roomconfig_changesubject'> <value>0</value> </field> <field label='Allow Occupants to Invite Others?' type='boolean' var='muc#roomconfig_allowinvites'> <value>0</value> </field> <field label='Maximum Number of Occupants' type='list-single' var='muc#roomconfig_maxusers'> <value>20</value> <option label='10'><value>10</value></option> <option label='20'><value>20</value></option> <option label='30'><value>30</value></option> <option label='50'><value>50</value></option> <option label='100'><value>100</value></option> <option label='None'><value>none</value></option> </field> <field label='Roles for which Presence is Broadcast' type='list-multi' var='muc#roomconfig_presencebroadcast'> <value>moderator</value> <value>participant</value> <value>visitor</value> <option label='Moderator'><value>moderator</value></option> <option label='Participant'><value>participant</value></option> <option label='Visitor'><value>visitor</value></option> </field> <field label='Roles and Affiliations that May Retrieve Member List' type='list-multi' var='muc#roomconfig_getmemberlist'> <value>moderator</value> <value>participant</value> <value>visitor</value> <option label='Moderator'><value>moderator</value></option> <option label='Participant'><value>participant</value></option> <option label='Visitor'><value>visitor</value></option> </field> <field label='Make Room Publicly Searchable?' type='boolean' var='muc#roomconfig_publicroom'> <value>1</value> </field> <field label='Make Room Persistent?' type='boolean' var='muc#roomconfig_persistentroom'> <value>0</value> </field> <field label='Make Room Moderated?' type='boolean' var='muc#roomconfig_moderatedroom'> <value>0</value> </field> <field label='Make Room Members-Only?' type='boolean' var='muc#roomconfig_membersonly'> <value>0</value> </field> <field label='Password Required to Enter?' type='boolean' var='muc#roomconfig_passwordprotectedroom'> <value>0</value> </field> <field type='fixed'> <value> If a password is required to enter this room, you must specify the password below. </value> </field> <field label='Password' type='text-private' var='muc#roomconfig_roomsecret'/> <field label='Who May Discover Real JIDs?' type='list-single' var='muc#roomconfig_whois'> <option label='Moderators Only'> <value>moderators</value> </option> <option label='Anyone'> <value>anyone</value> </option> </field> <field type='fixed'> <value> You may specify additional people who have administrative privileges in the room. Please provide one Jabber ID per line. </value> </field> <field label='Room Admins' type='jid-multi' var='muc#roomconfig_roomadmins'/> <field type='fixed'> <value> You may specify additional owners for this room. Please provide one Jabber ID per line. </value> </field> <field label='Room Owners' type='jid-multi' var='muc#roomconfig_roomowners'/> </x> </query> </iq>
注意: _whois 配置選項指定該房間是非匿名的(值為 "anyone"), 半匿名的(值為"moderators"), 還是全匿名的(值為"none", 不顯示在這).
如果沒有配置選項可用, 服務必須 MUST 傳回空的 query 元素給房間所有者:
例子 148. 服務通知所有者沒有配置可用
<iq from='[email protected]' id='create1' to='[email protected]/desktop' type='result'> <query xmlns='http://jabber.org/protocol/muc#owner'/> </iq>
房間所有者應該 SHOULD 接着填好表單并送出給服務.
例子 149. 所有者送出配置表單
<iq from='[email protected]/desktop' id='create2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#owner'> <x xmlns='jabber:x:data' type='submit'> <field var='FORM_TYPE'> <value>http://jabber.org/protocol/muc#roomconfig</value> </field> <field var='muc#roomconfig_roomname'> <value>A Dark Cave</value> </field> <field var='muc#roomconfig_roomdesc'> <value>The place for all good witches!</value> </field> <field var='muc#roomconfig_enablelogging'> <value>0</value> </field> <field var='muc#roomconfig_changesubject'> <value>1</value> </field> <field var='muc#roomconfig_allowinvites'> <value>0</value> </field> <field var='muc#roomconfig_maxusers'> <value>10</value> </field> <field var='muc#roomconfig_publicroom'> <value>0</value> </field> <field var='muc#roomconfig_persistentroom'> <value>0</value> </field> <field var='muc#roomconfig_moderatedroom'> <value>0</value> </field> <field var='muc#roomconfig_membersonly'> <value>0</value> </field> <field var='muc#roomconfig_passwordprotectedroom'> <value>1</value> </field> <field var='muc#roomconfig_roomsecret'> <value>cauldronburn</value> </field> <field var='muc#roomconfig_whois'> <value>moderators</value> </field> <field var='muc#roomconfig_roomadmins'> <value>[email protected]</value> <value>[email protected]</value> </field> </x> </query> </iq>
如果房間建立成功, 服務必須 MUST 通知新的房間所有者成功了:
例子 150. 服務通知新房間所有者成功
<iq from='[email protected]' id='create2' to='[email protected]/desktop' type='result'/>
如果因為指定的房間配置違反了一個或多個服務政策而導緻房間建立失敗 (例如, 因為密碼保護房間的密碼為空), 服務必須 MUST 傳回一個 <not-acceptable/> 錯誤.
例子 151. 服務通知所有者請求的配置選項不被接受
<iq from='[email protected]' id='create2' to='[email protected]/desktop' type='error'> <error type='modify'> <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
另一方面, 房間所有者可以 MAY 取消配置過程:
例子 152. 所有者取消初始的配置
<iq from='[email protected]/desktop' id='create2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#owner'> <x xmlns='jabber:x:data' type='cancel'/> </query> </iq>
如果房間所有者取消了初始的房間配置, 服務應該 SHOULD 銷毀房間, 確定發送不可用出席資訊給房間所有者 (詳見 "銷毀房間" 用例).
如果房間所有者在送出表單之前因為任何原因下線了(例如, 失去連接配接), 服務将接收到一個類型為 "unavailable" 的出席資訊節,從所有者到所有者的 <[email protected]/nick> 或到 <[email protected]> (或兩者). 服務必須 MUST 接着銷毀這個房間, 發送一個 "unavailable" 類型的出席資訊節,從房間到所有者,包含一個 <destroy/> 元素以及 reason (子元素)(如果提供了) ,參見本文的銷毀房間章節.
申請唯一房間名
在一些場合 (例如, 當 把一對一聊天轉為會議), 房間建立者可能想在嘗試建立房間之前請求一個唯一的房間名 (例如, 避免可能的房間沖突). 為此, 服務可以 MAY 如本章所述支援這個特性. (如果服務支援這個特性, 它必須 MUST 在對服務發現資訊請求應答時傳回一個 "http://jabber.org/protocol/muc#unique" 特性.)
房間建立者通過發送一個 IQ-get 給服務本身來請求唯一房間名, 這個IQ節中包含一個空的 <unique/> 元素,遵循 '随後的房間配置
在指定房間的初始配置之後的任何時間, 房間所有者可能想修改房間配置. 為此, 房間所有者必須 MUST 向房間發出一個新的配置表單請求,通過發送一個 IQ 到 <[email protected]> ,包含一個空的 <query/> 元素,遵循 '
如果沒有配置選項可用, 服務必須 MUST 傳回一個空的 query 元素給房間所有者,如前面的用例所示.
該房間所有者應該 SHOULD 接着以更新的配置資訊送出表單.
另外, 房間所有者可以 MAY 取消這次配置過程:
例子 159. 所有者取消随後的配置
<iq from='[email protected]/desktop' id='config2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#owner'> <x xmlns='jabber:x:data' type='cancel'/> </query> </iq>
如果房間所有者取消随後的配置, 服務必須 MUST 讓該房間的配置保持和房間所有者請求這次配置之前一樣.
如果一次房間配置變更導緻一個房間管理者失去管理權限,而這個管理者正在房間裡, 該房間必須 MUST 為那個管理者發送更新的出席資訊給所有房客, 表明狀态的變更,通過包含一個遵循 '
例子 160. 服務通知失去管理者崗位
<presence from='[email protected]/secondwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' jid='[email protected]/laptop' role='participant'/> </x> </presence> [ ... ]
如果一次房間配置變更導緻一個使用者獲得管理者權限,而這個使用者正在房間裡, 房間必須 MUST 為那個使用者發送更新的出席資訊給所有房客, 表明狀态的變更,通過包含一個遵循 '
例子 161. 服務通知所有使用者有人獲得管理者崗位
<presence from='[email protected]/secondwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='admin' jid='[email protected]/laptop' role='moderator'/> </x> </presence> [ ... ]
如果一次房間配置變更導緻一個房間所有者失去所有者權限,而這個所有者正在房間裡, 該房間必須 MUST 為那個所有者發送更新的出席資訊給所有房客, 表明狀态的變更,通過包含一個遵循 '
例子 162. 服務通知失去所有者崗位
<presence from='[email protected]/secondwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='admin' jid='[email protected]/laptop' role='moderator'/> </x> </presence> [ ... ]
如果沒有其他所有者,服務不能 MUST NOT 允許一個所有者撤銷他或她自己的所有權; 如果一個所有者企圖這麼幹, 服務必須 MUST 傳回一個 <conflict/> 錯誤給這個所有者. 然而, 如果有其他所有者,服務應該 SHOULD 允許一個所有者撤銷自己的所有者權限.
如果一次房間配置變更導緻一個使用者獲得所有者權限,而這個使用者正在房間裡, 房間必須 MUST 為那個使用者發送更新的出席資訊給所有房客, 表明狀态的變更,通過包含一個遵循 '
例子 163. 服務通知所有使用者有人獲得所有者權限
<presence from='[email protected]/secondwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='owner' jid='[email protected]/laptop' role='moderator'/> </x> </presence> [ ... ]
如果一次房間配置變更導緻房間類型變成僅限會員,但還有非成員在房間裡, 服務必須 MUST 從房間移除任何非成員,并在發送給那些剩餘的房客的 '不可用' 出席資訊節裡包含狀态碼 322.
配置變更通知
當一個房間的配置變更會對房間的隐私和安全政策産生影響時,該房間必須 MUST 發送通知給所有房客. 這個通知将包括一個 <message/> 節,包含一個遵循 '授予所有者權限
如果實作允許, 一個所有者可以 MAY 授予所有權給其他使用者; 隻要把使用者的崗位改成"owner":
例子 165. 所有者授予所有權
<iq from='[email protected]/desktop' id='owner1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='owner' jid='[email protected]'/> </query> </iq>
<reason/> 元素是可選的 OPTIONAL.
例子 166. 所有者授予所有權(飽含一個原因 Reason)
<iq from='[email protected]/desktop' id='owner1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='owner' jid='[email protected]'> <reason>A worthy witch indeed!</reason> </item> </query> </iq>
服務必須 MUST 把使用者添加到所有者清單并通知所有者成功了:
例子 167. 服務通知所有者成功了
<iq from='[email protected]' id='owner1' to='[email protected]/desktop' type='result'/>
如果該使用者在房間裡, 服務必須 MUST 接着以這個使用者的名義發送更新的出席資訊給所有房客, 表明已授予所有權,通過包含一個遵循 '
例子 168. 服務發送所有權通知給所有房客
<presence from='[email protected]/hecate' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='owner' jid='[email protected]' role='moderator'/> </x> </presence> [ ... ]
如果該使用者不在房間, 服務可以 MAY 從房間本身發送一個消息給房間的房客們, 表明已授予所有權,通過包含一個遵循 '
例子 169. 服務發送所有權通知給所有房客
<message from='chat.shakespeare.lit' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' jid='[email protected]' role='none'/> </x> </message> [ ... ]
撤銷所有者權限
實作可以 MAY 允許一個所有者撤銷其他使用者的所有權; 隻要把使用者的崗位改成非"owner":
例子 170. 所有者撤銷所有權
<iq from='[email protected]/desktop' id='owner2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='admin' jid='[email protected]'/> </query> </iq>
<reason/>元素是可選的 OPTIONAL.
例子 171. 所有者撤銷所有權(包含一個原因)
<iq from='[email protected]/desktop' id='owner2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='admin' jid='[email protected]'> <reason>Not so worthy after all!</reason> </item> </query> </iq>
如果沒有其它所有者,服務不能 MUST NOT 允許一個所有者撤銷他或她自己的所有權; 如果一個所有者嘗試這麼幹, 服務必須 MUST 傳回一個 <conflict/> 錯誤給該所有者. 然而, 如果有其他所有者,服務應該 SHOULD 允許一個所有者撤銷自己的所有權.
如果一個實作不允許所有者撤銷另一個使用者的所有權, 實作必須 MUST 傳回一個 <not-authorized/> 錯誤給做出這個請求的所有者.
注意: 允許一個所有者移除其它使用者的所有權能給房間管理一個折衷的控制模式; 是以這個特性是可選的 OPTIONAL, 并且鼓勵實作支援通過一個隻有擁有服務範圍管理權限的使用者使用的接口來移除所有者.
其它情況下, 服務必須 MUST 把使用者從所有者清單移除并通知所有者成功了:
例子 172. 服務通知所有者成功了
<iq from='[email protected]' id='owner2' to='[email protected]/desktop' type='result'/>
如果該使用者在房間裡, 服務必須 MUST 接着以這個使用者的名義發送更新的出席資訊給所有房客, 表明已失去所有權,通過包含一個遵循 '
例子 173. 服務通知失去所有權
<presence from='[email protected]/secondwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='admin' jid='[email protected]' role='moderator'/> </x> </presence> [ ... ]
如果該使用者不在房間, 服務可以 MAY 從房間本身發送一個消息給房間的房客們, 表明已失去所有權,通過包含一個遵循 '
例子 174. 服務發送失去所有權通知給所有房客
<message from='chat.shakespeare.lit' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='admin' jid='[email protected]' role='none'/> </x> </message> [ ... ]
修改所有者清單
如果實作允許, 一個房間所有者可能想修改所有者清單. 為此, 所有者首先請求所有者清單,通過向房間請求所有崗位為 'owner'的使用者.
例子 175. 所有者請求所有者清單
<iq from='[email protected]/globe' id='owner3' to='[email protected]' type='get'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='owner'/> </query> </iq>
如果'from'位址的 <[email protected]> 部分和房間所有者的純JID不符, 服務必須 MUST 傳回一個 <forbidden/> 錯誤給發送者.
否則, 服務必須 MUST 接着傳回所有者清單給所有者; 每個條目必須 MUST 包含 'affiliation' 和 'jid' 屬性,對任何正是一名房客(也就是正在房間裡)的所有者可以 MAY 包含 'nick' 和 'role' 屬性:
例子 176. 服務發送所有者清單給所有者
<iq from='[email protected]' id='owner3' to='[email protected]/globe' type='result'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='owner' jid='[email protected]'/> </query> </iq>
所有者可以 MAY 接着修改所有者清單. 為此, 所有者必須 MUST 發送修改的條目 (即, 僅 "delta") 給服務; 21每個條目必須 MUST 包含 'affiliation' 和 'jid' 屬性,但不應該 SHOULD NOT 包含 'nick' 屬性,不能 MUST NOT 包含 'role' 屬性 (它用于管理參與者之類的角色,而不是所有者之類的崗位):
例子 177. 所有者發送修改過的所有者清單給服務
<iq from='[email protected]/globe' id='owner4' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='owner' jid='[email protected]'/> </query> </iq>
隻有所有者被允許修改所有者清單. 如果一個非所有者試圖察看或修改所有者清單, 服務必須 MUST 拒絕這個請求并傳回一個 <forbidden/> 錯誤給發送者:
例子 178. 服務對于非所有者試圖修改所有者清單傳回錯誤
<iq from='[email protected]' id='ownertest' to='[email protected]/pda' type='error'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='owner' jid='[email protected]'/> </query> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
如果沒有别的所有者,服務不能 MUST NOT 允許一個所有者撤銷自己的所有權; 如果一個所有者嘗試這麼幹, 服務必須 MUST 傳回一個 <conflict/> 錯誤給該所有者. 然而, 如果有其他所有者,服務應該 SHOULD 允許一個所有者撤銷自己的所有權.
其它情況下, 服務必須 MUST 修改所有者清單并通知所有者成功了:
例子 179. 服務通知所有者成功了
服務必須 MUST 也為任何因前述所有者清單修改而導緻的崗位變化而發送出席資訊通知.<iq from='[email protected]' id='owner4' to='[email protected]/desktop' type='result'/>
授予管理者權限
一個所有者可以授予管理者權限給一個成員或無崗位的使用者; 隻要把使用者的崗位改成"admin":
例子 180. 所有者授予管理者權限
<iq from='[email protected]/desktop' id='admin1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='admin' jid='[email protected]'/> </query> </iq>
<reason/> 元素是可選的 OPTIONAL.
例子 181. 所有者授予管理者權限(包含一個原因 Reason)
<iq from='[email protected]/desktop' id='admin1' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='admin' jid='[email protected]'> <reason>A worthy witch indeed!</reason> </item> </query> </iq>
服務必須 MUST 把使用者添加到管理者清單并通知所有者成功了:
例子 182. 服務通知所有者成功了
<iq from='[email protected]' id='admin1' to='[email protected]/desktop' type='result'/>
如果該使用者在房間裡, 服務必須 MUST 接着以這個使用者的名義發送更新的出席資訊給所有房客, 表明已授予管理者權限,通過包含一個遵循 '
例子 183. 服務發送管理者權限通知給所有房客
<presence from='[email protected]/secondwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='admin' jid='[email protected]' role='moderator'/> </x> </presence> [ ... ]
如果該使用者不在房間, 服務可以 MAY 從房間本身發送一個消息給房間的房客們, 表明已授予管理者權限,通過包含一個遵循 '
例子 184. 服務發送管理者權限通知給所有房客
<message from='chat.shakespeare.lit' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='admin' jid='[email protected]' role='none'/> </x> </message> [ ... ]
撤銷管理者權限
一個所有者可能想撤銷一個使用者的管理者權限; 隻要把使用者的崗位改成非"admin"和非"owner":
例子 185. 所有者撤銷管理者權限
<iq from='[email protected]/desktop' id='admin2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='member' jid='[email protected]'/> </query> </iq>
<reason/>元素是可選的 OPTIONAL.
例子 186. 所有者撤銷管理者權限(包含一個原因)
<iq from='[email protected]/desktop' id='admin2' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='member' jid='[email protected]'> <reason>Not so worthy after all!</reason> </item> </query> </iq>
服務必須 MUST 把該使用者從管理者清單移除并接着通知所有者成功了:
例子 187. 服務通知所有者成功了
<iq from='[email protected]' id='admin2' to='[email protected]/desktop' type='result'/>
如果該使用者在房間裡, 服務必須 MUST 接着以這個使用者的名義發送更新的出席資訊給所有房客, 表明已失去管理者權限,通過包含一個遵循 '
例子 188. 服務通知失去管理者權限
<presence from='[email protected]/secondwitch' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' jid='[email protected]' role='participant'/> </x> </presence> [ ... ]
如果該使用者不在房間, 服務可以 MAY 從房間本身發送一個消息給房間的房客們, 表明已失去所有權,通過包含一個遵循 '
例子 189. 服務通知失去管理者權限
<message from='chat.shakespeare.lit' to='[email protected]/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='member' jid='[email protected]' role='none'/> </x> </message> [ ... ]
修改管理者清單
一個房間所有者可能想修改管理者清單. 為此, 所有者首先請求管理者清單,通過向房間請求所有崗位為 'admin'的使用者.
例子 190. 所有者請求管理者清單
<iq from='[email protected]/desktopaffiliation id='admin3' to='[email protected]' type='get'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='admin'/> </query> </iq>
如果'from'位址的 <[email protected]> 部分和房間所有者的純JID不符, 服務必須 MUST 傳回一個 <forbidden/> 錯誤給發送者.
否則, 服務必須 MUST 接着傳回管理者清單給所有者; 每個條目必須 MUST 包含 'affiliation' 和 'jid' 屬性,對任何正是一名房客(也就是正在房間裡)的管理者可以 MAY 包含 'nick' 和 'role' 屬性:
例子 191. 服務發送管理者清單給所有者
<iq from='[email protected]' id='admin3' to='[email protected]/globe' type='result'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='admin' jid='[email protected]' nick='secondwitch'/> <item affiliation='admin' jid='[email protected]'/> </query> </iq>
所有者可以 MAY 接着修改管理者清單. 為此, 所有者必須 MUST 發送修改的條目 (即, 僅 "delta") 給服務; 22 每個條目必須 MUST 包含 'affiliation'屬性(通常值為 "admin" 或 "none") 和 'jid' 屬性,但不應該 SHOULD NOT 包含 'nick' 屬性,不能 MUST NOT 包含 'role' 屬性 (它用于管理參與者之類的角色,而不是管理者之類的崗位):
例子 192. 所有者發送修改的管理者清單給服務
<iq from='[email protected]/globe' id='admin4' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='none' jid='[email protected]'> </item> <item affiliation='admin' jid='[email protected]'> </item> </query> </iq>
隻有所有者被允許修改管理者清單. 如果一個非所有者試圖察看或修改所有者清單, 服務必須 MUST 拒絕這個請求并傳回一個 <forbidden/> 錯誤給發送者:
例子 193. 服務對于非所有者試圖修改管理者清單傳回錯誤
<iq from='[email protected]' id='admintest' to='[email protected]/pda' type='error'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='admin' jid='[email protected]'/> </query> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
否則, 服務必須 MUST 修改管理者清單并通知所有者成功了:
例子 194. 服務通知所有者成功了
服務必須 MUST 也為任何因前述管理者清單修改而導緻的崗位變化而發送出席資訊通知.<iq from='[email protected]' id='admin4' to='[email protected]/desktop' type='result'/>
銷毀房間
房間所有者必須 MUST 能夠銷毀一個房間, 特别是如果這個房間不是持久房間的時候. 流程如下:- 房間所有者請求銷毀房間, 如果必要的話指出一個原因 reason 和一個備用場地.
- 該房間移除所有房客(包含适當的關于備用場地和被移除的原因的資訊) 并銷毀房間, 即使它被定義為持久房間.
不像前述的, 本文不指定一個MUC服務實作收到一個銷毀房間請求之後将會如何做. 例如, 如果房間定義為持久地, 一個實作可以 MAY 選擇鎖定房間I,這樣它不能被重用, 把加入該房間的請求重定向到替代場地, 或邀請目前的參與者到新的房間; 無論如何, 這些行為是可選的 OPTIONAL.
為了銷毀一個房間, 房間所有者必須 MUST 發送一個 IQ set 指令到要銷毀的房間的位址. 這個 <iq/> 節将包含一個遵循 '
例子 196. 服務移除每個房客
例子 197. 服務通知所有者成功銷毀房間<presence from='[email protected]/firstwitch' to='[email protected]/desktop' type='unavailable'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='none' role='none'/> <destroy jid='[email protected]'> <reason>Macbeth doth come.</reason> </destroy> </x> </presence> <presence from='[email protected]/secondwitch' to='[email protected]/laptop' type='unavailable'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='none' role='none'/> <destroy jid='[email protected]'> <reason>Macbeth doth come.</reason> </destroy> </x> </presence> <presence from='[email protected]/thirdwitch' to='[email protected]/pda' type='unavailable'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='none' role='none'/> <destroy jid='[email protected]'> <reason>Macbeth doth come.</reason> </destroy> </x> </presence>
<iq from='[email protected]' id='begone' to='[email protected]/desktop' type='result'/>
如果在一個銷毀請求中接收到的'from'位址的 <[email protected]> 和一個房間所有者的純JID不符, 服務必須 MUST 傳回一個 <forbidden/> 錯誤給發送者:
例子 198. 服務拒絕由非所有者送出的銷毀請求
<iq from='[email protected]' id='destroytest' to='[email protected]/laptop' type='error'> <query xmlns='http://jabber.org/protocol/muc#owner'> <destroy jid='[email protected]'> <reason>Macbeth doth come.</reason> </destroy> </query> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
錯誤和狀态碼
錯誤碼
和'錯誤條件映射 23; 實作應該 SHOULD 支援傳統和XMPP錯誤處理兩者.
表9: http://jabber.org/protocol/muc#user 名字空間的錯誤碼
本文不規定和上述錯誤條件相關的文本字元串(即, XMPP <text/> 元素值).碼 類型 元素 上下文 目的 401 Error Presence 進入一個房間 通知使用者需要密碼 403 Error Presence 進入一個房間 通知使用者他或她被房間禁止了 404 Error Presence 進入一個房間 通知使用者房間不存在 405 Error Presence 進入一個房間 通知使用者限制建立房間 406 Error Presence 進入一個房間 通知使用者必須使用保留的房間昵稱 407 Error Presence 進入一個房間 通知使用者他或她不在成員清單中 409 Error Presence 進入一個房間 通知使用者他或她的房間昵稱正在使用或被别的使用者注冊了 503 Error Presence 進入一個房間 通知使用者已經達到最大使用者數 狀态碼
多使用者聊天的使用一個 <status/> 元素(特指, <status/> 元素的的 'code' 屬性 ) 來傳達關于使用者在一個房間裡的狀态的資訊. 随着時間的推移, 狀态碼的數量已經增加了很多, 而新的狀态碼繼續被作者申請. 是以, 這些狀态碼現在記錄在一個由XMPP登記處維護的系統資料庫裡. 細節可參考本文的狀态碼系統資料庫.
注意: 通常, MUC 狀态碼傾向于沿用RFC 261624 和 RFC 1893 25 (1xx 碼表示資訊, 2xx 碼說明情況良好可繼續, 3xx 碼指定重定向被踢或被禁止的使用者, x3x 碼指系統狀态, x7x 碼指安全或政策事務, 等等) 裡面的狀态碼的 "抽象"含義.
注意: 如果今天來定義 MUC 協定, 它将指定一個更有彈性的, XML-友好的 途徑而不是寫死的狀态數字; 然而, 現在修改狀态彙報系統帶來的痛苦将遠大于好處, 這是為什麼狀态碼數字保持使用至今. 本文的未來版本可能定義一個更 類XMPP 的途徑來表示狀态條件, 保留狀态碼數字但是給它們補充更多的描述性的子元素,就像RFC 3920裡那樣.
國際化事項
如 RFC 3920 中所定義的, XMPP 實體 (包括 MUC 房間和 MUC 服務) 應該 SHOULD 遵守任何給定的節提供的 'xml:lang' 屬性. 然而, 群聊消息的同聲翻譯超出了本文的範圍.
這裡定義的狀态和錯誤碼允許一個用戶端實作展示一個本地化的界面; 然而, 任何給定語言社群的本地化文本字元串的定義超出了本文範圍.
盡管這裡的很多資料表單字段的标簽顯示為英文, MUC 用戶端應該 SHOULD 把這些字段展示為本地化的文本而不是英文文本.
安全事項
使用者驗證和授權
本文沒有定義或要求比明文密碼更安全的房間準入驗證或授權方法. 然而, 這些潛在的風險可能使用 RFC 3920 描述的通過使用 TLS 和 SASL 加密通道來減輕.端到端加密
這裡沒有定義沒有端到端消息或會話加密方法. 使用者不應該 SHOULD NOT 相信一個服務能保持通過房間發送的任何文本的安全.隐私
取決于房間配置, 一個房間可以公開地記錄房間裡發生的所有讨論. 服務必須 MUST 警告使用者該房間是公開記錄的,通過在該使用者的初始出席資訊中傳回一個狀态碼 "170" , 并且如果房間讨論被記錄 (使用者的用戶端也應該 SHOULD 在允許使用者進入之前查詢房間的配置,以"預先發現"房間是否被記錄),該使用者的用戶端也必須 MUST 警告使用者. 如果房間的配置随後修改成允許房間記錄(當房間發送狀态碼 170 時用戶端将發現),用戶端也必須 MUST 警告使用者 . 注意: 房間内的曆史和公開房間記錄是不同的, 并且很自然的一個房間不能有效地阻止房客獨立維護的自有的房間記錄, 它可能被公開; 使用者應該 SHOULD 謹慎操作并認識到任何房間讨論可能被有效地公開.匿名
取決于房間配置, 一個房間可以 MAY 暴光每個房客的真實 JID 給其他房客 (如果該房間是非匿名的) 并且将幾乎肯定地暴光每個房客的真實 JID 給該房間的所有者和管理者(如果該房間不是全匿名的).服務必須 MUST 警告使用者真實 JIDs 在房間被暴光,通過在該使用者的初始出席資訊中包含狀态碼 "100" , 并且使用者的用戶端必須 MUST 警告該使用者 (一個使用者的用戶端應該 SHOULD 也在允許使用者進入房間之前查詢房間配置以 "預先發現" 是否真實 JIDs 會在房間中暴光). 如果房間配置随後從半匿名或全匿名修改成非匿名(當房間發送狀态碼 172 時用戶端将發現) ,用戶端必須 MUST 也警告使用者,如果房間的配置随後從全匿名改成半匿名時(當房間發送狀态碼 173 時用戶端将發現),用戶端也應該 SHOULD 警告使用者.拒絕服務
公開的 MUC 房間能承受一定數量的攻擊, 大部分能減少拒絕服務攻擊. 這些攻擊包括但不限于:- 向房間裡塞進大量的非法房客進而阻止合法使用者加入房間.
- 發送侮辱性的消息接着在被踢或被禁止之前離開房間; 這些侮辱性的消息包含但不限于,大量消息以阻止參與者正常跟蹤會話線索或房間曆史, 對參與者的人身攻擊 (特别是房間管理者和主持人), 攻擊性的文字, 以及垃圾網站連結.
- 高頻率的制造出席資訊變更.
- 使用過長的昵稱導緻無法看到完整的發言.
- 辱罵房間管理者或其他房間房客.
- 在一個服務裡注冊很多昵稱然後禁止這些昵稱的使用.
- 模仿别的房客的昵稱(例如, 通過在尾部增加一個空格或看起來相似的字元串), 然後以那個房間昵稱發送消息用于欺騙房客.
其它事項
關于延遲遞送符号的列入和流程的更多安全事項參見 XEP-0203.IANA事項
本文檔與網際網路編号配置設定授權機構26無關。XMPP登記事項
XMPP登記處27在它的登記處包含了以下資訊.協定名字空間
XMPP登記處在它的協定名字空間系統資料庫裡包含了以下 MUC相關的名字空間:- http://jabber.org/protocol/muc
- http://jabber.org/protocol/muc#admin
- http://jabber.org/protocol/muc#owner
- http://jabber.org/protocol/muc#user
服務發現種類/類型
一個多使用者聊天服務或房間在服務發現裡是用 "conference" 種類categary 和 "text" 類型type 來辨別的.服務發現特性
有很多和MUC相關的服務或房間相關的特性可以被"服務發現"來發現. 這裡面最基本的是 '知名服務發現節點
知名服務發現節點 '允許的通訊章節).
字段标準化
資料表單的字段标準化28 定義了用于遵循特定名字空間的資料表單的字段标準化的過程. 在 MUC 裡面, 使用了四種這類表單: 房間注冊 ( "muc#register" FORM_TYPE), 請求發言權和準許請求 ("muc#request"), 房間配置 ("muc#roomconfig"), 以及用于房間資訊的服務發現擴充 ("muc#roominfo"). 這些保留的字段定義如下.
muc#register FORM_TYPE
注冊處送出
<form_type> <name>http://jabber.org/protocol/muc#register</name> <doc>XEP-0045</doc> <desc> Forms enabling user registration with a Multi-User Chat (MUC) room or admin approval of user registration requests. </desc> <field var='muc#register_allow' type='boolean' label='Allow this person to register with the room?'/> <field var='muc#register_email' type='text-single' label='Email Address'/> <field var='muc#register_faqentry' type='text-multi' label='FAQ Entry'/> <field var='muc#register_first' type='text-single' label='Given Name'/> <field var='muc#register_last' type='text-single' label='Family Name'/> <field var='muc#register_roomnick' type='text-single' label='Desired Nickname'/> <field var='muc#register_url' type='text-single' label='Your URL'/> </form_type>
muc#request FORM_TYPE
注冊處送出
<form_type> <name>http://jabber.org/protocol/muc#request</name> <doc>XEP-0045</doc> <desc> Forms enabling voice requests in a Multi-User Chat (MUC) room or admin approval of such requests. </desc> <field var='muc#role' type='text-single' label='Requested role'/> <field var='muc#jid' type='text-single' label='User ID'/> <field var='muc#roomnick' type='text-single' label='Room Nickname'/> <field var='muc#request_allow' type='boolean' label='Whether to grant voice'/> </form_type>
muc#roomconfig FORM_TYPE
注冊處送出
<form_type> <name>http://jabber.org/protocol/muc#roomconfig</name> <doc>XEP-0045</doc> <desc> Forms enabling creation and configuration of a Multi-User Chat (MUC) room. </desc> <field var='muc#roomconfig_allowinvites' type='boolean' label='Whether to Allow Occupants to Invite Others'/> <field var='muc#roomconfig_changesubject' type='boolean' label='Whether to Allow Occupants to Change Subject'/> <field var='muc#roomconfig_enablelogging' type='boolean' label='Whether to Enable Public Logging of Room Conversations'/> <field var='muc#roomconfig_getmemberlist' type='list-multi' label='Roles and Affiliations that May Retrieve Member List'/> <field var='muc#roomconfig_lang' type='text-single' label='Natural Language for Room Discussions'/> <field var='muc#roomconfig_pubsub' type='text-single' label='XMPP URI of Associated Publish-Subcribe Node'/> <field var='muc#roomconfig_maxusers' type='list-single' label='Maximum Number of Room Occupants'/> <field var='muc#roomconfig_membersonly' type='boolean' label='Whether an Make Room Members-Only'/> <field var='muc#roomconfig_moderatedroom' type='boolean' label='Whether to Make Room Moderated'/> <field var='muc#roomconfig_passwordprotectedroom' type='boolean' label='Whether a Password is Required to Enter'/> <field var='muc#roomconfig_persistentroom' type='boolean' label='Whether to Make Room Persistent'/> <field var='muc#roomconfig_presencebroadcast' type='list-multi' label='Roles for which Presence is Broadcast'/> <field var='muc#roomconfig_publicroom' type='boolean' label='Whether to Allow Public Searching for Room'/> <field var='muc#roomconfig_roomadmins' type='jid-multi' label='Full List of Room Admins'/> <field var='muc#roomconfig_roomdesc' type='text-single' label='Short Description of Room'/> <field var='muc#roomconfig_roomname' type='text-single' label='Natural-Language Room Name'/> <field var='muc#roomconfig_roomowners' type='jid-multi' label='Full List of Room Owners'/> <field var='muc#roomconfig_roomsecret' type='text-private' label='The Room Password'/> <field var='muc#roomconfig_whois' type='list-single' label='Affiliations that May Discover Real JIDs of Occupants'/> </form_type>
muc#roominfo FORM_TYPE
注冊處送出
<form_type> <name>http://jabber.org/protocol/muc#roominfo</name> <doc>XEP-0045</doc> <desc> Forms enabling the communication of extended service discovery information about a Multi-User Chat (MUC) room. </desc> <field var='muc#roominfo_contactjid' type='jid-multi' label='Contact Addresses (normally, room owner or owners)'/> <field var='muc#roominfo_description' type='text-single' label='Short Description of Room'/> <field var='muc#roominfo_lang' type='text-single' label='Natural Language for Room Discussions'/> <field var='muc#roominfo_ldapgroup' type='text-single' label='An associated LDAP group that defines room membership; this should be an LDAP Distinguished Name according to an implementation-specific or deployment-specific definition of a group.'/> <field var='muc#roominfo_logs' type='text-single' label='URL for Archived Discussion Logs'/> <field var='muc#roominfo_occupants' type='text-single' label='Current Number of Occupants in Room'/> <field var='muc#roominfo_subject' type='text-single' label='Current Subject or Discussion Topic in Room'/> <field var='muc#roominfo_subjectmod' type='boolean' label='The room subject can be modified by participants'/> </form_type>
狀态碼登記處
過程
XMPP注冊員為遵循 'URI查詢類型
作為由XMPP URI Query Components29授權的機構,XMPP注冊員維護着一個用于 XMPP URIs 的查詢和鍵-值對的系統資料庫(見<http://www.xmpp.org/registrar/querytypes.html>)。
join
"join" 查詢類型被注冊為一個 MUC相關的動作, 伴随一個可選的鍵 "password".
例子 199. Join動作: IRI/URI
xmpp:[email protected]?join
應用必須 MUST 要麼展示一個界面允許使用者提供一個房間昵稱,要麼基于配置好的選項或昵稱發現來擷取這個房間昵稱.
例子 200. Join動作: 結果節
<presence to='[email protected]/thirdwitch'> <x xmlns='http://jabber.org/protocol/muc'/> </presence>
join 動作可以 MAY 為這房間包含一個密碼. 自然的, 對一個包含了房間密碼的 URI 的通路必須 MUST 得到适當的控制.
例子 201. Join動作包含密碼: IRI/URI
例子 202. Join動作包含密碼: 結果節xmpp:[email protected]?join;password=cauldronburn
以下送出注冊 "join" 查詢類型.<presence to='[email protected]/thirdwitch'> <x xmlns='http://jabber.org/protocol/muc'> <password>cauldronburn</password> </x> </presence>
<querytype> <name>join</name> <proto>http://jabber.org/protocol/muc</proto> <desc>enables joining a multi-user chat room</desc> <doc>XEP-0045</doc> <keys> <key> <name>password</name> <desc>the password required to enter a multi-user chat room</desc> </key> </keys> </querytype>
invite
"invite" 查詢類型被注冊為一個 MUC相關的動作, 伴随一個可選的鍵 "jid".
例子 203. Invite動作: IRI/URI
xmpp:[email protected]?invite;[email protected]
如果加入中的使用者還未在房間裡, 應用必須 MUST 發送兩個節: 第一個加入房間,第二個邀請另一個人. 如果加入中的使用者已經在房間裡, 應用将隻發送邀請節.
例子 204. Invite動作: 結果節(s)
<presence to='[email protected]/thirdwitch'> <x xmlns='http://jabber.org/protocol/muc'/> </presence> <message to='[email protected]'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite to='[email protected]'/> </x> </message>
URI 可以包含多個邀請:
例子 205. Invite動作包含多個邀請: IRI/URI
例子 206. Invite動作包含多個邀請: 結果節xmpp:[email protected]?invite;[email protected];[email protected]
<message to='[email protected]'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite to='[email protected]'/> <invite to='[email protected]'/> </x> </message>
URI 也可以包含一個密碼:
例子 207. Invite動作包含密碼: IRI/URI
xmpp:[email protected]?invite;[email protected];password=cauldronburn
如果加入中的使用者還未在房間裡, 應用必須 MUST 發送兩個節: 第一個加入房間,第二個邀請另一個人. 如果加入中的使用者已經在房間裡, 應用将隻發送邀請節.
例子 208. Invite動作包含密碼: 結果節(s)
以下送出注冊 "invite" 查詢類型.<presence to='[email protected]/thirdwitch'> <x xmlns='http://jabber.org/protocol/muc'/> </presence> <message to='[email protected]'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite to='[email protected]'/> <password>cauldronburn</password> </x> </message>
<querytype> <name>invite</name> <proto>http://jabber.org/protocol/muc</proto> <desc>enables simultaneously joining a groupchat room and inviting others</desc> <doc>XEP-0045</doc> <keys> <key> <name>jid</name> <desc>the Jabber ID of the invitee</desc> </key> <key> <name>password</name> <desc>the password required to enter a multi-user chat room</desc> </key> </keys> </querytype>
商業規則
Addresses
為了提供關于從房間JIDs抓獲的位址的一緻性, Room IDs 必須 MUST 遵循 Stringprep 的 Nodeprep 規範并且 Room Nicknames 必須 MUST 符合 Stringprep (這些都定義在RFC 3920) 的 Resourceprep 規範. 盡管在RFC 3920 中沒有顯式的說明 , 一個 Room JID 的 Room ID (node) 和 Room Nickname (resource) 部分都必須 MUST 長度不為零. 另外, 一個 MUC 服務不能 MUST NOT 允許空的或不可見的房間昵稱 Room Nicknames (即, 房間昵稱Room Nicknames 隻包含一個或多個空格).
取決于服務實作,是否更多地限制房間昵稱 (例如, 通過應用情景例程, stringprep的Nodeprep規範, 或其他限制).
Message
- 如果一個房客想發送一個消息給所有其他房客, MUC 用戶端必須 MUST 把 'type' 屬性值設為 "groupchat". 服務可以 MAY 忽略不正确的消息類型, 或用 <bad-request/> 錯誤彈回.
- 如果一個MUC服務從一個角色為"none"的Jabber使用者收到一個發送給該房間的消息或給某個房客的消息, 服務不能 MUST NOT 遞送這個消息并應該 SHOULD 傳回給這個消息給發送者并伴随一個 <forbidden/> 錯誤.
- 如果一個MUC服務 接收到一個發送給不存在的或尚未解鎖的房間的消息, 服務應該 SHOULD 傳回這個消息給發送者并伴随一個 <item-not-found/> 錯誤.
- 一個MUC服務應該 SHOULD 不做修改地傳遞擴充的消息 (例如, 一個消息主體的 XHTML 版本) 給房客; 然而, 一個 MUC 服務可以 MAY 不允許消息的特定擴充(參見本文的允許的通訊章節).
- 一個MUC用戶端可以 MAY 生成擴充以滿足 消息事件 30 或 聊天狀态通知 31 規範; 然而, 一個 MUC 服務可以 MAY 不允許這些擴充 (參見本文的允許的通訊章節).
Presence
- 一個房間必須 MUST 安靜地忽略從一個角色為"none"的使用者發來的不可用出席資訊資訊.
- 隻有MUC服務自身應該 SHOULD 生成關于角色,崗位,全JIDs或遵循 ' 允許的通訊章節.
- 為了适當地通知房客角色和崗位, 并使之更易于Jabber用戶端跟蹤房間裡所有使用者的目前狀态, MUC服務實作必須 MUST 在所有出席資訊節裡提供關于角色和崗位的擴充的出席資訊, 包括一個使用者因為任何原因退出該房間時被發送的類型為"unavailable"的出席資訊節.
- 如果一個權限被撤銷, 服務必須 MUST 通知這件事,通過發送一個遵循 'RFC 3920).
- 在 muc#user 名字空間中被發送的關于角色和崗位的擴充的出席資訊必須 MUST 包含全JID (不是純JID) 作為 'jid' 屬性的值.
- 如果想要,一個用戶端可以 MAY 發送一個客戶化的退出消息 (就像 IRC 頻道裡經常出現的那樣) ,通過在退出時被發送的"unavailable"類型的出席資訊節裡包含一個 <status/> 元素.
IQ
- MUC被設計用于分享消息和出席資訊, 而不是 IQs. 一個被發送的到房間本身JID的 IQ 由房間本身來處理并且不反射給所有房客.
- 如果一個房客想在一個非匿名房間發送一個 IQ 節給其他使用者, 發送者應該 SHOULD 直接發送請求給接收者的純JID或全JID, 而不是試圖通過房間發送請求(即, 通過接收者的房間JID).
- 如果一個房客想在一個半匿名房間發送一個 IQ 節給其他使用者, 發送者能直接發送這個節給接受者的房間JID并且服務可以 MAY 轉發這個節給接收者的真實JID. 然而, 任何時候一個MUC服務不能 MUST NOT 洩露這個發送者的真實JID給接收者, 也不能洩露接收者的真實JID給發送者.
- 一個MUC用戶端必須 MUST 在IQ set 中的遵循 '
實作注意事項
以下方針有助于用戶端群組件開發者建立 MUC 實作.服務端
- 在處理一個被主持的房間裡遊客發送的消息時, 一個MUC服務可以 MAY 通過一個主持人讓每個消息排隊等待準許并且可以 MAY 通知發送者消息正在等待準許; 然而, 這一行為是可選的 OPTIONAL, 并且一個消息準許協定的定義 (例如, 使用XEP-0004定義的資料表單) 超出了本文的範圍.
- 對于一個 MUC 服務來說,在特定事件發生時提供房間内的消息是很常見的, 例如當标題變更時, 當一個房客加入或退出時, 或當一個房間被銷毀時. 這類消息完全是可選的 OPTIONAL 并且留給實作或布署來決定, 但如果使用了,則必須 MUST 是從房間JID本身(<[email protected]>) 而不是從一個特定的房客(<[email protected]/nick>)發送的類型為 "groupchat" 類型的消息. 無論如何, 通常接收的用戶端傾向于基于房間的事件以及MUC提供的特定狀态碼來生成類似的消息(例如, 使用者加入或退出) ; 這将幫助確定這類消息的正确的本地化.
- 出于禮貌, 一個MUC服務可以 MAY 發送一個房間外的 <message/> 給一個被踢的或被禁止的房客, 并且可以 MAY 廣播一個房間内的 <message/> 給所有剩餘的房客通知他們該房客已被該房間踢出或禁止. 無論如何, 這類消息是可選的 OPTIONAL, 并且事實上是多餘的,因為接收的用戶端生成這類消息所必需的資訊已經通過MUC服務發送的出席資訊節(特别是狀态碼)得到了.
- 出于禮貌, 如果一個使用者的崗位變更了而該使用者不在房間裡,一個MUC服務可以MAY發送一個房間外的 <message/> ; 這消息應該 SHOULD 被從房間發送給該使用者的純JID, 可以 MAY 包含一個 <body/> 元素描述崗位變更, 并且必須 MUST 包含一個狀态碼 101.
- 沒有需求要一個MUC服務将為舊的"groupchat 1.0"使用者提供特别的治療, 例如包含等價于擴充的遵循 '
- 如果服務接收到它之前發送給該使用者的節相關的遞送類錯誤,一個MUC服務應該 SHOULD 移除一個使用者; 遞送相關的錯誤即 <gone/>, <item-not-found/>, <recipient-unavailable/>, <redirect/>, <remote-server-not-found/>, 和 <remote-server-timeout/>.
- 一個MUC服務可以 MAY 選擇在反射出席資訊變更給一個房間的房客們之前,抛棄附加在<presence/> 節上的擴充的出席資訊. 也就是, 一個實作可以 MAY 選擇隻反射該出席資訊節的 <show/>, <status/>, 和 <priority/> 子元素,如 'jabber:client' 名字空間描述的 XML 架構之中, 結果導緻那個在擴充的名字空間中的出席資訊變更 "changes" (例如, gabber:x:music:info) 不被傳遞給房客. 如果一個服務禁止特定的擴充名字空間, 它應該 SHOULD 在本文 允許的通訊章節描述的知名的服務發現節點 'XHTML-IM [XEP-0045#附錄G:備注|32]]. 如果一個服務禁止特定的擴充名字空間, 它應該 SHOULD 在本文 允許的通訊章節描述的知名的服務發現節點 '發現保留的房間昵稱章節定義的協定.
允許的通訊
大家知道, 一個服務 (更準确地說, 一個正确配置的房間)可以 MAY 抛棄一些或所有的擴充的附加在從發送者通過房間反射給所有房客的 <message/> 和 <presence/> 節的名字空間. 如果房間這麼幹, 它應該 SHOULD 允許發送者通過發送 disco#info 查詢知名的服務發現節點 '用戶端
- Jabber用戶端可以 MAY 展示房間角色,通過在一個房間名冊裡為每個角色顯示特定的群. 這将使房客清楚圖形化的知道哪個房客是主持人, 參與者, 和遊客. 無論如何, 這樣一個展示是可選的 OPTIONAL.
- Jabber用戶端可以 MAY 實作多樣化的界面以提供快捷方式 "shortcuts" 給功能,例如修改某人昵稱, 踢人或禁止使用者, 發現一個房客的全JID, 或修改主題. 一個選項包含了類IRC 的指令例如 '/nick', '/kick', '/ban', 和 '/whois'; 另一個是使使用者能用滑鼠右擊房間名冊裡的項目. 所有這些界面形式是可選的 OPTIONAL. 然而, 為友善起見, 下面提供了一個 IRC 指令到 MUC 協定的映射.
IRC指令映射
IRC 用戶端使用大量常用的快捷方式 "shortcut" 指令,以一個斜杠開始, 例如 '/nick' and '/ban'. 下表提供一個 類IRC 指令到 MUC 協定的映射, 用于希望支援類似功能的 Jabber 用戶端.
表10: IRC指令映射
指令 功能 MUC協定 /ban <roomnick> [comment] 在房間裡以房間昵稱禁止使用者(用戶端翻譯房間昵稱為純JID) <iq id='someid' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='outcast' jid='bare-jid-of-user'> <reason>comment</reason> </item> </query> </iq>
/invite <jid> [comment] 以JID邀請使用者到此房間 <message to='[email protected]'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite to='jid'> <reason>comment</reason> </invite> </x> </message>
/join <roomname> [pass] 在服務裡加入房間(房間昵稱同本房間内的昵稱) <presence to='[email protected]/nick'> <x xmlns='http://jabber.org/protocol/muc#user'> <password>pass</password> </x> </presence>
/kick <roomnick> [comment] 以房間昵稱從房間裡踢人 <iq id='someid' to='[email protected]' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item nick='roomnick' role='none'> <reason>comment</reason> </item> </query> </iq>
/msg <roomnick> <foo> 發送私有消息"foo"給房間昵稱 <message to='[email protected]/nick' type='chat'> <body>foo</body> </message>
/nick <newnick> 變更在此房間内的昵稱為"newnick" <presence to='[email protected]/newnick'/>
/part [comment] 退出本房間(一些 IRC 用戶端也支援 /leave) <presence to='[email protected]/nick' type='unavailable'> <status>comment</status> </presence>
/topic <foo> 變更此房間主題為"foo" <message to='[email protected]' type='groupchat'> <subject>foo</subject> </message>
注意: 因為 MUC 房間昵稱遵循stringprep的Resourceprep腳本, 它們被允許包含一個空格字元, 而 IRC 昵稱不允許. 盡管一個給定的用戶端可以 MAY 支援引用字元串用于這個目的 (導緻指令類似 '/ban "king lear" insanity is no defense'), 最常見的引用字元(類似 " 和 ') 也是被Resourceprep允許的 , 進而導緻增加了複雜性和包含空格和引号的房間昵稱中引号的潛在問題. 是以不建議 NOT RECOMMENDED Jabber用戶端支援包含了空格符的房間昵稱的類IRC的快捷方式指令.
注意: 很多Jabber用戶端也實作了 '/me ' 指令,如 The /me Command 33 所述. 這個指令不會導緻任何 MUC 或 IRC 協定的動作是以不顯式在上表中.
XML架構
http://jabber.org/protocol/muc
<?xml version='1.0' encoding='UTF-8'?> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' targetNamespace='http://jabber.org/protocol/muc' xmlns='http://jabber.org/protocol/muc' elementFormDefault='qualified'> <xs:annotation> <xs:documentation> The protocol documented by this schema is defined in XEP-0045: http://www.xmpp.org/extensions/xep-0045.html </xs:documentation> </xs:annotation> <xs:element name='x'> <xs:complexType> <xs:sequence> <xs:element ref='history' minOccurs='0'/> <xs:element name='password' type='xs:string' minOccurs='0'/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name='history'> <xs:complexType> <xs:simpleContent> <xs:extension base='empty'> <xs:attribute name='maxchars' type='xs:int' use='optional'/> <xs:attribute name='maxstanzas' type='xs:int' use='optional'/> <xs:attribute name='seconds' type='xs:int' use='optional'/> <xs:attribute name='since' type='xs:dateTime' use='optional'/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:simpleType name='empty'> <xs:restriction base='xs:string'> <xs:enumeration value=''/> </xs:restriction> </xs:simpleType> </xs:schema>
http://jabber.org/protocol/muc#user
<?xml version='1.0' encoding='UTF-8'?> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' targetNamespace='http://jabber.org/protocol/muc#user' xmlns='http://jabber.org/protocol/muc#user' elementFormDefault='qualified'> <xs:annotation> <xs:documentation> The protocol documented by this schema is defined in XEP-0045: http://www.xmpp.org/extensions/xep-0045.html </xs:documentation> </xs:annotation> <xs:element name='x'> <xs:complexType> <xs:choice minOccurs='0' maxOccurs='unbounded'> <xs:element ref='decline' minOccurs='0'/> <xs:element ref='destroy' minOccurs='0'/> <xs:element ref='invite' minOccurs='0' maxOccurs='unbounded'/> <xs:element ref='item' minOccurs='0'/> <xs:element name='password' type='xs:string' minOccurs='0'/> <xs:element ref='status' minOccurs='0' maxOccurs='unbounded'/> </xs:choice> </xs:complexType> </xs:element> <xs:element name='decline'> <xs:complexType> <xs:sequence> <xs:element ref='reason' minOccurs='0'/> </xs:sequence> <xs:attribute name='from' type='xs:string' use='optional'/> <xs:attribute name='to' type='xs:string' use='optional'/> </xs:complexType> </xs:element> <xs:element name='destroy'> <xs:complexType> <xs:sequence> <xs:element ref='reason' minOccurs='0'/> </xs:sequence> <xs:attribute name='jid' type='xs:string' use='optional'/> </xs:complexType> </xs:element> <xs:element name='invite'> <xs:complexType> <xs:sequence> <xs:element ref='reason' minOccurs='0'/> </xs:sequence> <xs:attribute name='from' type='xs:string' use='optional'/> <xs:attribute name='to' type='xs:string' use='optional'/> </xs:complexType> </xs:element> <xs:element name='item'> <xs:complexType> <xs:sequence> <xs:element ref='actor' minOccurs='0'/> <xs:element ref='reason' minOccurs='0'/> <xs:element ref='continue' minOccurs='0'/> </xs:sequence> <xs:attribute name='affiliation' use='optional'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='admin'/> <xs:enumeration value='member'/> <xs:enumeration value='none'/> <xs:enumeration value='outcast'/> <xs:enumeration value='owner'/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name='jid' type='xs:string' use='optional'/> <xs:attribute name='nick' type='xs:string' use='optional'/> <xs:attribute name='role' use='optional'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='moderator'/> <xs:enumeration value='none'/> <xs:enumeration value='participant'/> <xs:enumeration value='visitor'/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> </xs:element> <xs:element name='actor'> <xs:complexType> <xs:simpleContent> <xs:extension base='empty'> <xs:attribute name='jid' type='xs:string' use='required'/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:element name='continue'> <xs:complexType> <xs:simpleContent> <xs:extension base='empty'> <xs:attribute name='thread' type='xs:string' use='optional'/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:element name='status'> <xs:complexType> <xs:attribute name='code' use='required'> <xs:simpleType> <xs:restriction base='xs:int'> <xs:minInclusive value='100'/> <xs:maxInclusive value='999'/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> </xs:element> <xs:element name='reason' type='xs:string'/> <xs:simpleType name='empty'> <xs:restriction base='xs:string'> <xs:enumeration value=''/> </xs:restriction> </xs:simpleType> </xs:schema>
http://jabber.org/protocol/muc#admin
<?xml version='1.0' encoding='UTF-8'?> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' targetNamespace='http://jabber.org/protocol/muc#admin' xmlns='http://jabber.org/protocol/muc#admin' elementFormDefault='qualified'> <xs:annotation> <xs:documentation> The protocol documented by this schema is defined in XEP-0045: http://www.xmpp.org/extensions/xep-0045.html </xs:documentation> </xs:annotation> <xs:element name='query'> <xs:complexType> <xs:sequence> <xs:element ref='item' maxOccurs='unbounded'/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name='item'> <xs:complexType> <xs:sequence> <xs:element ref='actor' minOccurs='0'/> <xs:element ref='reason' minOccurs='0'/> </xs:sequence> <xs:attribute name='affiliation' use='optional'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='admin'/> <xs:enumeration value='member'/> <xs:enumeration value='none'/> <xs:enumeration value='outcast'/> <xs:enumeration value='owner'/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name='jid' type='xs:string' use='optional'/> <xs:attribute name='nick' type='xs:string' use='optional'/> <xs:attribute name='role' use='optional'> <xs:simpleType> <xs:restriction base='xs:NCName'> <xs:enumeration value='moderator'/> <xs:enumeration value='none'/> <xs:enumeration value='participant'/> <xs:enumeration value='visitor'/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> </xs:element> <xs:element name='actor'> <xs:complexType> <xs:simpleContent> <xs:extension base='empty'> <xs:attribute name='jid' type='xs:string' use='required'/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:element name='reason' type='xs:string'/> <xs:simpleType name='empty'> <xs:restriction base='xs:string'> <xs:enumeration value=''/> </xs:restriction> </xs:simpleType> </xs:schema>
http://jabber.org/protocol/muc#owner
<?xml version='1.0' encoding='UTF-8'?> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' targetNamespace='http://jabber.org/protocol/muc#owner' xmlns='http://jabber.org/protocol/muc#owner' elementFormDefault='qualified'> <xs:annotation> <xs:documentation> The protocol documented by this schema is defined in XEP-0045: http://www.xmpp.org/extensions/xep-0045.html </xs:documentation> </xs:annotation> <xs:import namespace='jabber:x:data' schemaLocation='http://www.xmpp.org/schemas/x-data.xsd'/> <xs:element name='query'> <xs:complexType> <xs:choice xmlns:xdata='jabber:x:data' minOccurs='0'> <xs:element ref='xdata:x'/> <xs:element ref='destroy'/> </xs:choice> </xs:complexType> </xs:element> <xs:element name='destroy'> <xs:complexType> <xs:sequence> <xs:element name='password' type='xs:string' minOccurs='0'/> <xs:element name='reason' type='xs:string' minOccurs='0'/> </xs:sequence> <xs:attribute name='jid' type='xs:string' use='optional'/> </xs:complexType> </xs:element> <xs:simpleType name='empty'> <xs:restriction base='xs:string'> <xs:enumeration value=''/> </xs:restriction> </xs:simpleType> </xs:schema>
http://jabber.org/protocol/muc#unique
<?xml version='1.0' encoding='UTF-8'?> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' targetNamespace='http://jabber.org/protocol/muc#unique' xmlns='http://jabber.org/protocol/muc#unique' elementFormDefault='qualified'> <xs:annotation> <xs:documentation> The protocol documented by this schema is defined in XEP-0045: http://www.xmpp.org/extensions/xep-0045.html </xs:documentation> </xs:annotation> <xs:element name='unique' type='xs:string'/> </xs:schema>
鳴謝
作者感謝以下個人,為他們很多對于本協定草案的幫助性的評論: David Sutton, Peter Millard, Joe Hildebrand, Craig Kaes, Alexey Shchepin, David Waite, Jean-Louis Seguineau, Jacek Konieczny, Gaston Dombiak, 以及其他在 [email protected] 會議室和在 Standards 郵件清單裡的人.附錄
附錄A:文檔資訊
系列:XEP
序号:0045
釋出者:XMPP标準基金會
狀态:草案
類型:标準跟蹤
版本:1.24
最後更新:2008-07-16
準許機構:XMPP理事會
依賴标準:XMPP Core, XMPP IM, XEP-0004, XEP-0030, XEP-0068, XEP-0082, XEP-0128
替代标準:無
被替代标準:無
縮略名:muc
muc名字空間的XML方案: <http://www.xmpp.org/schemas/muc.xsd>
muc#admin名字空間的XML方案: <http://www.xmpp.org/schemas/muc-admin.xsd>
muc#owner名字空間的XML方案: <http://www.xmpp.org/schemas/muc-owner.xsd>
muc#unique名字空間的XML方案: <http://www.xmpp.org/schemas/muc-unique.xsd>
muc#user名字空間的XML方案: <http://www.xmpp.org/schemas/muc-user.xsd>
系統資料庫: <http://www.xmpp.org/registrar/muc.html>
原文控制: HTML RSS
本文的其它格式: XML PDF
附錄B:作者資訊
Peter Saint-Andre
Email: [email protected]
JabberID: [email protected]
URI: https://stpeter.im/
附錄C:法律通告
版權
XMPP擴充協定的版權(1999-2008)歸XMPP标準化基金會(XSF)所有.
權限
特此授權,費用全免,對任何獲得本協定副本的人,對使用本協定沒有限制,包括不限制在軟體程式中實作本協定,不限制在網絡服務中布署本協定,不限制拷貝,修改,合并,發行,翻譯,分發,轉授,或銷售本協定的副本,被允許使用本協定做了以上工作的人士,應接受前述的版權聲明和本許可通知并且必須包含在所有的副本或實質性部分的規格中.除非單獨的許可,被重新分發的修改工作,不得含有關于作者,标題,編号,或出版者的規格的誤導性資料,并不得宣稱修改工作是由本文的作者,作者所屬的任何組織或項目,或XMPP标準基金會簽注。
免責聲明'
## 特别注意:本協定是提供的“原樣”的基礎,沒有擔保或任何形式的條件,明示或暗示,包括,但不限于任何擔保或關于名稱,非侵權性,适銷性或适合作某一特定目的的條件. ##
責任限制
在任何情況下以及沒有任何法律規定時,不論是侵權行為(包括疏忽),合同或其它方面,除非根據适用法律的要求(如蓄意和有嚴重疏忽行為)或以書面形式同意,XMPP标準基金會或任何作者不對本協定所造成的損失承擔責任,包括任何直接,間接,特殊,偶發,或任何從本協定出,入,連接配接的字元産生的或實作,布署或其他對本協定的使用導緻的相應的損害賠償(包括但不限于善意的損失,停止作業,電腦失靈或故障,或任何和所有其他商業損害或損失) ,即使XMPP标準基金會或作者已被告知此類損害的可能性。
知識産權的一緻性
XMPP擴充協定完全遵守XSF的知識産權政策(可在<http://www.xmpp.org/extensions/ipr-policy.shtml>找到副本或寫信給XMPP标準基金會, 1899 Wynkoop Street, Suite 600, Denver, CO 80202 USA).
附錄D:和XMPP的關系
可擴充的消息和出席資訊協定 (XMPP) 定義于 XMPP Core (RFC 3920) 和 XMPP IM (RFC 3921) 規範裡,由 XMPP标準基金會貢獻到由依據RFC 2026成立的網際網路工程人物組管理的網際網路标準流程 Internet Standards Process. 本文定義的任何協定已在網際網路标準流程之外開發,并且被了解為 XMPP 的擴充而不是一個XMPP本身的演化, 開發, 或修改.附錄E:讨論地點
主要的XMPP擴充協定讨論地點是 <[email protected]> 讨論清單.
在 xmpp.org 的其它讨論清單中的讨論可能也有合适的; 所有的清單見 <http://xmpp.org/about/discuss.shtml> .
勘誤表可以發送郵件到 <[email protected]>.
附錄F:需求一緻性
以下用于本文的需求關鍵字的解釋見于 RFC 2119: "MUST", "SHALL", "REQUIRED"; "MUST NOT", "SHALL NOT"; "SHOULD", "RECOMMENDED"; "SHOULD NOT", "NOT RECOMMENDED"; "MAY", "OPTIONAL".附錄G:備注
- RFC 1459: Internet Relay Chat <http://tools.ietf.org/html/rfc1459>.
- RFC 2810: Internet Relay Chat: Architecture <http://tools.ietf.org/html/rfc2810>.
- RFC 2811: Internet Relay Chat: Channel Management <http://tools.ietf.org/html/rfc2811>.
- RFC 2812: Internet Relay Chat: Client Protocol <http://tools.ietf.org/html/rfc2812>.
- RFC 2813: Internet Relay Chat: Server Protocol <http://tools.ietf.org/html/rfc2813>.
- XEP-0133: Service Administration <http://xmpp.org/extensions/xep-0133.html>.
- XEP-0030: Service Discovery <http://xmpp.org/extensions/xep-0030.html>.
- XEP-0059: Result Set Management <http://xmpp.org/extensions/xep-0059.html>.
- XEP-0128: Service Discovery Extensions <http://xmpp.org/extensions/xep-0128.html>.
- RFC 3920: 可擴充的消息和出席資訊協定 (XMPP): Core <http://tools.ietf.org/html/rfc3920>.
- XEP-0203: Delayed Delivery <http://xmpp.org/extensions/xep-0203.html>.
- XEP-0091: Legacy Delayed Delivery <http://xmpp.org/extensions/xep-0091.html>.
- XEP-0082: XMPP Date and Time Profiles <http://xmpp.org/extensions/xep-0082.html>.
- RFC 3921: 可擴充的消息和出席資訊協定 (XMPP): Instant Messaging and Presence <http://tools.ietf.org/html/rfc3921>.
- XEP-0249: Direct MUC Invitations <http://xmpp.org/extensions/xep-0249.html>.
- XEP-0077: In-Band Registration <http://xmpp.org/extensions/xep-0077.html>.
- XEP-0004: Data Forms <http://xmpp.org/extensions/xep-0004.html>.
- 一些評論者抱怨公開房間的所有者和管理者存在潛在的濫用; 很不幸的, 能力越大責任越大.
- XEP-0050: Ad-Hoc Commands <http://xmpp.org/extensions/xep-0050.html>.
- XEP-0060: Publish-Subscribe <http://xmpp.org/extensions/xep-0060.html>.
- 這和房間配置的行為不同, 這裡 'muc#roomconfig_roomowners' 字段指定房間所有者的完整清單, 不是delta.
- 這和房間配置的行為不同, 這裡 'muc#roomconfig_roomadmins' 字段指定房間管理眼的完整清單, 不是delta.
- XEP-0086: Error Condition Mappings <http://xmpp.org/extensions/xep-0086.html>.
- RFC 2616: Hypertext Transport Protocol -- HTTP/1.1 <http://tools.ietf.org/html/rfc2616>.
- RFC 1893: Enhanced Mail System Status Codes <http://tools.ietf.org/html/rfc1893>.
- 網際網路編号配置設定機構 (IANA) 是用于網際網路協定的唯一性參數值配置設定的核心協調者, 例如号碼和URI計劃. 更多資訊, 見 <http://www.iana.org/>.
- XMPP登記員 XMPP Registrar 維護着一個保留的協定名字空間以及用于由XMPP标準基金會準許的XMPP擴充協定的上下文參數的注冊項的清單. 更多資訊, 見 <http://xmpp.org/registrar/>.
- XEP-0068: Field Data Standardization for Data Forms <http://xmpp.org/extensions/xep-0068.html>.
- XEP-0147: XMPP URI Query Components <http://xmpp.org/extensions/xep-0147.html>.
- XEP-0022: Message Events <http://xmpp.org/extensions/xep-0022.html>.
- XEP-0085: Chat State Notifications <http://xmpp.org/extensions/xep-0085.html>.
- XEP-0071: XHTML-IM <http://xmpp.org/extensions/xep-0071.html>.
- XEP-0245: The /me Command <http://xmpp.org/extensions/xep-0245.html>.
附錄H: 修訂曆史
注意: 本協定的舊版本可能在 http://xmpp.org/extensions/attic/ 還可用
版本 1.24 (2008-07-16)
增加了更多原因reason元素的例子; 移除了關于黑名單包含的昵稱部分; 增加了拒絕服務注意事項.
(psa)
版本 1.23 (2008-01-14)
- 定義了 getmemberlist 房間配置選項
- 增加了直接邀請協定
- 修正了當房間滿的時候房間承認所有者/管理者的邏輯
- 定義了和LDAP群關聯的服務發現擴充字段
- 指定了房間配置字段能被列入擴充的房間資訊之中
- 指定了消息格式用于使用者不在房間時的崗位變更
- 增加了例子展示結果集管理
- 推薦出席資訊錯誤中包含的MUC子元素
- 為一對一聊天和多使用者聊天的連續性描述了ThreadID的使用, 包括在邀請中為 continue 元素定義 thread 屬性.
(psa)
版本 1.22 (2007-04-10)
更新了延遲消息遞送以反映 XEP-0203 演化到草案和 XEP-0091 的過時.
(psa)
版本 1.21 (2006-09-13)
- 澄清了MUC擴充的介入,在房間加入/建立請求觸發資料表單流但沒有MUC擴充可導緻自動房間建立以向後相容舊的 groupchat 1.0 協定.
- 指定昵稱變更時如果昵稱被鎖定則傳回 <not-acceptable/> 錯誤.
- 要求用戶端在進入房間之前發現房間配置并指定相關的安全事項, 包括使用隐私相關的狀态碼 170, 171, 172, 173, 和 174.
- 指定在房間配置選項不能被執行或違反服務政策時使用 <not-acceptable/> 錯誤.
- 強制要求房間昵稱不能隻包含空格.
- 移除所有服務發現用例到專用章節.
- 修改 urn:xmpp:delay 支援從 SHOULD 改為 MUST.
- 澄清 _whois 房間配置選項定義房間類型.
- 定義 XEP-0128 房間資訊字段用于讨論記錄, 關聯的 pubsub 節點, 以及聯系人 JID.
- 指出修改角色到主持人導緻崗位變更為管理者或所有者成為推薦的, 而不是必需的.
- 增加了國際化事項中關于資料表單的本地化的部分.
- 指出實作可以持久化角色括月整個通路并且應該在被主持的房間裡這樣做.
- 增加了協定和服務發現特性用于在建立房間之前請求唯一的房間名.
- 更多澄清保留的房間昵稱和昵稱鎖定的性質.
- 定義資料表單用于請求發言權和準許發言申請.
- 增加了多個邀請的例子用于XMPP URI.
- 澄清了出席資訊,讨論曆史的順序, 等等.
- 增加了狀态碼用于房客擁有的房間昵稱, 服務修改的房間昵稱, 并警告房間讨論被公開記錄.
- 澄清關于房間記錄和非匿名房間的隐私和匿名事項.
(psa)
版本 1.20 (2005-09-08)
同意了踢人和禁止使用者的能力, 并定義了一個使用者不能被一個比自己崗位低的主持人或管理者踢或禁止.
(psa)
版本 1.19 (2005-04-21)
定義了怎樣發送并發多邀請; 糾正了一些和崗位變更狀态一緻性的錯誤; 修改了消息事件禁令表單從 MUST NOT 到 SHOULD NOT; 修正了和 #traffic disco 節點相關的錯誤處理; 允許了 <password/> 作為<destroy/>的一個子元素; 修改了最大使用者數錯誤從 <not-allowed/> 到 <service-unavailable/>; 指定了 maxchars 屬性的字元數是指完整的 XML 節; 為 FORM_TYPEs;增加了 disco 特性 為狀态碼定義了系統資料庫; 為遵守協定分開了建立即時房間的用例; 調整了 XML 架構以反映之前的修改; 重寫了緒論; 澄清了小的文本錯誤.
(psa)
Version 1.18 (2004-11-02)
Corrected several errors in the affiliation state chart and in the examples (wrong FORM_TYPE values); mentioned /me command. (psa) Version 1.17 (2004-10-04)
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 fromhttp://jabber.org/protocol/muc#user to http://jabber.org/protocol/muc#register; modified FORM_TYPE for room configuration fromhttp://jabber.org/protocol/muc#owner to http://jabber.org/protocol/muc#roomconfig. (psa) Version 1.16 (2004-06-30)
Added example and registry submission for service discovery extension. (psa) Version 1.15 (2004-06-24)
Removed jabber:iq:browse references; clarified order of presence stanzas sent to new occupant on entering room; specified format of in-room messages (type='groupchat', from='[email protected]'); 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. (psa) Version 1.14 (2004-05-03)
Corrected discovery of registered roomnicks; added note about error to return if nicks are locked down. (psa) Version 1.13 (2004-03-31)
Fixed an error in the muc#user schema. (psa) Version 1.12 (2004-03-01)
Corrected a few errors in the examples; added IQ results in order to clarify workflows. (psa) Version 1.11 (2004-02-05)
Clarified JID matching rules (same as for privacy lists in XMPP IM). (psa) Version 1.10 (2004-01-07)
Added XMPP error handling; fully specified all conformance terms. (psa) Version 1.9 (2003-12-14)
Removed protocol for requesting voice in a moderated room (should be performed using Ad-Hoc Commands). (psa) Version 1.8 (2003-12-04)
Added protocol for requesting voice in a moderated room; added (informational) mapping of IRC commands to MUC protocols. (psa) Version 1.7 (2003-10-21)
Added room configuration option for restricting presence broadcast to certain roles. (psa) Version 1.6 (2003-10-03)
Added history management protocol on entering a room. (psa) Version 1.5 (2003-09-11)
Specified that ban occurs by JID, not roomnick; allowed privileged users to send messages to the room even if not present in the room; added note that service should remove occupant if a delivery-related stanza error occurs; enabled user to disco the room in order to discover registered roomnick; specified that "banning" by domain or regex is a service-level configuration matter and therefore out of scope for MUC; specified that role should be decremented as appropriate if affiliation is lowered; added some clarifying text to room creation workflow; added implementation note about sending an out-of-band message if a user's affiliation changes while the user is not in the room; fixed stringprep references (room nicks use Resourceprep); clarified relationship between Room ID (i.e., node identifier of Room JID, which may be opaque) and natural-language Room Name; specified Field Standardization profile per XEP-0068; defined XMPP Registrar submissions; added schema locations. (psa) Version 1.4 (2003-02-16)
Added XML schemas. (psa) Version 1.3 (2003-02-11)
Added reference to nodeprep Internet-Draft. (psa) Version 1.2 (2003-01-30)
Commented out revision history prior to version 1.0 (too long); clarified business rules regarding when nicks, full JIDs, and bare JIDs are used in reference to roles and affiliations; consistently specified that extended presence information in the muc#user namespace must include the full JID as the value of the 'jid' attribute in all cases; cleaned up text and examples throughout; added open issue regarding syntax of room nicknames. (psa) Version 1.1 (2002-12-16)
Added protocol for declining an invitation; replaced <created/> element with status code 201; modified the destroy room protocol so that <destroy/> is a child of <query/>; clarified usage of 'nick' attribute when adding members; prohibited use of message events. (psa) Version 1.0 (2002-11-21)
Per a vote of the Jabber Council, revision 0.23 was advanced to Draft on 2002-11-21. (For earlier revision history, refer to XML source.) (psa) Version 0.23 (2002-11-06)
Added examples for disco#items queries sent to a room; prohibited 'type' attribute on invite messages sent from client to room; added dependencies on browse and disco; changed 'room user' to 'occupant'; fixed many small errors throughout. (psa) Version 0.22 (2002-11-04)
Added example for disco#items; added support for cancellation of room configuration using type='cancel' from XEP-0004; noted 403 error for invites sent by non-admins in members-only room. (psa) Version 0.21 (2002-11-01)
Clarified several small ambiguities; made <body/> optional on invites sent from the service to the invitee; added error scenarios for changing nickname and for destroying the room; specified that the service must return the full member list for a members-only room (not only the members in the room); updated the disco examples to track protocol changes. (psa) Version 0.20 (2002-10-29)
Specified that messages sent to change the room subject must be of type "groupchat"; updated the legal notice to conform to the XSF IPR policy. (psa) Version 0.19 (2002-10-28)
Added ability to create an instant room within MUC (not by using gc-1.0 protocol); cleaned up disco examples. (psa) Version 0.18 (2002-10-27)
Added experimental support for disco; added sections for security, IANA, and JANA considerations; corrected typographical errors; cleaned up some DocBook formatting. (psa) Version 0.17 (2002-10-23)
Added the optional <actor/> element (with 'jid' attribute) to <item/> elements inside presence stanzas of type "unavailable" that are sent to users who are kicked or banned, as well as within IQs for tracking purposes; reverted all list editing use cases (ban, voice, member, moderator, admin, owner) to use of MUC format rather than 'jabber:x:data' namespace; added several guidelines regarding generation and handling of XML stanzas; cleaned up the change room subject use case; changed several ambiguous uses of 'would', 'can', and 'will' to 'should', 'may', or 'must'; fixed several small errors in the text, examples, and DTDs. (psa) Version 0.16 (2002-10-20)
Added the <item/> element to presence stanzas of type "unavailable" in order to improve the tracking of user states in the room; consolidated <invitee/> and <invitor/> elements into an <invite/> element with 'from' and 'to' attributes; made <reason/> element always a child of <item/> or <invite/> in the muc#user namespace; moved the alternate room location in room destruction to a 'jid' attribute of the <alt/> element; further specified several error messages; disallowed simultaneous modifications of both affiliations and roles by a moderator or admin; added several more rules regarding handling of XML stanzas; added use cases for granting and revoking administrative privileges; adjusted DTD to track all changes. (psa) Version 0.15 (2002-10-18)
Fully incorporated the change to affiliations + roles; moved a number of admin use cases to a new section for moderator use cases; added participant use case for requesting membership; added admin use cases for adding members, removing members, granting and revoking moderator privileges, and modifying the moderator list; organized the sections in a more logical manner. (psa) Version 0.14 (2002-10-17)
Significantly modified the privileges model by distinguishing between in-room "roles" and long-lived "affiliations"; specified the privileges of the various roles and affiliations; included state transition charts for both roles and affiliations; removed use of MUC protocol for editing ban, voice, and admin lists (but not for the actions of banning users and granting/revoking voice); added delivery rule regarding IQ stanzas; changed kick so that the action is based on changing the role to "none". (psa) Version 0.13 (2002-10-16)
Corrected the change nickname examples (newnick sent on unavailable, no nick sent on available). (psa) Version 0.12 (2002-10-16)
Removed SHA1 passwords; specified that room shall add passwords on invitations to password-protected rooms (not supplied by invitor). (psa) Version 0.11 (2002-10-16)
Changed 'participant' to 'room user' and 'discussant' to 'participant'; clarified presence rule about client generation of extended presence information; added role of 'none'. (psa) Version 0.10 (2002-10-15)
Fixed extended presence on entering or creating a room (plain '...muc' with no fragment); harmonized #user with #admin regarding the use of the <item/> element and associated attributes (jid, nick, etc.), and added 'role' attribute; modified management of voice, ban, admin, and member lists to use <query/> wrapper and new <item/> structure; changed the 'member' role to 'discussant', added 'outcast' role for banned users, and added new 'member' role to enable management of member lists; changed invitation-only rooms to members-only rooms and made appropriate adjustments to apply member lists to both members-only rooms and open rooms; modified nickname change protocol slightly to send the old nickname in the unavailable presence and the new nickname in the available presence; removed prohibition on members-only rooms that are password-protected; removed the <query/> wrapper for the <destroy/> element; updated the DTDs. (psa) Version 0.9 (2002-10-13)
Added extended presence ('...#user') on entering a room for 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. (psa) Version 0.8 (2002-10-10)
Made further changes to the room creation workflow (finally correct); removed feature discovery use case (this needs to be addressed by a real service discovery protocol!); added ability for room owners to edit the admin list; removed <body/> from invitations generated by the service; removed messages sent to kicked and banned users (handled by unavailable presence with status code); added a number of implementation notes; converted all examples to Shakespeare style. (psa) Version 0.7.6 (2002-10-09)
Fixed the room creation workflow; changed some terminology ("join" to "enter" and "leave" to "exit"). (psa) Version 0.7.5 (2002-10-08)
Specified and improved the handling of invitation-only rooms. In particular, added the ability for room admins to edit the invitation list and added a configuration option that limits the ability to send invitations to room admins only. (psa) Version 0.7.4 (2002-10-07)
Changed namespaces from http://jabber.org/protocol/muc/owner etc. to http://jabber.org/protocol/muc#owner etc. per Jabber Council discussion. (psa) Version 0.7.3 (2002-10-07)
Changed namespaces to HTTP URIs; left role handling up to the implementation; further clarified presence rules. (psa) Version 0.7.2 (2002-10-06)
Disallowed kicking, banning, and revoking voice with respect to room admins and room owners; replaced <x/> with <query/> in the Discovering Room Features and Destroying a Room use cases; corrected some small errors and made many clarifications throughout. (psa) Version 0.7.1 (2002-10-04)
Removed <whois/> command (unnecessary since participants with appropriate privileges receive the full JID of all participants in presence stanzas); completed many small fixes throughout. (psa) Version 0.7 (2002-10-03)
More clearly delineated participant roles and defined the hierarchy thereof (owner, admin, member, visitor); replaced <voice/> element in extended presence with <item role='member'/>; changed initial room configuration to use IQ rather than message; adjusted presence rules (especially regarding extended presence information); cleaned up examples throughout; updated DTD to track changes. (psa) Version 0.6 (2002-09-21)
More clearly defined the scope; removed fully anonymous rooms; changed meaning of semi-anonymous rooms and of non-anonymous rooms; added mechanism for notification of full JIDs in non-anonymous rooms; replaced the <admin/> element in extended presence with a <role/> element (more extensible); changed room passwords to cleartext; added status codes for various messages received from the service; added lists of valid error and status codes associated with the '