修改主持人列表
管理员可能希望修改主持人列表. 为此, 管理员首先通过请求房间内所有角色为'moderator'的用户来请求主持人列表.
例子 136. 管理员请求主持人列表
<iq from='crone1@shakespeare.lit/desktop' id='mod3' to='darkcave@chat.shakespeare.lit' 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='darkcave@chat.shakespeare.lit' id='mod3' to='crone1@shakespeare.lit/desktop' type='result'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='member' jid='hag66@shakespeare.lit/pda' nick='thirdwitch' role='moderator'/> </query> </iq>
管理员可以 MAY 接着修改主持人列表. 为此, 管理员必须 MUST发送修改的条目(即, 仅"delta") 给服务; 每个条目必须 MUST 包含 'jid' 属性和'role' 属性(通常值设为 "member" 或 "participant") 但不应该 SHOULD NOT 包含 'nick' 属性并且不能 MUST NOT 包含 'affiliation' 属性(它被用于管理类似管理员这样的岗位而不是主持人这样的角色):
例子 138. 管理员发送修改了的主持人列表给服务
<iq from='crone1@shakespeare.lit/desktop' id='mod4' to='darkcave@chat.shakespeare.lit' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item jid='hag66@shakespeare.lit/pda' role='participant'/> <item jid='hecate@shakespeare.lit/broom' role='moderator'/> </query> </iq>
服务必须 MUST 修改主持人列表并通知管理员成功了:
例子 139. 服务通知管理员成功了
<iq from='darkcave@chat.shakespeare.lit' id='mod4' to='crone1@shakespeare.lit/desktop' type='result'/>
服务必须 MUST 随后以所有受影响的用户发送更新的出席信息给所有的房客, 支出主持人权限的变更,通过发送前面用例所述的适当的扩展出席信息.
显然, 房间所有者或房间管理员的主持人权限不能被撤销. 如果一个房间管理员尝试通过修改主持人列表来撤销这类用户的主持人权限, 服务必须 MUST 拒绝请求并返回一个 <not-allowed/> 错误给发送者:
例子 140. 服务在用户尝试撤销管理员或所有者的主持人权限时返回错误
<iq from='darkcave@chat.shakespeare.lit' id='modtest' to='hag66@shakespeare.lit/pda' type='error'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item jid='hecate@shakespeare.lit/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='darkcave@chat.shakespeare.lit' id='approve' to='crone1@shakespeare.lit/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>hag66@witchesonline</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 Commands 19来接收注册申请列表,就像 Publish-Subscribe 20里所做的一样) 超出了本文的范围.
所有者用例
每个房间必须 MUST 至少有一个所有者, 而所有者(或一个成功者)在一个房间的生命周期里是这个房间长期存在的属性(例如, 所有者在退出一个持久性的房间时不会失去所有权). 本文假定(初始的) 房间所有者是那个新建了该房间的用户并且有一个房间所有者有权修改房间配置选项的定义,例如房间类型. 理想情况下, 房间所有者不仅能指定房间类型(密码保护的, 仅限会员的, 等等) 而且包括如本文的 [XEP-0045#需求|需求]章节所述的房间特定属性. 另外, 如果所有者能指定其他所有者们的JID也是不错的, 但那将取决于具体实现.
为了让配置选项更加广泛提供必要的伸缩性, 房间配置将使用 Data Forms (XEP-0004), 通过使用由 'http://jabber.org/protocol/muc' 名字空间触发. 也就是, 如果一个实体在它请求加入房间的 join/request 里不包含 MUC 名字空间, 那么服务将立刻新建房间,在新建房间之前不等待通过数据表格进行配置(这保证了和旧的"groupchat 1.0"协议的向后兼容); 无论如何, 如果房间的 join/create 请求包含了 MUC 扩展, 那么服务在新建和解锁该房间之前将通过数据表格请求配置.
注意: 以下展示的配置选项列出了本文的需求章节的所有特性和房间类型; 无论如何, 实际的配置选项和表格布局将取决于实现和具体的布署. 而且, 这些只是例子,不代表这些就是房间可以拥有的所有允许或需要的配置选项. 一个特定的实现或布署可以 MAY 选择提供额外的配置选项(敏感词过滤, 设置房间的缺省语言, 消息记录, 等等), 这就是为什么在这里使用 'jabber:x:data' 协议是很有价值的.
新建房间
一般注意事项
新建房间的权限可以 MAY 限制在特定的用户群或可以 MAY 保留给一个服务级别的管理员. 如果访问被拒绝而一个用户试图新建一个房间, 服务必须MUST 返回一个 <not-allowed/> 错误:
例子 142. 服务通知用户不能新建房间
<presence from='darkcave@chat.shakespeare.lit/thirdwitch' to='hag66@shakespeare.lit/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 发送出席信息到 <room@service/nick> 并声明他或她对MUC协议的支持,通过包含一个扩展的出席信息,并包含在一个空的满足'http://jabber.org/protocol/muc'名字空间的 <x/> 子元素里(注意这里不包含 '#owner' 或 '#user' 后缀).
- 如果用户被允许新建房间并且房间还不存在, 服务必须 MUST 根据一些缺省配置新建此房间, 指定请求的用户成为初始的房间拥有者, 并增加这个拥有者到该房间但不允许任何别的用户进入该房间(有效地锁定 "locking"该房间). 从房间发送由所有者收到的初始的出席信息节必须 MUST 包含扩展的出席信息以指出该用户的状态为一个所有者并承认房间已经被创建了(通过状态码 201) 并等待配置.
- 如果初始的房间所有者想新建和配置一个保留房间, 房间所有者必须 MUST 接着请求一个配置,通过发送类型为"get"的IQ节并包含一个空的满足'http://jabber.org/protocol/muc#owner'名字空间的<query/>元素给该房间 ,然后完成第4和第5步. 如果房间所有者喜欢新建一个即时房间, 该房间所有者必须 MUST 发送一个遵循'http://jabber.org/protocol/muc#owner'名字空间的 query 元素并包含一个遵循 'jabber:x:data' 名字空间的空的类型为 "submit" 的 <x/> 元素, 然后跳到第6步.
- 如果房间所有者请求了一个配置表格, 服务必须 MUST 发送一个包含配置表格并遵循 'jabber:x:data'名字空间的 IQ 给房间拥有者. 如果没有配置选项可用, 房间必须 MUST 返回一个空的 query 元素给房间所有者.
- 初始的房间所有者应该 SHOULD 为该房间提供一个开始的配置(或接受缺省配置),通过发送"set"类型并包含完整的配置表格的 IQ . 另外, 房间所有者可以 MAY 取消配置过程. (实现可以 MAY 设置一个初始化配置的超时, 这样如果房间所有者再给定的超时时间内不配置房间, 房间所有者就被假定已经接受了缺省得配置或取消了配置过程.)
- 一旦服务从初始房间所有者接收了完整的配置表格(或接收到了一个即时房间的请求), 服务必须 MUST 解锁 "unlock" 这个房间 (即, 允许其他用户进入此房间) 并发送"result"类型的 IQ 给房间所有者. 如果服务接收到了取消(指令), 它必须 MUST 销毁这个房间.
以下例子展示了这个协议流程.
首先, Jabber用户必须 MUST 发送出席信息给房间, 包含空的 <x/> 元素,遵循 'http://jabber.org/protocol/muc' 名字空间(当他寻求进入一个房间时也发送和这同样的节).
例子 143. Jabber用户新建一个房间并声明对多用户聊天的支持
<presence from='crone1@shakespeare.lit/desktop' to='darkcave@chat.shakespeare.lit/firstwitch'> <x xmlns='http://jabber.org/protocol/muc'/> </presence>
如果该房间不存在, 服务应该 SHOULD 新建这个房间(取决于关于新建房间的本地策略), 指定发出请求的用户的纯JID成为所有者, 添加这个所有者到房间, 并通过发送以下格式的出席信息节承认房间新建成功:
例子 144. 服务承认房间新建成功
<presence from='darkcave@chat.shakespeare.lit/firstwitch' to='crone1@shakespeare.lit/desktop'> <x xmlns='http://jabber.org/protocol/muc#user'> <item affiliation='owner' role='moderator'/> <status code='110'/> <status code='201'/> </x> </presence>
接收到该房间已经创建的通知之后, 房间所有者需要决定是否接受缺省的房间配置(即, 新建一个即时房间 "instant room") 还是做一些不同于缺省房间设置的配置 (即, 新建一个保留房间"reserved room"). 完成这两个用例的协议流程展示如下.
注意: 如果如上的发送到一个不存在的房间里的出席信息节没有包含一个遵循 'http://jabber.org/protocol/muc'名字空间的 <x/> 元素, 服务应该SHOULD 立刻新建一个缺省的房间(即, 它必须 MUST 假定客户端支持 "groupchat 1.0" 而不是 Multi-User Chat, 所以在等待房间创建者决定是创建即时房间还是保留房间的时候,它不能 MUST NOT 锁定这个房间).
新建即时房间
如果初始的房间所有者想接受缺省的房间配置(即, 新建一个即时房间"instant room"), 房间所有者必须 MUST 拒绝初始配置表格,通过发送一个 IQ set 给 <room@service> 本身,包含一个遵循'http://jabber.org/protocol/muc#owner'名字空间的 <query/> 元素, 这里 <query/> 的唯一子元素是一个空的遵循'jabber:x:data'名字空间的 <x/> 元素并且拥有一个 'type'属性值为 "submit":
例子 145. 所有者请求即时房间
<iq from='crone1@shakespeare.lit/desktop' id='create1' to='darkcave@chat.shakespeare.lit' type='set'> <query xmlns='http://jabber.org/protocol/muc#owner'> <x xmlns='jabber:x:data' type='submit'/> </query> </iq>
服务必须 MUST 接着解锁该房间并允许其他实体加入它.
新建保留房间
如果初始的房间所有者想新建并配置一个保留房间, 这个房间所有者必须 MUST 请求初始配置表格,通过发送一个 IQ get 给 <room@service> 本身,包含一个空的遵循 'http://jabber.org/protocol/muc#owner' 名字空间的 <query/> 元素 :
例子 146. 所有者请求配置表单
<iq from='crone1@shakespeare.lit/desktop' id='create1' to='darkcave@chat.shakespeare.lit' type='get'> <query xmlns='http://jabber.org/protocol/muc#owner'/> </iq>
如果房间还不存在, 服务必须 MUST 返回一个初始的房间配置表单给该用户. (注意: 以下例子展示一个配置选项的典型例子. 已登记用于房间创建和配置的所有 x:data 字段列表由 XMPP Registrar 维护; 参见本文的 XMPP注册项事项 章节.)
例子 147. 服务发送配置表单
<iq from='darkcave@chat.shakespeare.lit' id='create1' to='crone1@shakespeare.lit/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 darkcave@macbeth 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='darkcave@chat.shakespeare.lit' id='create1' to='crone1@shakespeare.lit/desktop' type='result'> <query xmlns='http://jabber.org/protocol/muc#owner'/> </iq>
房间所有者应该 SHOULD 接着填好表单并提交给服务.
例子 149. 所有者提交配置表单
<iq from='crone1@shakespeare.lit/desktop' id='create2' to='darkcave@chat.shakespeare.lit' 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>wiccarocks@shakespeare.lit</value> <value>hecate@shakespeare.lit</value> </field> </x> </query> </iq>
如果房间创建成功, 服务必须 MUST 通知新的房间所有者成功了:
例子 150. 服务通知新房间所有者成功
<iq from='darkcave@chat.shakespeare.lit' id='create2' to='crone1@shakespeare.lit/desktop' type='result'/>
如果因为指定的房间配置违反了一个或多个服务策略而导致房间创建失败 (例如, 因为密码保护房间的密码为空), 服务必须 MUST 返回一个 <not-acceptable/> 错误.
例子 151. 服务通知所有者请求的配置选项不被接受
<iq from='darkcave@chat.shakespeare.lit' id='create2' to='crone1@shakespeare.lit/desktop' type='error'> <error type='modify'> <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
另一方面, 房间所有者可以 MAY 取消配置过程:
例子 152. 所有者取消初始的配置
<iq from='crone1@shakespeare.lit/desktop' id='create2' to='darkcave@chat.shakespeare.lit' type='set'> <query xmlns='http://jabber.org/protocol/muc#owner'> <x xmlns='jabber:x:data' type='cancel'/> </query> </iq>
如果房间所有者取消了初始的房间配置, 服务应该 SHOULD 销毁房间, 确保发送不可用出席信息给房间所有者 (详见 "销毁房间" 用例).
如果房间所有者在提交表单之前因为任何原因下线了(例如, 失去连接), 服务将接收到一个类型为 "unavailable" 的出席信息节,从所有者到所有者的 <room@service/nick> 或到 <room@service> (或两者). 服务必须 MUST 接着销毁这个房间, 发送一个 "unavailable" 类型的出席信息节,从房间到所有者,包含一个 <destroy/> 元素以及 reason (子元素)(如果提供了) ,参见本文的 销毁房间章节.
申请唯一房间名
在一些场合 (例如, 当 把一对一聊天转为会议), 房间创建者可能想在尝试新建房间之前请求一个唯一的房间名 (例如, 避免可能的房间冲突). 为此, 服务可以 MAY 如本章所述支持这个特性. (如果服务支持这个特性, 它必须 MUST 在对服务发现信息请求应答时返回一个 "http://jabber.org/protocol/muc#unique" 特性.)
房间创建者通过发送一个 IQ-get 给服务本身来请求唯一房间名, 这个IQ节中包含一个空的 <unique/> 元素,遵循 'http://jabber.org/protocol/muc#unique' 名字空间:
例子 153. 实体请求唯一房间名
<iq from='crone1@shakespeare.lit/desktop' id='unique1' to='chat.shakespeare.lit' type='get'> <unique xmlns='http://jabber.org/protocol/muc#unique'/> </iq>
如果服务支持这个特性, 它应该 SHOULD 以 XML 字符数据的方式返回一个唯一房间名,包含一个 <unique/> 元素 (但不创建该房间):
例子 154. 服务返回唯一房间名
<iq from='chat.shakespeare.lit' id='unique1' to='crone1@shakespeare.lit/desktop' type='result'> <unique xmlns='http://jabber.org/protocol/muc#unique'> 6d9423a55f499b29ad20bf7b2bdea4f4b885ead1 </unique> </iq>
服务可以 MAY 拒绝返回一个唯一房间名给一个没有资格创建房间的实体, 或那些发送请求唯一房间名过多次数的实体, 等等.
服务可以 MAY 使用算法保证房间名的创建在服务上下文中是唯一的 (例如, 对发出请求的JID,datetime,和random salt的SHA-1 哈希运算).
房间创建者将接着使用 XML 字符数据 <unique/> 元素作为它请求的房间JID的节点标识符(ID):
例子 155. 所有者以唯一名创建房间
<presence from='crone1@shakespeare.lit/desktop' to='6d9423a55f499b29ad20bf7b2bdea4f4b885ead1@chat.shakespeare.lit/firstwitch'> <x xmlns='http://jabber.org/protocol/muc'/> </presence>
随后的房间配置
在指定房间的初始配置之后的任何时间, 房间所有者可能想修改房间配置. 为此, 房间所有者必须 MUST 向房间发出一个新的配置表单请求,通过发送一个 IQ 到 <room@service> ,包含一个空的 <query/> 元素,遵循 'http://jabber.org/protocol/muc#owner' 名字空间.
例子 156. 所有者请求配置表单
<iq from='crone1@shakespeare.lit/desktop' id='config1' to='darkcave@chat.shakespeare.lit' type='get'> <query xmlns='http://jabber.org/protocol/muc#owner'/> </iq>
如果'from'地址的 <user@host> 部分和房间所有者的纯JID不符, 服务必须 MUST 返回一个 <forbidden/> 错误给发送者:
例子 157. 服务禁止非所有者的访问配置
<iq from='darkcave@chat.shakespeare.lit' id='configures' to='wiccarocks@shakespeare.lit/laptop' type='error'> <query xmlns='http://jabber.org/protocol/muc#owner'/> <error type='auth'> <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq>
另外, 服务必须 MUST 以当前使用的选项组作为缺省值发送一个配置表单给房间所有者:
例子 158. 服务发送配置表单给所有者
<iq from='darkcave@chat.shakespeare.lit' id='config1' to='crone1@shakespeare.lit/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> Complete this form to make changes to the configuration of your room. </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'> <value>A Dark Cave</value> </field> <field label='Short Description of Room' type='text-single' var='muc#roomconfig_roomdesc'> <value>The place for all good witches!</value> </field> <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>